countdowntest.xml                                                                                   0000644 0001750 0001750 00000002251 11675237203 013152  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   <ladder><IO><item><name>I0:0/0</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/1</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/2</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/3</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/4</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/5</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/6</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/7</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/8</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/9</name><type>bool</type><description /><value>False</value></item><item><name>time</name><type>int</type><description /><value>100</value></item></IO><Rung><input><block><function>And</function><arguments><item>I0:0/0</item></arguments></block></input><output><block><function>CountDown</function><arguments><item>time</item><item>I0:0/1</item><item>I0:0/2</item></arguments></block></output></Rung></ladder>                                                                                                                                                                                                                                                                                                                                                       countuptest.xml                                                                                     0000644 0001750 0001750 00000002216 11675237203 012630  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   <ladder><IO><item><name>I0:0/0</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/1</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/2</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/3</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/4</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/5</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/6</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/7</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/8</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/9</name><type>bool</type><description /><value>False</value></item><item><name>cnt</name><type>int</type><description /><value>0</value></item></IO><Rung><input><block><function>And</function><arguments><item>I0:0/0</item></arguments></block></input><output><block><function>CountUp</function><arguments><item>cnt</item><item>I0:0/1</item></arguments></block></output></Rung></ladder>                                                                                                                                                                                                                                                                                                                                                                                  faults1.png                                                                                         0000644 0001750 0001750 00000057303 11703163603 011577  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   PNG

   IHDR       ~[   sRGB    gAMA  a   	pHYs    od  ^XIDATx^}	Uŕ}(4NDiD5q! K\ZmM2KF%DAlDZEeHc@ d4FGAю~?$٪n~uWS_U}Su&QT\
џ"5J%{ꪫ~x孫ss8Ygbud%l2=#R>'*݋	EhQ$A(2s~Rv P@~ن '%F(_Shr7rXď)0Ypx\iŧawǧ?[76{,fؖƌ>c㿜76~ش&]~/wI՟jLЀCQ|#8L|%·\ڈn+}Cl0te]T"<W+echDF4$[[`Ii_f/"lB#/i$VܞQ\bqQQQ|!pYp=LBa:R*~4La29 &7
Jgr.Щh87@1n]{?co|pE?iPRS+>+x- q_[|ww[
Kx"q3P1 \ޅ^=MTGfZNsn-w<~'쳿={־{Y 4nj AJvVzL9J(-)++-~	/)+-)).-J_򵥕&QRY(Da6q
$eH?C꧴]D<$0@QCL?x2455a&qD*	/m|!=cMB ˪nS.s+mma\,$ RIU<d
p͸qK04}A:l3d,YaÈin"9qps7E>s I
ꄁ0cJ24gƦB2h^5w`>o\i޷۷mƋo]	9L$
sg^,ʅotyx_<p=`?AsN{/#b+ A`@ R<K +[ݺ޽;\unD)*w-J=[4@nvh,Q)30首}D+Sx$ӳ.B4S(ԌSLfSpgΥNV:tw&A68Ds3"%DwSQV1lV3aDxgCTL"4qscYHGdb5P|I-(bc$lbw:c0d6JcgJ`Dդx
^м= >M_$̸Y
-ى܅@ppH9S\".n䓿u_Íywݺfd5=lCtig/Uk:]!JX&sv)\<R#RgCXI"1'+儸ݝF
fEQ;NxRC,wp.Gp-阬,q
\'\!+h>&mPOټJVd𺦴c]M]2jY2c?=ܵ|j-eLU?ŊcrAf8 JH\5a<ŏXs.^#W$u76z}e;e˖ǓԎy|鿷l<1p| |a>Wl_^Bb@dӘ9'?9o|هGC1~
F'Ȧ1]8;j@g}d0A/<qwls]y	Al`=&B~S1BwkyR\Hk/LƇJkn.ZEZ!#z0Ը?2eDrǲw&
߅,D\SZ8X<C(0*:][ɮ-XEseC	nlhccZbln<(E*qkyj@τ55^AdC&hAL`g,'^Q<۶a*AȤ%'5-_Bek0{|ՆV,	5ǝwlpǜ__D͉n=fCDH"AbCBܛ!!*ܐ\N3`ȴwp;qR˃h1ep=нW1zh2
p=z]1%֭݈/cHjN+PM~.c3_PBN\Z1ٝdB
8:%5p4GV~!!^#\$6oYDK0Kb,P96땆X])Skwx#7k	!}CU@
)S_JNsCˑRf$\Ίd0+5826,h'՞XL'}L}_1pa)C81.8p!Ϗ>''Bik'9cn'>C^1}t~8?k=?./Dpq|w?&[#(KsߞOq`?"S=y"G3
	@z<)BԇR ĂK!'!k̄FE h\'JԃفgHӌg @k(2꤬YH >&҈m)		$&?$D8 7Chla@+G\dnF*ǶN">;:R9{z*zID2[	[Qi;~
[4\nZ,)^z=>By{سg	cCDܻ-3:8c}>PTmoG&=k*D!#{7}.rA#˛'$ܻ_2gKұuX;>AQ+N&sO01  D4u쬢ce^[֓@Ix@ag?l.95pX@'~_7qdYR[4~gõvɅ!2R*>pd)/jvMv^E=tЅ¢oP
ZI^s~nU`6Sp0dA
ܳ#-_PEoUS} 8GĐZ`HifNgo=qpwAt)O$(f  wu]w䝷q,y%Ӯd#T/s>xK'~7~>oB~?`BpMpAQtestri40>i&e3~rL; cϷ.,$ ĵNyPX&MCm
}I(*+xGo9/ַQ}/3N"%/7t\+.;	XV=FnIWM1'_i2k/%J{dC;z 7<ӧO+eHH)wl늉7ПqN^N~cȐ9|u'
I8#AN 	%p\{Ӄ_}8F'Fq!E+~:
?kE?g	WEE)Ql$wFܽXwV,\مаB\4~IL!4'(tm([85	BV8fTF#(Wt<2'<IZ(az|ӣ>8FtΪ̋9I(bDr?qh+R)!_X	L1}>Ī>t}r&
cpyG=Lc.iɰLqZ#7dߢi)h[f3:Z3lls`VvRP-U:bN@ TCh4JQY8\$z{	s:W,F܃
#ڙб=/o)JҾ}pZȠA14_h]<kr5Nni3:O
׷q&5i/L`CXk&@;Lt<O('#'̅?lG)}ȡtPi:dȚ[D, v.ibaqF4qbvhI](e]%53ɀ!6tfJ|cms+9kj\~e,TC[)ƠZ2bXlKXʖn;2ZfC@ڏo:H1o)'EbyCD >[>?bghb1!*1 ?T@Ykn@>7~ 5/+b 0 nWuMg0sϻLsXwu˛kΫn^!So/m?#>`h8cdfEpߧZrg[D<.C2&A~Z<p6FPƉ\`8x [e(, tRfJ\(bðHONݵu5\̖brClH>zlnHLc`O}B^鉙Ba>DƁgW)%Re"@/iᚼ< ;1!h)+D/>G7V"<)9`50"^,+Qu/M(+٭G7GD^ܣף;3r-GwMLH{p,z	݊zv+QN,-*+(9~tȒ;Gْ}^uӯGg0[M'x9]pm_]QT{Ӽ:){Ww4qP3(sPi?wXO^QL/^bG{?~)a^0a_Eg!1%{ɪfPY7ÀP$2+uŻ|0pwlat"kBSH`(+GWq:yB>D`o1!N'X	
Y0.=Xemy8xt1PMYq'M⋧^[ɧH^V)v,KL$/W{N{hJ;x%6p|&A3G]3mʟiUX; +r!An?TZC9wwCRa-ph.j:j#f}'N.aLd: AMI@&4T=eE-&㜌'*"
4~EfsQIe$)8sI\6&nGfs[;:hR} T($ĤP-Z%t8bYU@~pl}CL.n1 obp[$.?J}}5"P,*Igq313~7y~DtCFhQ<F_nV#SKb;:X z@}&HXuy0OX,-gn=JˊK˚,Fgwnݽ(ݺ7X֣[˺RYҝmnx{iكNHOΒ28Jz\r.)Wq^%Y^Ƴ">g>C&ؐ	AE1^E{ApBYTnY>E,.B6zX-0C"mg9v|5LS:l}:(9߰^.\h#=ie91@*tp,?mi@wxxOS_<pX4G.8e'Q0f@q4 Bk&|`'õtm|aKѱ4 o\py6j2̔mAn؁p/\, N1skapHDMƆб~=<r@Rpp5c7#iQn>*
xW
ٽGO	GOA?VOH'E#yFyb4
O㔕v.β>%p./lջw>p!.w,S'$T2ȹ!O$R(r{|sz.ՓAO$~1Fb=-e;hj^b8iS̿I}"Cfqb˖6:oU$" eBTB9h5lrCj?~|> s6g>Z#/ҘAcnTuBR\xԏÄt&Hj3ǃ(,V#	뀆k>$g@K1)0FS
RUld7߽EpyDdpYH6;;)gJ7b3e}4
eiȮbH]gPͰ55k~/~A= q' =0x5%'>A,8̊b]x[i.ջ:^e{uݫCz	l|p)?=!σ(iK2ğwٽOOխߠAGEDq%oy] i:exۼdn΍WͿ){G;iU|_Iߝ{oί}?az1."KHB^A!#?dJL@B:V2Egh.LZQѿc;\;	
6f+$IbHZ#	7QOc81M#E@qY;mq6A\HҤ?{LіH*q~lqqH(>gcKVP&?TđB1\y}ܵqZgO	38/+F(2 A*d]-\K/D- 5bk.aa_o
bY_*~6P>2 `zz%em;7o۶4elS.ܢ~r\\X;c+msn1{@yӧNONFiU$zÄ'ך<eK-XMBd{Jp"J;:?<AS\S}Ç.CvUW!<!2Hcl DGQa(ܲ2k9rO6J!MH4À~0̍*b@EԔ
:ITK6".ѐa<	Dnh[Z-$-;Ц7ahKWl%q	o/3*DEO?ɛo)^9 8A4N&/	W948- pw3:p.@
agzvׯbnov͙^<?];w>>3|)gt;{я+~3G/[$J͹H롱fbrT,t'o&J."LҲx.6#Ռ橼R|0ݰ9J&SǥAη1-O	R	?ȃ kXReI74egǻQFE%\¶2q,7٢[mĵvj0h\-ZQnrCRa:<~HX1Ѣ-!#ЖheCQX(<1<EetfBٲ!eC|Ԡ'|3kdXڳ:e;L7;lm4h/;IWI?eP%evqǂ{EJKQ-?2(컈iI:@lJziP6}	!LNV"iHdh,h̔}l~'58+)v	Ʊ^mFB0Q=y9~~|ӛ\*13k.O1B|bʓF.gcXǶru-j 5=-.1_6f|FݐG{2ݐd6Z1	c"!&"Xt0Zp1oNZSGPdӢfG8bdb(oɤ6󠙝53G,/0N"Ke.Uxvl{}	RmC1?Ppq#Cq,we0$;?WHZ,C	i(׊B/l\V7z@Y7,'- &-"W&QT,^TqI(q7H_2'ht`_Ekг~lb+;ׅ9(Ġ}ʷLdZʈ<q2JRd[k9֋Eԝ66+ￎ"q˽7F!1B=خ6]/y2}ױj1mGG89	d)j8lTRlmQ]2t"XhU_~E2]c`u8-_Aa;iZz"i-+h8
?^$ÑQC3 v?hr<Sz<#L3Db]٥H*M^I,]JP ?xF|ׇW$g <,wMjaJ&D>ehGPa1Y'K}Ih'!jK1Xѡab2fimKV$&kQ=%/@]NO3O\,Yqa8>.iAPZl2m0Ӻ3ԙBIcyjC.̋;Md~t" @HHD|"PlKGiq-΅N4~`u$;3/N|A-ȃ쐦^1I-g Ƥ
ߵ$ˀ<&+""o#ȃ$Ȱ3zrQíe]$]B<#
Q4#V!M}dE2Ў@dSdlhlH=ŨpY6s4S5"BGfY	CZLl,":HѩLNqĲKK@L[pˊH`6N	nr,?I+V^d~!
|_GG"N%ElժĘ`*HMKf^*'Hv.RO38#b̐>,)cP%Y}CߔptL2%d,&+eM+e;CNOfÀ=`!!jd-XRƎz쿅b{"0LcU1N;20	A8\Mq⥨.d[\dl#萡:*;vls=PYTy& H{41~b0(<`f$ bb!~lʃ7@딽yn;نEnzP+ieMș;fgaҿ.Oݐv*0>{rl;P&LB<-ME?fup5Ǡ~fYU_aq	/̕ƴ6w{tj߹*MJ[<S
yI#:`oQ
Ls4B]rcpJ3-Nh'Bi%SWNʜ'#)&*, boeh9Uď"OFPSm,)4ntBl3Mu34_
;=T@4rDXvRT'0XG-c@%ȅhbΠd$3Q0<Xeִ	yxxi`ܹkȫ/p"	t>jVɐ"J} v0'Y_xhX޼YTAJ4&!Pj]%S*Ux}	i+lfmAwC3Ā6f(y`øqKe97/m#?\vBbYwmI0e29s<,<K·2!#Z}YؑGL$B.BBGNƤKoi+hS:`IH>^쏲@7'FNb?D$t]}:01#CYZ9O~b~`j SiQA|/,aiԉSq.hB􏑊y$$uL2.~HVH,23~&PG\8<lt@9QRbLS_Xm9343$ieԚk:q9(pTZ)F&I$ZN1I#V
n8-uJȰb5~u԰~vw
=giX =bd9R269i˨;L3:{&|cZb`mdU᜖utF'tkeYvE@hc.KKJwy۝w1swϯiCqTPCӟ܊G`sǭd̃SUVbg"_q~;acozsWa=E@Mz胏<Wb;^5{UU;{^("Pv-2
3_fB<SsyW;{V@*.	UIӁ={vȕk];56!1ĵIJ!Fo"N8ukmwڜe
N$J	jMQDu`ۄY/QTbk9 pyξ Ҳzhsݷv鿿Vx[l%t+!Cn|w߻r}/<U/^J3WemIaW,zI")2LN_zzk}]C&8>܎O3s#ϝQhS'̶G})4./E*EZM{K!iٰve*>?c7Q-jCTD<5k~럸N4M*x+n8HkmzǷ2JVխysƧ~7hޅN;>s1뽪QAkVA[UhIߵ!=}Ł7zȹވ~Z7l]0Sm"$"	F{fc+O9;]\eWCH拝T2wHEv=WƜ~S#FNN9DzFyv猧@;1nڪ3j7XV˧{ϳRyG&KUQŲE2|ʯY3He*YSe
~3U^+rē+E#F%V=&GxjGo6hm@?ÄҼar̀9эOǻ^I512oɘ̽%&+ȵKtesظ歗ex\DqO!M(ewV<*kw?O1MZ"¤[v?Z5hٜyXWYS|빧_pŪQj?,[+1 H
'f~.r#NrSxƶ-ͽ4<ҩ0:zׯn}քv";N^7Z<Vx701rDs_ꡄm5i̏?dpMmHsEoع[g>+qm+͑Y50v1cnZS`e_e(-eP^+)rKu3FE Y+sRE8G?P2%2e4)Mukpֽ-1NȈ5i7~ۗ/Vne:pyc/۹{Mǥvӓƽ>kiˌ	FV=E@+DIa#3]>NaQӿlޖ'z9wXΪB@ȬM3MKl!O[ _ ߤ)ӟ^⸹O`Ӡ[c|O/vM㖣ӿqܱ"AY"O#IRL^qK?m7s)-V .HqQ+^N~mڝWKιEH[H~tݥ<$#$T^DBjP8v<?{drC+,x7G_qY[{OGW!j̮QX^\bǳ;kT6b=xFܼ<|jy)6OL?GoՋ,p$gɇ72
d";[#	_T4m?<qxDUbGp@jIw۩CA6gnB<ug>4=1m8\[FiurU\u~8Z2<0ifR(q!FffDÊ/ Mt<W 	G'T!j._C;X$嘆wυIm{s{㝊k<"3]6p?ЊGe&X;*֛UTݧ\ȠCPxN??Hۏ'y,w<py/]뫔sT@E`+9eg qN@bfRr
7x]>=E@H|\ Gn>s>krƮWAE@+ydc5O^;_R\Ʈ]Ny[y;nB"(9@G=bc΋Lru~kE=w޹g3« "dU+_ud~'i=;xYCPE3D^dvoEh5zٕ>xmuZ"(@`ɐ_汕b/]|͏tF">U욇" 	[k~VirR*"(!@Ѝ~3b GF4?[P@sBwxA^`@:ԉ.Ӫ*"d .V1Q|}б3U*@A i9|A$F3QvqiSTP2C'ϟ'aU(]	#qAVp;O?#GUT5mzF>;ck+wftTLk	&,\]̡'pB6f̘)(Z
TK7׬ͯ\^2o/ ;?{Nzʷ1"ynpuuC Ãy
`n.xBaÆ_|x0wD d𷽋6mZ߾}Gى<vͯLX}|o_}G)>y<A((Zc-q6!FJb̃zʅ^`p[<s5;v͆_?~p?E3%pFvω"o8dP^ѐTP6" K())6v`qqA>RhH䊀"Zig^]#DD}^1.tP!VX?@,ʣ><ƣޱM0Ak"s@w]H05Yx`^)v<jca^4{Y?-WXϤ L1	9#;d:|cmw()EU%uUzM43NuL.v	7Sz3S,-.*qE-C,;ҴS.}b[ _YY)<b VcӠm#`Qy*gW&*jj!+M]XL6C6Qnl&]].7y]$2s>"e@wet.[D(Xf$@5nU͏o9
]˛ڹDok3珎\	fJUO#Xԟ'<I|1't-U;0O!O{SMa+MMZhtA~|Q|/"}9ׯiRy.urS{MčcE>$I:B.XDt_NbA*:F.CsbRKX]4.	8~UQs]3k{RjIccպؐdc/V5rv,r")4
І2c=A#:ZYfz`"ȥǚ-+6nF(Z~Xey2$!csK^DxS8{jp[G]/Q7FnPPI̓cLtkYaݕ9 1#[I'!uiR7o ;1bCY«6A/dr=-<=AQWiG4nHÚFE yr#$!csKQDhUkD,Ǽ9-y Gb4,%#[*P/>)hLю6;Xi?RbF}Kw}kvq	WB]R2\\5/b{⸳[P;򍆤]kޚccDx1vTYAI*G_q=XR"ff6J?i1[+d%.&-s\7"yR'Mpfvh)!÷T	V !c}ܝį\hQxnH%TJPZw7~nE>oFB6V-X_Le}:ʢNAsQ[B6V_t
0zwF6XþUJEc1|M
J&DEszJ}2>dEDˤ6<tAqUv>+bd>&EF}*?Xjsv'u`&BLÎ̮><d&a+d?ǅL7ޫΠ1K2HRTcaFsjF6谉o,\t^;.@Tah^4h׍Ƌ-YQ2;q0ض,f:x'>mu[iD1LvΘQMڒ|ľTG,}X?ƿڬGi|ݺ-e9-Q}0^[[uu}4e[ٴF}Z.[01'h8 ıLfk)-};	a^kEXn_~?z~1;se4;E@h0t=G$-3F.K<<IkZi@Нn'Γ
tՔ*"{u29̙32]r)E_:kTZ]6v3)a]M5/E@%PC}O @~1hjWrInEPl! ,GGd2lX3T9~N1/N36E0Cm|%4-_<ٌչiխ;>/mۺu	>tE+hyXawlLd 7rJl2A:KunɝW|yCÃ?EEsgxȃ[nZ;n1ʃŃzt:O^~}ٲhX^B(z^ݜnr%	81ʃZ'Z"Y8<Dxp~_c %(@"+}+l2uCfꋫ/$v}{t6>O_v1
f<4L it	DZEp`cP?n<u 1՗\>9
lXl*{RD@X}An;p 7_s4\>@*K0f&P|GOhI{<A'zDVS;,Z?E@(Lh@!XwhB@@MN&D.޼yՓ2K.2| MWx ,&t!nXiB}?`>rmDA˃<{ˁ/<+^ӦMWav-(3߰aCj w2Cadxl? :qT/>)k9|_<'IAM)@LriAڅ.E*". ;/Yrl"б7R 2ݏcFKSB xX.f 𡬣4RwPZ"( ۻ>RѾ>pd
E)"С.Ȍ%fqaJՅ[?E;pTtE@Y. ~	8[Z_E@H |u_;OB(w,އIT&M0^ X{<'ri/TE !ۗ_~n$wmwğ9I[8i81%j0r ~*7c7_ݍ]?e4^Iư+!uch9R-CP@#dA;_lfSPn܀G/JqzsF<KF!cR̭:I"@CjU7o'TQa3iJt@TE@ E6D`-zO@ਥ7n|N`Ds1ǞCcM@ijQHK*SE͓w/[9GW1E },ׅ担-Ev,+yx
إ#{n&@4ny▱@!M3IHRvu3G<[juɃ9Knkx7ybX!a.kOyj;OsRE  П'5&4edk')1_E4sXu$WaI$:<kt"=4	&(Ov%H܃3I\JRD h0Ш%Z)E@(dxĘfL㰐aҺ+@"(/(_W^"PppV2ByR E >Wt. f[yKf2skȪm`Mt]7 L8_l͘3)\1Te,Y,WzNBU
؅WL
n7	ú:֎N튘BU(]iF d9kjrJe,Tfy^α*s"雯bz&%&&H<Icd{|[XwΩ>GЖ3%Z:[W`=X@
LkVZװ3X8[/UޠxWYYov
HBnMxY!$fo߻P1?lkq"!YPׇ-c~B$mVTݺ2#[L/yA]RNe 4X9iPvZ5BNMkZ&n/z4}SQ3oV IFXF/fEVn ~V(YIVA4x0޼ Ub0Q[ј٪STԛw[1E~1Fpv}vJkVDVxpݸffo&'0Fz$9`tC?k]75BC_?{o9<ȓ2eӘ0DK9,ݺ2nԻfDQ(ae>qHٲ?cw(ycH=lEjE@0\1LbL/9{nLv)g	N>_|qadvL'E8vإJ4'0yTCoݷo_^zikիWCcյ:M+'O՚om-Ẩ|쑟+_eXW狃kyfa%\ݺp".H"Q'onET2E@PZ:ςى&=m"hBE@P:4͌_,S]NUWEU11 A)bi"t fApYV	xiSNCmo	yx]PyZ!`o?	~̃||&Aw๴nk]0aBI4~,nF;"E̽'X#3+ojqFySyP[NP
Pz:iM7>TXTT+>\YϸAX\ ͣTF`Æ	 @ţF|Qgҙ7 Z}_((6ĬYA,[v8h'pBଛ;</#Ϫ4/n}Zs?؉<$*ḳ =ay555΃͛=yUB//<@SM7NA"9qT` X=T!Kz
κy.4e+_
Z5#E@Pr&9uԼ%W	("hZgB;MLʃفYsQ\E,D*V}?RBK
sT.E@oՑAc+	ffBPrLZ8ςp&Ud.gTPS0\ l&ps [0}?
jies_B`D꺙\k6GP݉:dmf=E@c"<(zRaw "  M{Ŋ"(@?萠`.ʦ(mF>x}80OOgL2$U
RdJ~05L+P7VW7W^kzFG`H&q	'k*2I	13V	$bLO*'NV=
^US(@"Z$,CkIϨ8%Bz-w,NE:Z"MeA_HU3uXuyRWWb,=/HѨӯX|'_;x%-V59Z=E7- j,am#o
x5
`kA 03n"5^6wlk4a5S]".A2QAӣ0L*a`?jmspڍu|FaMFƭT

)UydMmRP5fe\7_hq%'#fռ7	&FmAC6nN0,TI0@YaėLD8<UUVgV"P0Xp{T5^d@CJI*|du`7Y glheSE͓u8dMM$ith"2c?iP̀M'C;B-1E@B!aZaP@@uTX@+<j|P E IPE@P,?O>}­so1c	!woݫW;fuؗ]hc]^K"P^^{CrCk]KcԜp	/b]]]fP_喺Uw\<*0f̘`@ED<-J0aB yVIɴi<خ k)py!Ū-lذ-7Ϟ9dv1Pi)sxB-&XzuN yV}@P.@t4
(@}U	eVPr
 9:*"tʃ (@{uZq.4ʠ(@@T*l#,Ѱ]SYjE@PRͥK曝M_Oxn7h]fn$$֡ %N7{y~L[_K߫*b|xck_oI,+<n܀G/J+rzsF"=KF!cR̭:I"BZKߞnU$I4s_k{dm[^4QKoJBx#c=;G3ƚٮtUE#M/i%h{u`0
XXV`PE@ho-gdoܖL+l9B<r1Rcb&"8
,5a!]G`X&X1~8s!t_;xJ|H\Yqz#l063%`WG.EU3n0MP@+GƳDgsx~$Aڍ$BkLE@P@x0h"t
I*@. `.ʠ(@xj3[CV@@@]*Lz#w	Ԭm!e}#<\gHTY{e7}!5JJ~T5Z, Wz'[vELR.@"#xx¡b+D`"Xʔq]wEǪtmȊlM|3\Q$&H<I)A_ {2[`\wfԼD`c|yc Yw1װ3X8[/Uޠx.YYov
T7on<S!$fo߻򵩮Ɖ<dR~vފf[W;HY*)hԻf%)a- hrJ%!`5kbǭPL=n"mZcbvg=PѼME͔jg#4ncU1>+fܭ"
jrE wHkVg!17o4FpG;q2D;nEcv*5]`(Dwg֕J"z׬Twq͂͢n߼MN`ƍ>&1;n%Ir6:~]f݌KÃh\]z)Cn]Yh=B`R.F>$D8M}o`x-Sh̖ko(2ف7V>_ـö\dHO:;#Lusf͘1s΄իWwbY74.&@j¯QDcǎ]Dy@54pA}]
;x0r/(//ġB]B۩W8Ey555'pke;ydWknn96oˢ>_6%tEKݺ:-NPD c*\")Y!";~0)@^ `^4VBPڀ6l$<{)拇چJiwxSHg貽Qʹ72,NP(e_7 `V@I'XmJdGzҥ^WZ?ohkE 3OMaWʩ(@躙!"g躙<kP"d̓>|nfάI,5+ڐ@I &m=<O_>ME I|
aXLt,	ZuT N9L
cyvk\Sy04Nbn@n<i&x:]}Pk?V,"
A3=a---b5+E@Pc33vml"tu:l?ʯ(@~@1j+@B Z
tSiE +$YQ3Q.@źBnR]P2D i!]P<qn6U+( QE Z:_ͪUPQgVC@y0Tk(!řᥱE ?pMX}P'󣡵"
K&("P"BZE ylv"8(jwPBG@xS<5GhC@/.6+@/(@|1z("Pb%,kE@`tX{"
2_\(=@(ItŌE@sL}$u$ϻVO(LM֊@!"L}7hEEx0o8^B秂(@ dXib"DQqɦ_>,H܌Y^W{9g.GM(@n"տuޭ7̾يW8TRE<?n|g~qRhI"?vO8a=B K/4Jk|7ԧdn2/~[JFVt@RTFn)gÂ4]RV<LmNhfPL-+b۶o%MV<ML頤7T
I98W@og7V~k_ln5?W__bXA"Pz#H'5ߵnLŶ);ӚƵLl0b{om-F_JP[-}VZt8pm){z@Z@$XKUBVUp3hD.nEEEvh[KG7x\`THV4{V'BʉvQiEN(=
ef)2b
lqY::& 'C#zaJXX}`Ǩy 	=N^~=`?y>x~paU(ߨi'n]_o{$lӥ4('PNkekMyVP<kQũrD#͖Jt;7rC
20c$pJ֛~s1|xv?[+nk92=?ESKIHARpfױMضdǶEJ$)Vx)k{ ʴA3c?}-8Ji+-ȥa<,N٢äZ=K?}{>5FsqIiyyW^yyIFB]E2GAef3z1N'N[eu5it6Af*8;~G`(JXɜ/*SlUm{4H0}ܪ5"(]M]Y?,kzT    IENDB`                                                                                                                                                                                                                                                                                                                             faults2.png                                                                                         0000644 0001750 0001750 00000033536 11703165233 011603  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   PNG

   IHDR  
     x&   sRGB    gAMA  a   	pHYs    od  6IDATx^}	Օޫ}QBeғ!j7F%$jNhQ2ӃIfF%i!BN:Z\&C`HhT֢ovoy[QPEq9箩͛7{?
9*9&M<yr___OOO' T>|xNK:ncN~JfJ@?(U(H\U\4SdՋZf|ܶ']36tS,y>rpͿy{iV^GVYbu]pXyPnHj@,|BHR0gŰP_% $~D)qt)av\j*ܮ*[
sspa$<#CBg<gv|=")Y'R'$(S$i%)U_/^wK|Z@Hzc_;\l($T:_JS%@Hg?F *+凹SY2*ġ6Y8~Ȑ@<5Ĳ"LyE.Uɟh%:[E;d*
ȵxbV^Qf
2QTKY*b)(JB9_BBPW b>P,"~&Opy"'| 7r"<C&pKȽC8l|{~1VàA`A`BxN3
\<ՒA x0  K|K 'cPQaԺ
0tBQΎU&?+`(0qb 5#8Ԋk&ATRJķX+|>+bPOL@ȁ/Ec
|KҡXu(\ 
F\.ۦ0PApEA_APiA"΁#(|+)
k$ɟzz7Q84QZbR|%m}$K4`i*)O/DDMmQ˲+ߣSuYahMn޷?x~AX.PTJJR)  8U/oW!zǤ~rɤV2PVpU0g|O!mf¤`'
H
ʹg-O!یPF!=b)4(
TĂ':i=2bV&|I("l7q3
\bب*%V[,>Uam4c4]!1*O1$&ڈس'rFH|\!-e|/-~Cpp' ߿DI F9PI%E4k(_P 4lEKc[qnuTKE˦,C@{)@c"Ƶb52"=eS>q(E0BCȟL,'I@maTXmF\ćKrbY)+䲹P8¡xH@؀,)\a@ȏOk,Ց@ʖhc{J4|ME-ˇ(T -䋓;A>QVA?
ܒ7ocCm+DEn1eW$Wy(؎߇ ʇQ׏\jT*XvCHBOU[l`Ob>mSC |wO류&!Cΐ?|%B\D4n 0NN:mjkFY/R}V4^b+)+)
ז-#J`eyX,g
T/RPU":7[`)F"B\ozs'?N~#F!,*L@l4>2]B	<aHN"<R\t/
)~wШT0ΝodKWv7Ʒ}rJ|۞ŗ'="}ui^)w|㽓鵖WzT:2Yl"=9v5~_L6!2]E"X"kє,D!a9K>5![K9HpX=5+>8[DZ¸/oUqg]'`rǵrK| =hCP!<b_y_|//&,!p,t)HA7n)柀]G_{ۃݟ24㜮KZ#P%fɀSc!b=ʞ=r(zEn0a7rsϒ{Sx #ݫe,Ք~"6jQ&4Z/Zԩe&C}MOa/W2ΡZNFL,N|P	Hh&S"h-S Ouwx*EK`_: qbOLZ(ƈ".B=XsYVzEՀ1
FdXp틅ިAȾH:l(LPL#ueZ6/wS@*EU%VCI!,l|cF1W
~ۋm14O9$IM!_6O.&lwC	VcL}⿝~O8z3Go:ٷgɏޤr[?yOĴDjpt}71PV"7-Z(髰A韴dc1%pԅ0\mBٮ0nŵjD6MCc#%jKw:2m=ٙJwm]AGW++#pg_]>|WI0-6!(ʂ
B`%\U`\=.=_;~7tٝNODP?s&ݲwԥ7={S_zom7JoG~sׯ^셀$"Hq+)LPSE
o,aRycE]+%A_XɴFXQ0kt:dgEhUmEt[Z;Zz2]=Iwtg:]]TOG#N
]fg,~;DP4Ls OЉ%rAK;0[,U<>hPa{={{6iuyZǊFIkXU43F8EpoM#H)G[YzTS((}:wHBuȫ,G$t+&p̻xL"جIL56qbKOOeB/t_oKLτt߄	}Ao_K_O'(|g ɼ	9@n'LE@YP"C&4IЏbVQ"E.!on㫿|fP |:|eqjV Vp@DtU+`g7+DeH+i0,T v)eY2P4``-֜&H d?A5XU`xLI24!db_w)m&B 0Nh7m"-'f	SQr;CK %BP:ᴾ+)'!xD$ɦζqV *lyD ?]	V"xob<{V;~`GK[;ibeJ$!
lBJiʊFs.r"IRWIV*-Q%Z5꺙JrPUl#f\ް|!XJKf2hi!x}ŗvuNގ޶޾>mA5-S%D~[(̧[J&Nrtì+ީ{x=ұK<P=x^-qo_Yo|'?+NZmx4o]}tޗzÿ{'W*i%>3@`
4 4,%/kD8mm<06l\/a}4L4-6|Ղ&WLoMh54"aqR)?嫢ŭގL*wOs<8L^!ZڑFU0Ҷ?qs1hV0qe>,ȅWPs@^3SRb*RZ5TRd\	y,10'
b;kD3-EWyVX	:>Qfʚ*ca"B"Nb^$VX_!sX˫<a.T* LyB{ݥyxՏn;(< ,r;ۮJ^d欞u_]ݟr%Â}tqnXJCFx㡕H)Ĩ`@Op IJl-0>iV5M4K2VBm`_\0!`#$6KCش5`+9%H2צב9/-L#uo0γ	x4e /TFVCːS˓SG-|Lci%gQZ14qR"ܖd0h_Ŕ(V4tTQQ a \UuEc`!5<fLO*I36D`.c`IZԋ@|Ρ,'\B:D!"=8᪂rPdٚAM[mFABqv#CR&s6PbJ:ӯE*0J?W,>b#[v]fUh:xj,44$A$N3ه&Y'g0@_9%\F?gMbq7]"oOK!ID*iVEIEdm`XIXTh?KHHrPL$LDck^@f!QxF+QPlXLc7V˴xj	dZF(Q* (!(<% ?FL*-l*`~?Z\@g7i	64ͧwTZxEJ"TOHd*1)[UlEj[xm1TU":)RԘKc#WARnMH0<尌ZJuĪCt!I(w,ek^JFMMW%jӒMHmPYel~(CXbȺD'ZdhR(Ͷ$WS]wQj8K$VlLjJΦ1pI!#
ި4Ĳ+H(~DBm3ezBpCyCǰĨDm~XҞoeȔKK$ya(*hAO,4BLd #p"TFj&CEXqDK@3AeLʦ<bЋ<T%S@K+  Y""VJw/j4J-VJCV,\Wͣ<"!K"k먐eGٰ3VIT#_mHk>1)<qV f4=SR 2rj7?pfW%b!DL29܈J`_b#KAoHomBh$Ԥjߐ	q^_U= {[៎HsTs5>d#*<k;S6_Oρ-_Z_yQ UkYs@58^怂݁r{"ױ{9p"8q"<8WDz{#Ła1R\ 8ߨr@#X۸ Ǹz倇3ۖ%u	p>bSx<ʦv#/k͓q<F.7es88G7N3֒-T"n-5q"F޽j1u1EA[U^#^ppMuWdlyxuu8	iCdZ&.vq;f,5j#JGR/d9So>|L ?jP`Y;2ms. m%(m;n3uU
`7br!\asFɵ9#!c;O3h)\9θc8}'S4vz
</zˬ=ٯ5?߯09p˗wCcw+ۨku[t8fÏ{ra8<nr=r	G)$j0p?q~g|{ͪoss`pi[z>SN &~'Y,\STkxk~V;fo /&hd,[=X{5}2}'r's k=< E/> %sK>j]nxC/7IHX#z(ۛ7qKn6~r_~]7*D$SGv""&zxAV]/1Ղ2K7U䌻:yT0U?xLoV*-|jǮ1qMTlX"'2y]s"i k۵੅M49(fP.Ƹ^Y08F"ٴq4e<^~`a~DkTfnk`EAJ}hJOIzm-"n?&غdzZ޴aMwEZ<rY<p4Pc%1b"H7CUi& 2%qCb7` ۵VspbEg\5j!C:Av͕^$t;dzZ*s%U6Ft%37qxbJ!Уk֙o;.Y<NfViz"łg@,WķnZ8i!@}͘M)V%;cPU~	ѵhvl#UTWsfE8N~I'*;x+>fJCjx.{Xq_JU|hk\O-DQ+ҤUmU'F VOc{zW+ZM@ǂ>,*D^#C	j/]P5Tm1]@p]j"N8&GcW'zq[pհvOқ@W~u[DU~Jy4:\:?,#UQXs6+soDi7QaGΞX*T<s%H4[Y'Y3LkICō<ӍAV~MՌQ~%|,\蘆lpH*0PP>uc$=*ֱ[J5VD{ȹ=#GDcU@3E{Tچh>]seqD?p9(Cc:l FY&yhX=qL~
"k)pŹ\uB	[}=t^;ڬ]6cCypϕRWs+9@`xM˾oqڵڂ_q6ոr	eA#{ߐB	A&ZSC&"%[M:	4A7)ZF Dmk7jV
cPo$s ]v*ihds`s6Ý`ެ1O@+s%<6gO18Pu+BoWihAvCiҢ<ݫg
uDFCJ֥g,Ok O͸Gh1mPkz$q iBw?8Ɂ]Ld'QD:vQ.y怵CcWax .9":r[8ecWB	Q(+G%rEEEaQaemVe=:\ifC.Fhǅ2'h xxlxp\yx8΁xml1-^3ɓ.`%hl#w%uʕ1\uXy.&o!D(6p's |ϕ	ρPohY^_Nr &
xl8)hဖ*Âث/1r !]\8Olh#^Q)K`ICi	ў%e㮷:pΉ<q:"JxG:ICq?]uq~5s_ixe3V.uz]qrյGȸ]oa9/'2@~5gëW-	K+/(r@9_jΕJd,+3n+sU<[VZ~`/w9`!]prh(aQ^.ôA۵G:!]:h\/t]@v͸W~R8鉓J 8Qq!q|2;iQ(y|8M4w"J#
z̿wivy CW	?bٔQ*B&O@/\.\0
2=<ר/
baph ;884x,;4Ȏ8/ހOj5yz]@>+G?:a&O<0QN+pYVρMh
jeԜ9Wȓ.<|@guHQorSr98r@C())Apd=#0?\sxy?̝ ~yP860pt` >!WAX[8&ܠX,@:xz8p^<phH884~H6;ĳ`Ԝ& zJE <ϼr5R|5Rx+@<< Rb! joΣ)WH8qe;ұ)"hS<\ ϰ}BhT
 W&Τ- 7GK<<* )詒4B#Hf dZ[ tyyiU*Gi϶(d*x^\kTB+%㵇8ID d\!H `]O SGsF 4=Bx@@K $N\Cˊ	u[Ӂ=%pV"\
 ;vsHh䡣"OD+ Hky`to'k/4.q]iW2d+Z&e.IU8@&s@x&l"vCzqs]Wڃ`?J8p<A6ӴUAp;G'5yڌ\E[2gaA/lp<NI,"yoj\bg\v0pI6\q-=Bx;	ap4
3p.	|tsCrCkdʃ=}I{Cxik/3qLA*}
;
\)/AU\s's0Jh.?=ڙb=8AYZ<PTu꒩V9x +͠ךjV܅!Ӛɴ]ws	⊴wwtut(k8SEy!'=njmjjo q~y U{]=B:;;;ڻqS[8bUq-OhWɛJllo}p\^\#z()W]N#0 mpM6<{(t8yvILZx6e|ȸŁHރB<Ws9z5AÂ4&*2Gs6jRAIxٴeK1O3YlUq#73q3PzwU3ך\-{yЮAhC_.iQO瀆g[6pGsC	%e.qΕUQzƺlŐC֜)OpY<`9~eGtzyŁXx4;~yVN%n9. 8K\s/$A	{[)zy,C5TxJx.\=gX2Z8w?[h֕sE!N#z3vfNnvH6<dWᩴz:ttvcՂZ/B{.k;`%mw.nɴ!Ɠ9@Ӧ];qC=8Ɂ`\bZYIс;N%NDӶ%/#>
l*ziQqxރN.'6ޡ:u	|?㒧Uքv.+"윸!OHXtÁ
X?9tUr8["roF{Tyћt{,ރY#CZ
֯tYV]Ch[] CNñNhNr0n>z`@%xᰘI=lF[1Tʹ ,G&<nr Cpy敂`9O]s7Ueڠfc/JxvZ
G?\7J bZR܁Z'&nS(b=XE--m0
Gvj,մA>ʟxx٘2r' :`_M=ƕtfOgWOWwogw/Z~90mu^!ηpp3NX3aAqt>qY@>	dZee#=h{,:w{Z+99WYi6aΉ'`s'Ŷ&.3"=xIh]ު_q iFc2m/<<99<j<s<@|oA͌ay&y8Y0x=Ov|ul ti*z5޾*#Ut#B{aA/9=T=<w<<dbsvԯ@ٵpBGρ{NSg޶mۏ_${{gv=/ٌ'_<UNrd֜e˖}eyo]~Iz]%gٲ_Ϣ#RO}/ÂHxM1{zyxn_Ë@Uxxxn)Iby99=߃)=v=k<<Xs6tbl	wKsH8ՇI'8<ݯ9 !=BbTrOdRIkW""|0aIOzʕR͆I%˖Mq0j>}TxtiOc޽'bR{nAO]1f1eAxȞB7l0ew߽^},j++q|Le@hAI\@|\[Psy>C$@uX{Qp R`vItC~9{<,í-|,WVOWOdx"/e9
=6Xa^~lY2k/^5w^ӈИGgGW8W߷vѺ͋2'.~tea[`@&Ɖz')ݫoY:cԏ("=hx0:cׅ}w?~ۢy|Lsv-gIqo8NeJ%6$H41$bJ(d]A];`mK]tR-N@	b)sWnmylhTٙtQ!'EtP|>y5Yn#～W+*^#Z|XyRs-
H	5_,R<V{4mzڛLgBHi7tx鴊/,X9l1^V"dkPS߱h|-`*,TomƏ
az>ݫWCXe~.5uڌ d	{ÞTB^Pݍ:U0^% Ps?vh"ݲsF-!Ԩ`Iq%Pǧ7pUh9TRxJQ]=`Bvў>{˖^iSIC\+4=
|c~X}3^cI=^s[٣c,_Á	\k2V8 u<90m?ٝ,,Z6@?>V8w{l֎nե߹l˿I{qgʸ]Z
~+S	cي{<?V6axpA["|kS{KV)|mMY{`?'Q{x܍𤋮^&Ybn8B9
:CB+?1!Mq xr9P|m^{L?e=cD𘎊R.
B 䲹P6;r	W\qŜ99O^x'w'u[zEn7q5*ɴnq5F=?znLPv:7RǑw((IH'~E]ͼA	::J|\P Ͼ}ᥭdօm@{̞=}_#Y#ƌ<;k8a
=Yoyԉ)(ME]oLf3_ؗ&hQCƏ#iCՍ@/0NGVD(NI, bu \"oHుyo:}\6s9H Z·w]q|'f-dS\u"ӔI[z!)tyG_J}=(ǑV~~ё$
E5vδtXZ½va=d6BDGF!508uKfpdFoJG5BKsq-705w[FrD6{#Yhl[& oN߰ï ޝs9s{w~.>ebg&^tmR'j@j`BB*Qx-Ghe4"4V"bQqWV.*&26tz-_vz`}铦MM[~\K/޶
m&>>CR([._jiNTw.c%BaT=`^4jJTz*_	;^ʆy䑁#O?-=pO<q!رW^ᗿ+%	*px؋UxiJ	gyZof)%Ar    IENDB`                                                                                                                                                                  ladder.py                                                                                           0000644 0001750 0001750 00000007552 11703163104 011314  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   #Created by dan december 2011.  www.danomagnum.com
#from ttk import Label, Button#, Checkbutton, Style
import tkSimpleDialog
import block_functions


functionlist = block_functions.BLOCK_FUNCTION_LIST
itemlist = [] #need to fill this in to add stuff I guess

class Fault(Exception):
	pass

class IO(object):
	def __init__(self,value,name,typedesc,input=False,description=""):
		self.latched = False
		self.input = input
		self.typedesc = typedesc
		self.set(value)
		self.name=name

		self.description = description

	def delifparent(self,parent):
		displays = self.display[:]
		for d in displays:
			if d.master == parent:
				#I am a child of you, so I wll delete myself
				self.display.remove(d)
				d.destroy()
		if not self.display:
			del(self)

	def set(self,value=0):
		if self.latched:
			return False
		if self.typedesc == 'bool':
			if isinstance(value,bool) or value == 1 or value == 0:
				self.value = bool(value)
			else:
				raise Fault('Value tried to be set to something not a bool')
		else:
			self.value = value
		return True

	def latchon(self):
		self.latched = True
		if self.typedesc == 'bool':
			self.value = True

	def latchoff(self):
		self.latched = True
		if self.typedesc == 'bool':
			self.value = False

	def unlatch(self):
		self.latched = False


	def status(self):
		return self.value

	def __nonzero__(self):#evaluates the decision block
		if self.value:
			return True
		else:
			return False

	def __repr__(self):
		return str(self.value) + ' ' + self.name
	def __eq__(self,n):
		return self.value == n
	def __lt__(self,n):
		return self.value < n
	def __gt__(self,n):
		return self.value > n
	def __ge__(self,n):
		return self.value >= n
	def __le__(self,n):
		return self.value <= n
	def __trunc__(self):
		return self.value
	def __int__(self):
		try:
			i = int(self.value)
		except:
			i = 0
		return i
	def toggle(self):
		if self.latched == False:
			self.value = not self.value


	def properties(self):
		ds = self.name + "\n" + str(self.value) + "\n"
		ds += "Force: "
		if self.latched:
			ds += "on"
		else:
			ds += "off"
		ds += "\nDescription:" + self.description
		return ds



class block(object):
	def __init__(self,function = block_functions.DEFAULT,parent=None,output=False,rung=None):
		self.faulted = False
		self.function = function()
		self.name = self.function.name
		self.arguments = []
		#self.display = None
		#self.frm2 = None
		self.rung=rung
		#self.popupparent = None
		#if parent:
		#	#self.display_new(parent)
		#if output:
		#	#self.display_update_output()
		#else:
		#	#self.display_update()


	def status(self):
		return self.function.on(*self.arguments)

	def run(self,on=True):
		try:
			if on:
				self.function.on(*self.arguments)
			else:
				self.function.off(*self.arguments)
			self.faulted = False
		except:
			self.faulted = True
			raise
		
	def __nonzero__(self):#evaluates the decision block
		return self.status()


	def properties(self):
		ds = self.function.properties() + "\n\n"
		return ds


class rung(object):
	def __init__(self):
		self.inputs = []
		self.outputs = []

	def run(self):
		conds = map(lambda x:x.status(),self.inputs)
		if all(conds) or not self.inputs:
			map(lambda x:x.run(),self.outputs)
		else:
			map(lambda x:x.run(on=False),self.outputs)
			

def closeblock(bit):
	b = block()
	b.arguments.append(bit)
	return b


if __name__ == '__main__':
	I1 = create_binary_array(10,'I1:0/')

	b1 = block()
	b1.function = func_and
	b1.arguments.append(I1[0])
	b1.arguments.append(I1[1])
	I1[0].set(True)
	I1[1].set(True)


	a = value_word(0)

	out1 = block()
	out1.function = func_add
	out1.arguments.append(a)
	out1.arguments.append(1)

	out1.run()

	r = rung()
	r.inputs += [b1]
	r.outputs += [out1]

	r.run()

	I1[0].set(False)
	r.run()




                                                                                                                                                      pyladderlogic.py                                                                                    0000755 0001750 0001750 00000000045 11677227637 012722  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   #!/usr/bin/python

import tkintergui
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           test.xml                                                                                            0000644 0001750 0001750 00000001317 11675237203 011213  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   <ladder>
	<IO>
		<item>
			<name>I0:1</name>
			<type>bool</type>
			<description></description>
			<value>0</value>
		</item>
		<item>
			<name>I0:2</name>
			<type>bool</type>
			<description></description>
			<value>0</value>
		</item>
		<item>
			<name>O0:0</name>
			<type>bool</type>
			<description></description>
			<value>0</value>
		</item>
	</IO>



	<Rung>

		<input>
			<block>
				<function>And</function>
				<arguments>
					<item>I0:1</item>
					<item>I0:2</item>
				</arguments>
			</block>
		</input>
		<output>
			<block>
				<function>Close</function>
				<arguments>
					<item>O0:0</item>
				</arguments>
			</block>
		</output>
	</Rung>
</ladder>
                                                                                                                                                                                                                                                                                                                 test3.xml                                                                                           0000644 0001750 0001750 00000002200 11675237203 011266  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   <ladder><IO><item><name>I0:0/0</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/1</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/2</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/3</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/4</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/5</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/6</name><type>bool</type><description /><value>True</value></item><item><name>I0:0/7</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/8</name><type>bool</type><description /><value>False</value></item><item><name>I0:0/9</name><type>bool</type><description /><value>False</value></item></IO><Rung><input><block><function>And</function><arguments><block><function>Not</function><arguments><item>I0:0/1</item></arguments></block><item>I0:0/0</item></arguments></block></input><output><block><function>Close</function><arguments><item>I0:0/3</item></arguments></block></output></Rung></ladder>                                                                                                                                                                                                                                                                                                                                                                                                tkintergui.py                                                                                       0000644 0001750 0001750 00000025057 11703165500 012250  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   #Created by dan december 2011.  www.danomagnum.com
#from Tkinter import Tk, Frame, BOTH, RIGHT, LEFT, RAISED, Label, IntVar, BooleanVar, X, RAISED, Menu, Scrollbar,Y, Scrollbar, TclError, N, S
from Tkinter import *
#from ttk import Button, Style, Scale
#from ttk import Scale
import tkinterladder as ladder
#from .ladder import tkinterladder as ladder
import time
import pickle
import copy
import tkFileDialog
import tkSimpleDialog
import tkxmltoladder as xmltoladder
import datetime

FAULTDEBUG = FALSE

FORMATS = [('Python Ladder Logic','*.pll')]
FORMATSXML = [('Python Ladder Logic XML files','*.xml')]

class AutoScrollbar(Scrollbar):
	# a scrollbar that hides itself if it's not needed.  only
	# works if you use the grid geometry manager.
	def set(self, lo, hi):
		if float(lo) <= 0.0 and float(hi) >= 1.0:
				# grid_remove is currently missing from Tkinter!
				self.tk.call("grid", "remove", self)
		else:
				self.grid()
		Scrollbar.set(self, lo, hi)
	def pack(self, **kw):
		raise TclError, "cannot use pack with this widget"
	def place(self, **kw):
		raise TclError, "cannot use place with this widget"

class IOWindow(tkSimpleDialog.Dialog):
	def body(self, master):

		self.vartype = StringVar()
		Label(master, text="Type:").grid(row=0)
		Radiobutton(master, text="Boolean", variable=self.vartype, value='bool').grid(row=0,column=1)
		Radiobutton(master, text="Integer", variable=self.vartype, value='int').grid(row=0,column=2)
		Radiobutton(master, text="String", variable=self.vartype, value='str').grid(row=0,column=3)
		
		self.vartype.set('bool')


		Label(master, text="Name:").grid(row=1)
		self.name = Entry(master)
		self.name.grid(row=1, column=1)

		Label(master, text="Value:").grid(row=2)
		self.value = Entry(master)
		self.value.insert(0,0)
		self.value.grid(row=2, column=1)

		self.result = None
		return self.name # initial focus

	def apply(self):
		val = False
		vartype = self.vartype.get()
		print vartype
		val2 = self.value.get()
		if vartype == 'bool':
			val = bool(val2)
		elif vartype == 'int':
			val = int(val2)
		elif vartype == 'str':
			val = str(val2)
		print val
		self.result = [val, vartype,self.name.get()]
#print first, second 

class FaultWindow(tkSimpleDialog.Dialog):

	def __init__(self, parent,faults = [], title = 'Fault'):

		Toplevel.__init__(self, parent)
		self.transient(parent)
		self.faults = faults

		if title:
			self.title(title)

		self.parent = parent

		self.result = None

		body = Frame(self)
		self.initial_focus = self.body(body)
		body.pack(padx=5, pady=5,fill=BOTH,expand=1)

		self.buttonbox()

		self.grab_set()

		if not self.initial_focus:
			self.initial_focus = self

		self.protocol("WM_DELETE_WINDOW", self.cancel)

		self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
					  parent.winfo_rooty()+50))

		self.initial_focus.focus_set()

		self.wait_window(self)


	def body(self, master):

		Label(master, text="Faults:").pack(side=TOP)
		self.faultlist = Listbox(master)
		self.faultlist.pack(side=TOP,fill=BOTH,expand=1)
		for f in self.faults:
			self.faultlist.insert(END,f)

		self.result = None
		return self.faultlist

	def apply(self):
		pass
#print first, second 



class MainWindow(Frame):
	def __init__(self, parent):
		Frame.__init__(self, parent, background="white")
		self.parent = parent
		self.rungs = []
		self.exspeed = 100
		self.paused = False
		self.pausedvar = BooleanVar()
		self.faulted = False
		self.faultvar = BooleanVar()
		self.faults = []
		self.pausedvar.set(self.paused)
		self.faultvar.set(self.faulted)
		self.initUI()
		self.updatesize = False
		self.calculating = False

	def initUI(self):
		#this sets up the interface, and then goes into the program part
		#self.parent.title("PyLadderLogic")
		#self.style = Style()
		#self.style.theme_use("default")
		#self.pack(fill=BOTH,expand=1)
		self.grid(row=0,column=0,sticky='news')
		ladder.fix_scroll = self.scrollsizeupdate
		ladder.remove_row = self.removerows

		#sc = Scrollbar(self)
		#sc.pack(side=RIGHT,fill=Y)

		topperfrm = Frame(self)
		topperfrm.pack(fill=X,expand=1)
		spdlbl = Label(topperfrm,text="Speed^-1")
		spdlbl.pack(side=LEFT)
		scale = Scale(topperfrm, from_=50, to=1000, command=self.onScale,orient=HORIZONTAL)
		scale.set(100)
		scale.pack(side=LEFT)

		spdlbl = Checkbutton(topperfrm,text="Pause",command=self.playpause, variable=self.pausedvar,indicatoron=0)
		spdlbl.pack(side=RIGHT)
		self.faultbutton = Checkbutton(topperfrm,text="Fault",command=self.clearfault, variable=self.faultvar,indicatoron=0,fg='black')

		self.faultbutton.pack(side=RIGHT)
		button1 = Button(topperfrm,text="Run one loop",command=self.runone)
		button1.pack(side=RIGHT)
		button1 = Button(topperfrm,text="Update",command=self.toggleit)
		button1.pack(side=RIGHT)



		topfrm = Frame(self)
		topfrm.pack(fill=X,expand=1)



		self.popup = Menu(root,tearoff=0)
		self.popup.add_command(label='Add Rung',command=self.addrung)
		self.popup.add_command(label='Add IO',command=self.addIO)
		self.popup.add_command(label='Load XML',command=self.loadxml)
		self.popup.add_command(label='Save XML',command=self.savexml)
		root.config(menu=self.popup)


		#this section defines the "bits" in the "plc" and a few 10-bit words
		#IO = ladder.value_word(0,"I0:0")
		#IO.bits_display_new(topfrm)
		#self.IO = IO.bits()
		self.IO = []
		#self.IO[0].set(True)
		#self.IO[1].set(True)
		#self.IO[2].set(True)
		#self.IO[6].set(True)
		#ladder.itemlist += self.IO

		self.dataforms = [topfrm]

	def addrung(self):
		r = ladder.rung()
		self.rungs.append(r)
		r.display_new(self)


	def addIO(self):
		w = IOWindow(self)
		if w.result is not None:
			[value, vartype, name] = w.result
			r = ladder.IO(value, name, vartype)
			self.IO.append(r)
			r.display_new(self.dataforms[0])
			ladder.itemlist = self.IO

	def toggleit(self):
		#this function is named this because I just kept reusing it, so no reason.
		#self.bv.set(random.randint(0,1023))
		#self.bv.display_update()
		#self.blk1.display_update()
		#for r in self.rungs:
			#r.display_update()
		#self.update_idletasks()
		#canvas.config(scrollregion=canvas.bbox("all"))
		self.removedata()

	def runone(self):
		#do one run through the ladder
		self.paused = True
		self.pausedvar.set(self.paused)
		for r in self.rungs:
			r.run()
			r.display_update()
		
	def onScale(self, val):
		#set the speed
		speed = int(float(val))
		self.exspeed = int(float(val))

	def playpause(self):
		#toggle the play/pause
		self.paused = not self.paused
		self.pausedvar.set(self.paused)

	def clearfault(self):
		#clears any faults
		w = FaultWindow(self,self.faults)
		self.faulted = False
		self.faultvar.set(self.faulted)
		self.faultbutton.configure(fg='black')


	def scrollsizeupdate(self):
		#canvas.config(scrollregion=canvas.bbox("all"))
		self.updatesize=True

	def removerows(self,row):
		pausestate = self.paused
		self.paused = True
		self.pausedvar.set(self.paused)
		while self.calculating:
			time.sleep(.1)
		self.rungs.remove(row)
		row.__del__()
		self.paused = pausestate
		self.pausedvar.set(self.paused)

	def removedata(self):
		pausestate = self.paused
		self.paused = True
		self.pausedvar.set(self.paused)
		while self.calculating:
			time.sleep(.1)
		self.IO = []
		ladder.itemlist = []
		dfs = self.dataforms[:]
		for f in dfs:
			f.destroy()
		self.dataforms = []
		self.paused = pausestate
		self.pausedvar.set(self.paused)

	def savexml(self):
		filename = tkFileDialog.asksaveasfilename(parent=root,filetypes=FORMATSXML,title="Save")
		if not filename:
			return False
		
		pausestate = self.paused
		self.paused = True
		self.pausedvar.set(self.paused)

		while self.calculating:
			time.sleep(.1)


		xmltoladder.create_xml(self.rungs,self.IO,filename)
		


		self.paused = pausestate
		self.pausedvar.set(self.paused)



	def loadxml(self):
		filename = tkFileDialog.askopenfilename(parent=root,filetypes=FORMATSXML,title="Save")
		if not filename:
			return False
		rows = self.rungs[:]
		for r in rows:
			self.removerows(r)
		self.removedata()
		f = open(filename,'r')
		[self.rungs, self.IO] = xmltoladder.create_ladder(f)
		f.close()
		self.reinit()
		self.updatesize=True

	def reinit(self):
		ladder.itemlist = []
		topfrm = Frame(self)
		topfrm.pack(fill=X,expand=1)
		for i in self.IO:
			i.display_new(topfrm)
		ladder.itemlist += self.IO
		self.dataforms.append(topfrm)


		for r in self.rungs:
			r.display_new(self)
			r.display_update()


def calculatron(*args):
	#this is what automatically executes the logic at whatever interval is set
	app = args[0]
	if not any((app.paused, app.faulted)):
		app.calculating = True
		for r in app.rungs:
			try:
				r.run()
				r.display_update()
			except Exception as e:
				app.faulted = True
				app.faultvar.set(True)
				app.faultbutton.configure(fg='red')
				app.faults.append(e.message)
				if FAULTDEBUG:
					raise
		app.calculating = False
	else:
		pass
	root.after(app.exspeed,calculatron,app)
def scrollbarupdate(*args):
	app = args[0]
	if app.updatesize:
		canvas.config(scrollregion=canvas.bbox("all"))
		app.updatesize = False
	root.after(100,scrollbarupdate,app)

def OnMouseWheel(event):
	d = 0
	if event.num == 5 or event.delta == -120:
		d = 1
	elif event.num == 4 or event.delta == 120:
		d = -1
	canvas.yview("scroll", d, "units")

root = Tk()
vscrollbar = AutoScrollbar(root)
vscrollbar.grid(row=0,column=1, sticky=N+S)
hscrollbar = AutoScrollbar(root, orient=HORIZONTAL)
hscrollbar.grid(row=1, column=0, sticky=E+W)
canvas = Canvas(root, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set,width=1000,height=300)
canvas.grid(row=0, column=0, sticky=N+S+E+W)

root.bind('<MouseWheel>', OnMouseWheel)
root.bind('<Button-4>', OnMouseWheel)
root.bind('<Button-5>', OnMouseWheel)

vscrollbar.config(command=canvas.yview)
hscrollbar.config(command=canvas.xview)

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0,weight=1)

frame = Frame(canvas)
frame.rowconfigure(1, weight=1)
frame.columnconfigure(1,weight=1)


#rows = 5
#for i in range(1,rows):
    #for j in range(1,10):
        #button = Button(frame, padx=7, pady=7, text="[%d,%d]" % (i,j))
        #button.grid(row=i, column=j, sticky='news')


app = MainWindow(frame)
canvas.create_window(0, 0, anchor=NW, window=frame)
frame.update_idletasks()
canvas.config(scrollregion=canvas.bbox("all"))
app.update_idletasks()
root.after(100,calculatron,app)
root.after(100,scrollbarupdate,app)
root.mainloop()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 tkinterladder.py                                                                                    0000644 0001750 0001750 00000025503 11703163104 012711  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   #Created by dan december 2011.  www.danomagnum.com
#from ttk import Label, Button#, Checkbutton, Style
from Tkinter import StringVar, LEFT, RIGHT, BOTH, Frame, X, RAISED, IntVar, Menu, Checkbutton, Y, BooleanVar, Label, Button
import tkMessageBox
import tkSimpleDialog
import block_functions
import ladder

TRUECOLOR = "green"
FALSECOLOR = "red"
FAULTCOLOR = "yellow"
LATCHCOLOR = "blue"
DEFAULTCOLOR = "black"
fix_scroll = lambda x:x
remove_row = lambda x:x


functionlist = block_functions.BLOCK_FUNCTION_LIST
itemlist = [] #need to fill this in to add stuff I guess

class IO(ladder.IO):
	def __init__(self,value,name,typedesc,input=False,description=""):
		super(IO,self).__init__(value,name,typedesc,input,description)

		self.displayvariable = StringVar()
		if self.typedesc == 'bool':
			self.displayvalue = BooleanVar()
		elif self.typedesc == 'int':
			self.displayvalue = IntVar()
		else:
			self.displayvalue = StringVar()
		self.display = []

	def prompt_for_value(self):
		if self.typedesc == 'int':
			result = tkSimpleDialog.askinteger(self.name,self.name,initialvalue=self.value,minvalue=0,maxvalue=1023)
			if result is not None:
				self.set(result)
			self.display_update()

	def delifparent(self,parent):
		displays = self.display[:]
		for d in displays:
			if d.master == parent:
				#I am a child of you, so I wll delete myself
				self.display.remove(d)
				d.destroy()
		if not self.display:
			del(self)


	def latchon(self):
		super(IO,self).latchon()
		self.display_update()

	def latchoff(self):
		super(IO,self).latchoff()
		self.display_update()


	def unlatch(self):
		super(IO,self).unlatch()
		self.display_update()

	def clicked(self):
		#super(IO,self).clicked()
		self.toggle_and_display()
	def toggle_and_display(self):
		self.toggle()
		self.display_update()

	def display_new(self,parent):
		self.display_update()
		b = Checkbutton(parent,textvariable=self.displayvariable,command=self.clicked,variable=self.displayvalue,indicatoron=0)
		b.pack(side=LEFT)
		self.display.append(b)

		self.popup = Menu(parent,tearoff=0)
		self.popup.add_command(label="force on",command=self.latchon)
		self.popup.add_command(label="force off",command=self.latchoff)
		self.popup.add_command(label="remove force",command=self.unlatch)
		self.popup.add_separator()
		self.popup.add_command(label="properties",command=self.properties_display)
		self.popup.add_command(label="Set",command=self.prompt_for_value)
		self.popup.add_command(label="description",command=self.setdesc)
		b.bind("<Button-3>",self.popup_menu)

		return b

	def popup_menu(self,event):
		try: 
			self.popup.tk_popup(event.x_root,event.y_root,0)
		finally:
			self.popup.grab_release()

	def properties_display(self):
		ds = self.properties()
		tkMessageBox.showinfo(self.name,ds)


	def display_update(self):
		if self.display:
			for d in self.display:
				if self.latched:
					d.configure(foreground=LATCHCOLOR)
				else:
					d.configure(foreground=DEFAULTCOLOR)
		ds = self.name + "\n" + str(self.value)
		if self.description:
			ds += "\n" + self.description
		if self.displayvariable:
			self.displayvariable.set(ds)

			dv = None
			if self.typedesc == 'bool':
				dv = bool(self.value)
			elif self.typedesc == 'int':
				dv = int(self.value)
			else:
				dv = str(self.value)
			self.displayvalue.set(dv)

	
	def setdesc(self):
		result = tkSimpleDialog.askstring(self.name,self.name,initialvalue=self.description)
		if result is not None:
			self.description = result
		self.display_update()
	


class block(ladder.block):
	def __init__(self,function = block_functions.DEFAULT,parent=None,output=False,rung=None):
		super(block,self).__init__(function,parent,output,rung)
		self.display = None
		self.frm2 = None
		self.popupparent = None
		if parent:
			self.display_new(parent)
		if output:
			self.display_update_output()
		else:
			self.display_update()

	def run(self,on=True):
		try:
			super(block,self).run(on)
		except:
			self.display_update()
			raise


	def delifparent(self,parent):
		if self.frm.master == parent:
			#I am a child of you, so I wll delete myself
			if self.frm2:
				self.frm2.destroy()
			for a in self.arguments:
				a.delifparent(self.frm)

	def removeblock(self,child):
		if child in self.arguments:
			self.arguments.remove(child)

	def display_new(self,parent):
		frm = Frame(parent,border=2,relief=RAISED,pady=5)
		frm2 = Frame(frm,border=1,relief=RAISED,)
		frm2.pack(fill=X)
		l = Label(frm2,text=self.function.__name__())
		l.pack()

		for bit in self.arguments:
			bit.display_new(frm)
		frm.pack(side=LEFT)
		self.display = frm

		self.popupparent = parent
		self.popup = Menu(self.popupparent,tearoff=0,postcommand=self.updatemenu)
		addmenu = Menu(self.popup,tearoff=0)
		for item in itemlist:
			addmenu.add_command(label=item.name,command=self.additem(item))
		self.popup.add_cascade(label="add argument",menu=addmenu)
		self.popup.add_command(label="properties",command=self.properties_display)
		self.popup.add_separator()
		self.popup.add_command(label="remove block",command=self.delblock)
		self.popup.add_separator()

		self.updatemenu()
		self.frm = frm
		frm.bind("<Button-3>",self.popup_menu)
		fix_scroll()

	def testing(self):
		print self.arguments
		print self.status()
		print self.function.on

	def properties_display(self):
		ds = self.properties()
		tkMessageBox.showinfo(self.name,ds)

	def updatemenu(self):
		self.popup.delete(5)
		self.popup.delete(4)
		self.popup.delete(3)
		self.popup.delete(2)
		self.popup.delete(1)
		self.popup.delete(1)
		self.popup.delete(1)
		
		addmenu = Menu(self.popup,tearoff=0)
		for item in itemlist:
			addmenu.add_command(label=item.name,command=self.additem(item))
		for fnct in functionlist:
			addmenu.add_command(label=fnct.__name__,command=self.addsubblock(fnct))
		self.popup.add_cascade(label="add argument",menu=addmenu)
		self.popup.add_command(label="properties",command=self.properties)
		self.popup.add_command(label="test",command=self.testing)
		self.popup.add_separator()
		self.popup.add_command(label="remove block",command=self.delblock)
		self.popup.add_separator()



		self.removeargsmenu = Menu(self.popup,tearoff=0)
		for item in self.arguments:
			self.removeargsmenu.add_command(label=item.name,command=self.removearg(item))
		self.popup.add_cascade(label="remove argument",menu=self.removeargsmenu,)
	

	def addsubblock(self,fnct):
		return lambda:self.arguments.append(block(fnct,parent=self.frm,rung=self))
	def removearg(self,item):
		return lambda:self.removearg2(item)
	def removearg2(self,item):
		item.delifparent(self.frm)
		self.arguments.remove(item)

	def additem(self,item):
		return lambda:self.additem2(item)

	def additem2(self,item):
		self.arguments.append(item)
		item.display_new(self.frm)
		fix_scroll()

	def delblock(self):
		if self.frm2:
			self.frm2.destroy()
		self.frm.destroy()


	def popup_menu(self,event):
		try: 
			self.popup.tk_popup(event.x_root,event.y_root,0)
		finally:
			self.popup.grab_release()


	def display_update(self):
		if self.display:
			if self.faulted:
				self.display.configure(bg=FAULTCOLOR)
			elif self.status():
				self.display.configure(bg=TRUECOLOR)
			else:
				self.display.configure(bg=FALSECOLOR)
		for bit in self.arguments:
				bit.display_update()

	def display_update_output(self):
		for bit in self.arguments:
			bit.display_update()


class rung(ladder.rung):
	def __init__(self):
		super(rung,self).__init__()
		self.frminput = None
		self.frmoutput = None
	def __del__(self):
		for i in self.inputs:
			i.delifparent(self.frminput)
		for o in self.outputs:
			o.delifparent(self.frmoutput)

		self.frminput.destroy()
		self.frmoutput.destroy()
		self.frm.destroy()

	def run(self):
		super(rung,self).run()

		conds = map(lambda x:x.status(),self.inputs)
		if all(conds) or not self.inputs:
			if self.frminput:
				self.frminput.configure(bg=TRUECOLOR)
		else:
			if self.frminput:
				self.frminput.configure(bg=FALSECOLOR)
			

	def removeblock(self,child):
		if child in self.inputs:
			self.inputs.remove(child)
		elif child in self.outputs:
			self.outputs.remove(child)

	def display_new(self,parent):
		frm = Frame(parent,border=2,relief=RAISED)
		frmminheight = Frame(frm,height=20,width=1)
		frmminheight.pack(side=LEFT)
		self.frminput = Frame(frm,border=1,relief=RAISED)
		self.frmoutput = Frame(frm,border=1,relief=RAISED)
		self.frminput.pack(side=LEFT,fill=Y)
		self.frmoutput.pack(side=RIGHT,fill=Y)

		for inputblock in self.inputs:
			inputblock.display_new(self.frminput)
		for outputblock in self.outputs:
			outputblock.display_new(self.frmoutput)
		frm.pack(fill=X,expand=1)
		self.display = frm

		self.popup = Menu(parent,tearoff=0)
		self.inputmenu = Menu(self.popup,tearoff=0)
		self.outputmenu = Menu(self.popup,tearoff=0)
		for fnct in functionlist:
			self.inputmenu.add_command(label=fnct.__name__,command=self.addinput(fnct))
			self.outputmenu.add_command(label=fnct.__name__,command=self.addoutput(fnct))
		self.popup.add_cascade(label="add input",menu=self.inputmenu)
		self.popup.add_cascade(label="add output",menu=self.outputmenu)
		self.popup.add_separator()
		self.popup.add_command(label="remove rung",command=self.removerowclick)
		self.popup.add_command(label="new rung")
		self.popup.add_command(label="test",command=self.test)
		frm.bind("<Button-3>",self.popup_menu)
		self.frminput.bind("<Button-3>",self.popup_menu_input)
		fix_scroll()
		self.frm = frm

	def test(self):
		for i in self. inputs:
			i.test(self.frminput)

	def removerowclick(self):
		remove_row(self)

	def addinput(self,fnct):
		return lambda:self.inputs.append(block(fnct,parent=self.frminput,rung=self))

	def addoutput(self,fnct):
		return lambda:self.outputs.append(block(fnct,parent=self.frmoutput,output=True))

	def popup_menu(self,event):
		try: 
			self.popup.tk_popup(event.x_root,event.y_root,0)
		finally:
			self.popup.grab_release()
	def popup_menu_input(self,event):
		try: 
			self.inputmenu.tk_popup(event.x_root,event.y_root,0)
		finally:
			self.popup.grab_release()

	def display_update(self):
		for inputblock in self.inputs:
			inputblock.display_update()
		for outputblock in self.outputs:
			outputblock.display_update_output()



def closeblock(bit):
	b = block()
	b.arguments.append(bit)
	return b


if __name__ == '__main__':
	I1 = create_binary_array(10,'I1:0/')

	b1 = block()
	b1.function = func_and
	b1.arguments.append(I1[0])
	b1.arguments.append(I1[1])
	I1[0].set(True)
	I1[1].set(True)


	a = value_word(0)

	out1 = block()
	out1.function = func_add
	out1.arguments.append(a)
	out1.arguments.append(1)

	out1.run()

	r = rung()
	r.inputs += [b1]
	r.outputs += [out1]

	r.run()

	I1[0].set(False)
	r.run()




                                                                                                                                                                                             tkxmltoladder.py                                                                                    0000644 0001750 0001750 00000011534 11677227637 012760  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   from xml.etree import ElementTree
import tkinterladder as ladder
import block_functions

def block_from_xml(IOlist,block):
	newblock = ladder.block()
	funcxml = block.find('function')
	#print funcxml.text
	if funcxml is None:
		raise Warning('bad xml in a block, no function name' + str(block))
	functxt = funcxml.text
	if block_functions.BLOCK_FUNCTION_DICT.has_key(functxt):
		newblock.function = block_functions.BLOCK_FUNCTION_DICT[functxt]()
	argsxml = block.find('arguments')
	for arg in argsxml.getchildren():
		newargument = None
		if arg.tag == 'item':
			if IOlist.has_key(arg.text):
				newargument = IOlist[arg.text]
			else:
				raise Warning('bad xml in a block\'s arguments.  Cannot resolve IO name: ' + arg.text)
		elif arg.tag == 'block':
			newargument = block_from_xml(IOlist,arg)
		else:
			raise Warning('bad xml in block\'s arguments.  Not an item or block')
		if newargument is not None:
			newblock.arguments.append(newargument)
	return newblock

def create_ladder(xmlfile):
	data = ElementTree.parse(xmlfile)

	ladderxml = data.getroot()
	#Set up IO
	IOxml = ladderxml.find('IO')
	IOlist = {}
	for item in IOxml.getchildren():
		value = None
		valuetxt=None
		newIO = None
		if item.tag != 'item':
			Warning('bad xml in the IO section: expected an <item>: '  + str(item.tag))
			continue
		namexml = item.find('name')
		typexml = item.find('type')
		descxml = item.find('desc')
		valuexml = item.find('value')

		#if (not namexml) and (not typexml):
			#raise Warning('bad xml in the IO section: missing name or type: '  + str(item.tag))
			#continue
		nametxt = namexml.text
		typetxt = typexml.text

		if not descxml:
			desctxt = ''
		else:
			desctxt = descxml.text

		if valuexml is not None:
			valuetxt = valuexml.text

		if typetxt=='int':
			value = int(valuetxt)
		elif typetxt=='str':
			value = str(valuetxt)
		elif typetxt=='bool':
			value = bool(valuetxt)
		else:
			value = valuetxt
		#print nametxt,
		newIO = ladder.IO(value,nametxt,typetxt,description=desctxt)
		#print newIO

		if newIO is not None:
			IOlist[nametxt] = newIO
	#print "-----"
	#rint IOlist
	#rint "-----"




	#Set up Rungs

	#Rungsxml = ladderxml.findall('Rung')
	Rungslist = ladderxml.findall('Rung')
	Rungs = [] 
	for rung in Rungslist:
	#for item in Rungsxml.getchildren():
		#print "addrung"
		newrung = ladder.rung()

		for rungside in rung.getchildren():
			for subitem in rungside.getchildren():
				block = None
				if subitem.tag != 'block':
					Warning('bad xml in Rung input section, excpeted a block' + str(subitem.tag))
					#print "error here", subitem.tag
					continue
				
				block = block_from_xml(IOlist,subitem)

				if block is not None:
					if rungside.tag == 'input':
						newrung.inputs.append(block)
					elif rungside.tag == 'output':
						newrung.outputs.append(block)
					else:
						Warning('bad xml in the Rung section, expected input or output block: ' + str(item.tag))
						pass


		
			continue
		Rungs.append(newrung)
	IOlist = IOlist.values()
	##print "---"
	#print Rungs
	#print "+++"
	return [Rungs, IOlist]

def io_to_xml(IO):
	itemxml = ElementTree.Element('item')
	namexml = ElementTree.SubElement(itemxml,'name')
	namexml.text = str(IO.name)
	typexml = ElementTree.SubElement(itemxml,'type')
	typexml.text = str(IO.typedesc)
	descxml = ElementTree.SubElement(itemxml,'description')
	descxml.text = str(IO.description)
	valuexml = ElementTree.SubElement(itemxml,'value')
	valuexml.text = str(IO.value)

	return itemxml

def block_to_xml(Block):
	itemxml = ElementTree.Element('block')
	functionxml = ElementTree.SubElement(itemxml,'function')
	functionxml.text = Block.function.name
	argumentsxml = ElementTree.SubElement(itemxml,'arguments')
	for arg in Block.arguments:
		if isinstance(arg,ladder.IO):#arg.__class__ == ladder.IO.__class__:
			argxml = ElementTree.SubElement(argumentsxml,'item')
			argxml.text = arg.name
		elif isinstance(arg,ladder.block):#arg.__class__ == ladder.block.__class__:
			argxml = block_to_xml(arg)
			argumentsxml.append(argxml)
		else:
			raise Exception('bad type' + str(ladder.IO.__class__) + " " + str(arg.__class__))
	return itemxml

def create_xml(Rungs,IO,filename):
	ladderxml = ElementTree.Element('ladder')
	#take care of IO
	IOxml = ElementTree.SubElement(ladderxml,'IO')
	for item in IO:
		itemxml = io_to_xml(item)
		IOxml.append(itemxml)

	#Set up Rungs
	for rung in Rungs:
		Rungxml = ElementTree.SubElement(ladderxml,'Rung')
		inputsxml = ElementTree.SubElement(Rungxml,'input')
		outputsxml = ElementTree.SubElement(Rungxml,'output')

		for block in rung.inputs:
			b = block_to_xml(block)
			inputsxml.append(b)
		for block in rung.outputs:
			b = block_to_xml(block)
			outputsxml.append(b)
	tree = ElementTree.ElementTree(ladderxml)
	tree.write(filename)
	return True
                                                                                                                                                                    xmltoladder.py                                                                                      0000644 0001750 0001750 00000011513 11675237203 012402  0                                                                                                    ustar   dano                            dano                                                                                                                                                                                                                   from xml.etree import ElementTree
import ladder
import block_functions

def block_from_xml(IOlist,block):
	newblock = ladder.block()
	funcxml = block.find('function')
	#print funcxml.text
	if funcxml is None:
		raise Warning('bad xml in a block, no function name' + str(block))
	functxt = funcxml.text
	if block_functions.BLOCK_FUNCTION_DICT.has_key(functxt):
		newblock.function = block_functions.BLOCK_FUNCTION_DICT[functxt]()
	argsxml = block.find('arguments')
	for arg in argsxml.getchildren():
		newargument = None
		if arg.tag == 'item':
			if IOlist.has_key(arg.text):
				newargument = IOlist[arg.text]
			else:
				raise Warning('bad xml in a block\'s arguments.  Cannot resolve IO name: ' + arg.text)
		elif arg.tag == 'block':
			newargument = block_from_xml(IOlist,arg)
		else:
			raise Warning('bad xml in block\'s arguments.  Not an item or block')
		if newargument is not None:
			newblock.arguments.append(newargument)
	return newblock

def create_ladder(xmlfile):
	data = ElementTree.parse(xmlfile)

	ladderxml = data.getroot()
	#Set up IO
	IOxml = ladderxml.find('IO')
	IOlist = {}
	for item in IOxml.getchildren():
		value = None
		valuetxt=None
		newIO = None
		if item.tag != 'item':
			Warning('bad xml in the IO section: expected an <item>: '  + str(item.tag))
			continue
		namexml = item.find('name')
		typexml = item.find('type')
		descxml = item.find('desc')
		valuexml = item.find('value')

		#if (not namexml) and (not typexml):
			#raise Warning('bad xml in the IO section: missing name or type: '  + str(item.tag))
			#continue
		nametxt = namexml.text
		typetxt = typexml.text

		if not descxml:
			desctxt = ''
		else:
			desctxt = descxml.text

		if valuexml is not None:
			valuetxt = valuexml.text

		if typetxt=='int':
			value = int(valuetxt)
		elif typetxt=='str':
			value = str(valuetxt)
		elif typetxt=='bool':
			value = bool(valuetxt)
		else:
			value = valuetxt
		#print nametxt,
		newIO = ladder.IO(value,nametxt,typetxt,description=desctxt)
		#print newIO

		if newIO is not None:
			IOlist[nametxt] = newIO
	#print "-----"
	#rint IOlist
	#rint "-----"




	#Set up Rungs

	#Rungsxml = ladderxml.findall('Rung')
	Rungslist = ladderxml.findall('Rung')
	Rungs = [] 
	for rung in Rungslist:
	#for item in Rungsxml.getchildren():
		#print "addrung"
		newrung = ladder.rung()

		for rungside in rung.getchildren():
			for subitem in rungside.getchildren():
				block = None
				if subitem.tag != 'block':
					Warning('bad xml in Rung input section, excpeted a block' + str(subitem.tag))
					#print "error here", subitem.tag
					continue
				
				block = block_from_xml(IOlist,subitem)

				if block is not None:
					if rungside.tag == 'input':
						newrung.inputs.append(block)
					elif rungside.tag == 'output':
						newrung.outputs.append(block)
					else:
						Warning('bad xml in the Rung section, expected input or output block: ' + str(item.tag))
						pass


		
			continue
		Rungs.append(newrung)
	IOlist = IOlist.values()
	##print "---"
	#print Rungs
	#print "+++"
	return [Rungs, IOlist]

def io_to_xml(IO):
	itemxml = ElementTree.Element('item')
	namexml = ElementTree.SubElement(itemxml,'name')
	namexml.text = str(IO.name)
	typexml = ElementTree.SubElement(itemxml,'type')
	typexml.text = str(IO.typedesc)
	descxml = ElementTree.SubElement(itemxml,'description')
	descxml.text = str(IO.description)
	valuexml = ElementTree.SubElement(itemxml,'value')
	valuexml.text = str(IO.value)

	return itemxml

def block_to_xml(Block):
	itemxml = ElementTree.Element('block')
	functionxml = ElementTree.SubElement(itemxml,'function')
	functionxml.text = Block.function.name
	argumentsxml = ElementTree.SubElement(itemxml,'arguments')
	for arg in Block.arguments:
		if isinstance(arg,ladder.IO):#arg.__class__ == ladder.IO.__class__:
			argxml = ElementTree.SubElement(argumentsxml,'item')
			argxml.text = arg.name
		elif isinstance(arg,ladder.block):#arg.__class__ == ladder.block.__class__:
			argxml = block_to_xml(arg)
			argumentsxml.append(argxml)
		else:
			raise Exception('bad type' + str(ladder.IO.__class__) + " " + str(arg.__class__))
	return itemxml

def create_xml(Rungs,IO,filename):
	ladderxml = ElementTree.Element('ladder')
	#take care of IO
	IOxml = ElementTree.SubElement(ladderxml,'IO')
	for item in IO:
		itemxml = io_to_xml(item)
		IOxml.append(itemxml)

	#Set up Rungs
	for rung in Rungs:
		Rungxml = ElementTree.SubElement(ladderxml,'Rung')
		inputsxml = ElementTree.SubElement(Rungxml,'input')
		outputsxml = ElementTree.SubElement(Rungxml,'output')

		for block in rung.inputs:
			b = block_to_xml(block)
			inputsxml.append(b)
		for block in rung.outputs:
			b = block_to_xml(block)
			outputsxml.append(b)
	tree = ElementTree.ElementTree(ladderxml)
	tree.write(filename)
	return True
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     