From ee6233b8930668876ee10c802bafe312b1094f3c Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 28 Aug 2013 09:23:14 +0200 Subject: [PATCH 01/29] Add pl_editor_doc.icns, from Orson. Fix Bug #1217504 (bad look of Module Properties Dialog, 3D fields). Add Dick's workaround in plot_board_layers.cpp to try to avoid crash in solder mask calculations, due to a bug in boost::polygon, in resize function. --- 3d-viewer/3d_aux.cpp | 75 ++--- 3d-viewer/3d_struct.h | 3 +- pagelayout_editor/pl_editor_doc.icns | Bin 0 -> 55232 bytes .../dialog_edit_module_for_BoardEditor.cpp | 16 +- ...ialog_edit_module_for_BoardEditor_base.cpp | 27 ++ ...ialog_edit_module_for_BoardEditor_base.fbp | 282 +++++++++++++++++ .../dialog_edit_module_for_BoardEditor_base.h | 6 + .../dialog_edit_module_for_Modedit.cpp | 15 +- .../dialog_edit_module_for_Modedit_base.cpp | 27 ++ .../dialog_edit_module_for_Modedit_base.fbp | 284 +++++++++++++++++- .../dialog_edit_module_for_Modedit_base.h | 8 +- pcbnew/plot_board_layers.cpp | 7 +- 12 files changed, 669 insertions(+), 81 deletions(-) create mode 100644 pagelayout_editor/pl_editor_doc.icns diff --git a/3d-viewer/3d_aux.cpp b/3d-viewer/3d_aux.cpp index 591e36b5d9..0878053869 100644 --- a/3d-viewer/3d_aux.cpp +++ b/3d-viewer/3d_aux.cpp @@ -60,7 +60,7 @@ void S3D_MASTER::Set_Object_Coords( std::vector< S3D_VERTEX >& aVertices ) aVertices[ii].y *= m_MatScale.y; aVertices[ii].z *= m_MatScale.z; - // adjust rotation + // adjust rotation if( m_MatRotation.x ) RotatePoint( &aVertices[ii].y, &aVertices[ii].z, m_MatRotation.x * 10 ); @@ -176,64 +176,39 @@ GLuint EDA_3D_CANVAS::DisplayCubeforTest() return gllist; } -VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* parent, const wxString& title, - wxBoxSizer* BoxSizer ) +VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* aParent, wxBoxSizer* aBoxSizer ) { - wxString text; - wxStaticText* msgtitle; + wxString text; - if( title.IsEmpty() ) - text = _( "Vertex " ); - else - text = title; + wxFlexGridSizer* gridSizer = new wxFlexGridSizer( 0, 2, 0, 0 ); + gridSizer->AddGrowableCol( 1 ); + gridSizer->SetFlexibleDirection( wxHORIZONTAL ); + gridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - msgtitle = new wxStaticText( parent, -1, text, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + aBoxSizer->Add( gridSizer, 0, wxEXPAND, 5 ); - BoxSizer->Add( msgtitle, wxGROW | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM ); + wxStaticText* msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "X:" ) ); + gridSizer->Add( msgtitle, 0, wxALL , 5 ); - wxFlexGridSizer* GridSizer = new wxFlexGridSizer( 3, 2, 0, 0 ); + m_XValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString, + wxDefaultPosition,wxDefaultSize, 0 ); + gridSizer->Add( m_XValueCtrl, 0, wxALL|wxEXPAND, 5 ); - BoxSizer->Add( GridSizer, 0, wxGROW | wxALL, 5 ); + msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "Y:" ), wxDefaultPosition, + wxDefaultSize, 0 ); + gridSizer->Add( msgtitle, 0, wxALL, 5 ); - msgtitle = new wxStaticText( parent, -1, wxT( "X:" ) ); + m_YValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxDefaultSize, 0 ); + gridSizer->Add( m_YValueCtrl, 0, wxALL|wxEXPAND, 5 ); - GridSizer->Add( msgtitle, 0, - wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | - wxLEFT | wxRIGHT , 5 ); - m_XValueCtrl = new wxTextCtrl( parent, -1, wxEmptyString, - wxDefaultPosition, wxSize( -1, -1 ), 0 ); + msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "Z:" ), wxDefaultPosition, + wxDefaultSize, 0 ); + gridSizer->Add( msgtitle, 0, wxALL, 5 ); - GridSizer->Add( m_XValueCtrl, - 0, - wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | - wxLEFT | wxRIGHT, 5 ); - - msgtitle = new wxStaticText( parent, -1, wxT( "Y:" ), wxDefaultPosition, - wxSize( -1, -1 ), 0 ); - - GridSizer->Add( msgtitle, - 0, - wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | - wxLEFT | wxRIGHT, 5 ); - m_YValueCtrl = new wxTextCtrl( parent, -1, wxEmptyString, - wxDefaultPosition, wxSize( -1, -1 ), 0 ); - - GridSizer->Add( m_YValueCtrl, 0, - wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | - wxLEFT | wxRIGHT, 5 ); - - msgtitle = new wxStaticText( parent, -1, wxT( "Z:" ), wxDefaultPosition, - wxSize( -1, -1 ), 0 ); - - GridSizer->Add( msgtitle, 0, - wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | - wxLEFT | wxRIGHT, 5 ); - m_ZValueCtrl = new wxTextCtrl( parent, -1, wxEmptyString, - wxDefaultPosition, wxSize( -1, -1 ), 0 ); - - GridSizer->Add( m_ZValueCtrl, 0, - wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | - wxLEFT | wxRIGHT, 5 ); + m_ZValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxDefaultSize, 0 ); + gridSizer->Add( m_ZValueCtrl, 0, wxALL|wxEXPAND, 5 ); } diff --git a/3d-viewer/3d_struct.h b/3d-viewer/3d_struct.h index 4c1d2be577..d73077a266 100644 --- a/3d-viewer/3d_struct.h +++ b/3d-viewer/3d_struct.h @@ -155,10 +155,9 @@ class VERTEX_VALUE_CTRL { private: wxTextCtrl* m_XValueCtrl, * m_YValueCtrl, * m_ZValueCtrl; - wxStaticText* m_Text; public: - VERTEX_VALUE_CTRL( wxWindow* parent, const wxString& title, wxBoxSizer* BoxSizer ); + VERTEX_VALUE_CTRL( wxWindow* parent, wxBoxSizer* BoxSizer ); ~VERTEX_VALUE_CTRL(); diff --git a/pagelayout_editor/pl_editor_doc.icns b/pagelayout_editor/pl_editor_doc.icns new file mode 100644 index 0000000000000000000000000000000000000000..6760a09bb4bb5a22c066068b2c0c84df18e3b331 GIT binary patch literal 55232 zcmeIb2V4``+xI;P22in=wXLpO++Dk_Ygx2KKK1T4|9L+|BlQxzw4Yc*O_b1%=et^+_LX51m(Zpd3eld z2r_Tm`~Hor!u*`indzTWl0Lq6zy9GdjYelMS!@o%wTvu&`>>qJX2NVUE(>Oy56^vd zo0)Jw{#ktd({c`z9hUdvIyX2+B9`WSdc@>$Li6IU(Ico@^sf7>oHtxZ>0Ydo?8Fs?%## zL)9-WD=+(3)vtT?pMOz(Y08_Yrq#de`Xu*5ZS@m}ua+@BWEiSXW6v37QvJ*22Y-56 zd-Z8o6OJr@{`|p%`-bY@a`|xg4)J65l`Mh&>Ic7-#zbuPdVTPLvHA~ghPb#!kzO@a zeQ^2fum0ijdv`;SnH98DTPZMXmFOu5+KX19hOG*{2tm71O|@aupn(vy$Mks6|Hgl- zb%srig7WP!Ew3*G^;o@j%dY*04(;E$dG)$M(9S*B&7l3vpMAqF2Ht-9?Ag=Darf`s zx)F2ba%5QW#Q;AaFAtZUeFm)chtOD&P#_XH3dw?Ad_Gql`SVZUuh3m#NeP8oPN7h# z6%{bek=~V}yz$cyYyBYTwy>N(O^1>0Wo1lXR7l0Pv5V(0718e<>lBh7#uTW zFdUhkDpc4ZZwR^}qEMI|j$@@ckH=-e%uXy8O?~}`L90C=C{{!*%Oj=3X%^|93b2Fc z*$j2e58thJhoBfC{qru5K>vV%z`%fu0YUzscyuO{#n8kI8o0^@g02dgY3sQfRh6!~ z8kOXiakIWV4KA!!Et17$@~bcR?&)v@f&zqpALPQ!P7=|>1Ydjig#{J|9266@uIZmATt8L$k|1hw4NUiBzLih|m`q zBK-Jf2yzziGxlEH#nGfj@(%9avzLZmKk)W#x(q+Q0fNW^e)h&f1z(yHq9`aRDppo; z#+S*TWhiljH4sD;@N-s`NQ6~cSERwgA)!8;w5S^{1uAgdX2B{5f(88i)o0yY+=(Zh ziQD=*o!xhEA60*JIRu>(av9mlNlA$*8Ob2P{!C9wNlVU_N%6B6L(pjfhb@xH6iOus z0EI%W#hO>El;Fo5Am{|24Wfx#$>R%zBC%8^gXIGha=91{2hB4N9G8puVyQ$blPi=e zwWg{{tJT5UE-Ew{lx_}+Zp$hyDk%l|3Moe@aCwiiveIIvTdy7q=FgfoYst#xAa&U< zTu8F(uyB#R!{VjOSFD)t3C$>T53Mlc{|tXyqcPNQCR2I>U33Te4WnAlAM@2aqvr2hj-qDI-QqA<;MMVn3P2Acl3N%#Gjnw6Z9mX@B8n3kQ9C&LP0 zv!J&7$_?FDrA4cCnnt=W^#64KZ7TVu;>ow6{(CX-Qb20u*U8t|e?=)dSpQ|!O}>Wy zE4`YY`7AN2;r<(T>)E~BjOa%Cug@`VswVMH1N|2y-yF2)eQrWhWBs>0G3Rb0{a2^@ zI{7x)f9dG^3A4ZGzdTJ;ZSvj7;Vv9M}!t+JNMTOK` zb&@ap-qqs{EB5Z&f8fC0J^K&sJyv9zd~>#c+Hm^W+oNbDUmyVem!qxIfA>eMrK0ht z*+U2Y@MAuDr0>PVI{mjmDOAKCQKzP+rB706%hLt%bvkgFOo+Zd&szqv)6C+qc@C?~ z>h@n(&vW}7XTdZ3O-FXlw_8_V|IJLvfwTY2O-{?nY@q)t<#J_Jb+xv!{`-Hf`|iQV z5*Aia8)#oeK~X(h0rjROWM&3InP9Y6-&T!|h0M($v(Kp3INJE)zdCdRemuLu^T#)F zys7hBk7MoMaQn8l&;RcB!QbhH1l^UH0nL`ki)AH1m5y&dQ%`+^Y zUO}V7w1E{=Dy6)vw6vt8sHm{8pdc?VHzy}MD=RZIJ;!g!pBvV|P=^4Rd>0i9MIxC* zEQTeBlq7SN6C`NnVrcJL7-}DIo^)3WMiYe<<)tt_p75X&%H%1FE&l?CJ79-(l(O;? zI*m$&!4MpwdoT!8)h7qby+FRb|2g6v9TgmB&8a5YBox4?CQBEmifO_GFiA*A^0~n99m|!@c>d@vd;L67PQTOC>jLsp*0PTjx`Q{YMu9>fJl*#rhSO4tvMT6-Kl84Hfm zpI;*RIr_G};CI32G0Tx@#R9{M)I}D%flWvE!^f`!8@A8P3n5@Q3Wq?UNEjh1EGmTj zi0#O<qgHS4!D^zMQp3|V5x4it91#etagd8H5z^Y2IGus8Mza#HC7+p=TsC09{ z$B$|a82q6E&y-3o^>)E??-D+E;fkAE>|YK;gGjsfU9M(OIk>r8p*QzF`69TW==M9& zb-!{xRv30wiY>Gg*bgP{*c*jXUQj&kMKY;e35udZBe$eqkMOx)^ol9F7((HKaVbX& z>^Ecf@U~r%C?!|!f!pIFqKu*Ijs^S9&Q*RaLOFrg*p(b$pS%FtwG`N&-Mk~bn#mM^ z@<=6erAn#eO`SA*$hO%xQAydG59NhXuX#XUmpmWZxdhms*|l;U*Lbr@u zI(lZev)KEJ;3lM$KgT_r#fj4w8H_|pIEag7_)b`7fK{D3Ht1N`$>~V{8$EFB?1pJAxHc^M9AS{ z_M0&KW2-k@!tEUd5{Xz#9Y1%@Z$6oBA;2}aSN7F-b``OS&dl>3{WW~CmY8FG_ z4(vrT#gZ|LM$PEtjDq)SaCIjX1*5JkV9!C5WX%hm)M?8QR#%+D)EPw%r9 z1tEl;&=H(~*>hRy#2L^=I~eMDaLFov+}@rqsEYV*>G&zX{KiGqu+~hcL#jJyjpoy! zZ3{qg_SrA@)0^`oO!vR0j2qYU9jd@$2nH{3I#i*VVL-h)aT>H9n0Mb}xAcOJ%@MiV z^Tbp!i!`xUG^%w$JLu5tFd;{Pew+ra1$I4mEpYIzW@Rxv?RmU%p{R1hq`T2qu3jZx zgRa8YI$XUG5GCLUjn>_E&RgV#QeJbs7FF`-BG%`p$eD{IUvn@}3xNIF2f17}G48&7 zww-4+i>Y*9BudYreaM!1-Zd5hG+d47(5*A)yH~SWLbpYtxqoCb2khPLD=HN{94K}#!N(jF^3IHU};;4M6QsD zNrEmSu~;M$2t+ESqDHvm(vjoO>wqnjS6Rv9@nK;f@IFq=2TcS{124FwV!2XLYu|gx z@ZZnj_P~S>UT=Z-TVjb6dy@q#VO0mU8d%r1i?zehF=zDVFs~yRYvAVK#TT$wI4Z5b zuwD4eh*MP{E6^)pt_@ZgTphd}l*ydrRx| zq{>kXR}s``+B9ejup`)xowy;Vq8z3KP!S5DlpQv$pFQ|{+xaLo+io%J;Aro($k85g zKo(ofoi}g6Kp5&`+uM$hK(OL zjtIdE%x&k*wF`wT7cE?9yU2bH)SBwSh54UI^}arhrFvgus)xfYL!+awhBln*9h6lX zT{Q`{sYY|6UMdS3&-PdXR4B1*uSScH2RJ$By?09%HI(heGAVe~i`}WK#m6pO4)%ge z5`2pr%=WeBsQ2kNuKr|VlJIU|S%cZ$V6V^iG1rbBDR{$_Mn#l^8p!te(}%J)+gD-P{?WV4$8YP;_IP7{ zo$YgENiC1R0u85!Ntrjtz< zXbq|>8_}oFgTmnY6FrTm1K?_RG+^~scyrfnYf`JH{xEFF==u}=1ox1OAkT;H zIDYl)u6=v=?c2ZmLe$o^>o+b6s6Wx4!V^7m?)X_pxbvwK2$4iO-&mTL%JgYoC>9Ha ze7>+X&9|oc|BFWSzKxFPYtlS6q7T0u>eS$fUZ3T`h@Sc}TUp@R=!m{H$7@i=z5I9g z3*NgoC&!~gmzRb4>CuG={>{trr(OmoeT@DfxOb_UIsST-TXZqV@mHeCnwjHg=O`14 zQ1+FZ%)gW4%Zl&4t*n1UUpL2t5q-(K$M3VAH$TUV83n1i&m#VRlH(K)K4uSHz=eSF_0a{MAb-~G`YQlF7-=U~_w zX-_&~Iy&!Blj9dkvOVs)ZQQ$J`o3*jk!|MNckbK)Z)?BfujqPnyqzkBUCtKx)K6dxL;O8D!t>s_x@h)p1$1f|Kb5ki3NLIU`>%dD`b7(25EBV&S z>Q)0e-l2k{=J7-lkb`sIe)y31wg}bAN{b4$x%KDxd1ZW%u4qYKVPR2mehNpG z_AxOfyrCQ~$8-D!FLaGr7r0~BuI9JU;a&TE^J4=!-b0_`cbIUYWL9CjqPIdhx{liI;e<#-W^-vtb#TXXz>Hk99if5o%50x$E;psnxU zylrB8^C5NsumoEhXgGLPS>I>9FaD-QuK-i9nL~?EjS>}VC5V$7$LoAEdRzE(ccKM#OM0&i9YHuHuBzR6$+ zv2o*qK^TY4W-*!ID>^-UT#Y@{zEkJ!-}DryDoiTW!d$+D#I@`3jY>PjWU}k3c-p(T!#jph+`Viy^ znfYFVFFJ<85ssnAMPdMaf#`*}5uFhd5k}4+Cx}OpgT#ICF5+Lv7UD*;b$?z0@IfF3 ze}{yIg@;GLk;|hZBO@Zh!@@#Cf`czz3<7kozn?D{*L!<;dV09Kxw^VIJCPk7NkjyO z&!0Pc=FI6+Cr=zde(dOx!-o$YJg|S?zP)>P@7lF<$6wpGZQHtK^QMg(H>_W?ED*8@ z47vzBg@gi65fPEZs3nmR;o-nfNF6_3wSLHd!_Ow*XWiNWhyVjeH}gx0WpFu>LM%th zh^1yFC8T1ch*$^}kn)LnNG_B^%0@mDv!F~Q1Dl>;`RP+?G&p^YKV;z>7!+F-TJ5Rx z)OuEVXxggPAMgX_{((Um;o$Ec#=i^Ktp!sm2;lG8)zxyCP2yN^!SocK6Zb;pWu8kV zfv;AJaT_bWji|JgR7NN*r7)Saaz~02)v3aR7D^}52u!1;rGH=`P!p9pmbEP@DPuC} zB;3x8c9jl@27?~KKLEEPm06aT>CK1~GLUnj#nK6^x@HJy3xdH8#_gPGK6FopD{d>n zt7nwN02C`=TMk@PD2_nWiRM8MW{^y5t-yC=tdM18#Bxicts|8TOx@_w3`;sFfnL?p z-(PR(SPrTKG#Mn^%!PiPL0}uL2)=qNQn@9i95Z7vh*U?Q=1lizkeFUyn)(CRVq&=! z1-E6f7znT>)0{ws0-5A5Z2kN{16u@qU9g`ClnF}LUZ?+Z-BTH{zUrZ0gpe2=p+cAm2 zj!buEcrg80PA0Yl?+dsskzxgCB4EpAGm#1suyta%F}+zNrV|S>*slTF!2SYWFA7Yx z0`^p3Ujei)G07}vrWuPxX1cQQ60g;p`&`JvszyPmmXy*m+#IIGGhK{EtNa1GeR9I5uqCK6!t>Y?U4Z}q5Yp)A%dx%3ap0N^C*xkbe zJA+CkRuHH++_$b=wJ~NhVbj)wF4ta``Y{oX6`KtT1N3ogcY`&l!urZtyFVOGdk6XZ zdjz-zb-xI1li=PK6yWdc=d_D_?NuRg=glN>2mqkgpKj^u?v6VnR#?+2E}xh+eDkBE zPjIUFr%!30kTf{mJR?0Llbl8T+&w!dCo4G>{7-7~vmnIj_WNR>=4Dh{jTMIA>gI;G zUPVV5ts?r=>>;Pc3jA|DtZb_SlT|c;H6a2xg^YHtl2$O)RT{NiKn>aNclULf804%J7UQC3EVX%OS7!iDQ?Lq$(pYZDC>%1xzzv5%$5swG&u$Cn= zUAR^p4p!OKt5$&GIk~!Gif{#@R~&juAOj?T6fnMR0j~f`hyV_Ns6})=QTd0s=kGqe ze)J-j$tf-V;C$XcE~$*|%e6Gsb8#{1b;L?oqbHZc3iDb$Sl6psS#kd*lOvKBJdIAG z78K^Z^g0s$t-{J@<>c&=0m@eax|mHPa{YCHP@=}Y%H=E75_5Yo^)uDWM0Pf$sxv-#BbV7gl&^>dh` z^Q|=BFBHj`q67hiUxzP>`Nfq%wBPAa@#}SauRl&M`24w;$rrHGBkz9vL}4d}obkV% zj+NAti={W|%9U72iDYv9x`^DO=7J;I0o7=tP4__qQe2`A(bE(PE4?iXpNtrLa zkbsBTEHAEQC9b*xS9Ns6R59T3%hH;v!rJevwL-U9h)>Y_w^8T4-V`w^(jHuTnE3Fs zOjQ1gbUHXL0~FVdYX#maVg<&e+Y?E+G?+n6D}w3mO|RIO;yBtRR4>n z{zoD>9bF6)wFb4vx{L7d5L%m=G!5q-(j}wba%VjkVU@3rnY8)WIfx7Uo0h6`` zCO*3u9C77pz|pCT@0Cj`DWBiG%21$HGDd2!qt}g>*)-=m4q$_WjARN;Au(}at#<$> z-Kk-4oA?=}xc}aB){1TCjvb7+7IcZcZm?alP$^^-Bqb!uz??oQ?M)~gaOY(~jfdq} z6$ocxI1P&)dV2<^s)}XsfJm(LWD}TJ1Oo>H0D!D{@bgboXE`jLF~#0J_8NKJ)D;&+ zRdOMxEHmM?7)IMyiOXLFxdl8Z0PW<+wdV7ASVJvewgmHX{=Cr(gUc{pXhcFVc!5=B zYH+(7j-vNh_xgFZ{h}GehfY1!+)e146QSd%Kv#6X_DG`-C3-yagC;@Ir zT$oP~8ogMZJ%@XtgL%1xnu-`*ASwt{WSCA%U)p}uxaq4Fj2$_8^3p9^7tGuMCMZ;? zW#URoX2RXuaWB$o0&aeMbU@6@3NqK44L(2v56iH6Se-t54yy;9jxf418OF;Y#>p;l zya^2EEKPL;d#+dt+wte81^#BY@aWqu+fvIPyY3r&Kp0g0V)fly)ZWlsaU|Fl@;b>rllsOWahs* z?RB@t%aSFyms6)cX|)oVfiT;fdV!_=u?GQA7qv^u!z z69hQviCq_^Od{m5Y30R*`FVNyl*H3+H;q1IOBMqk@JVyM3nJ4Bza&^aU`bmHOT->E zdZKFYDLsbHUT!~q^r&$&r;qJ#`R!$%!2@>bH7Yr%NF|#|2TzO@yv(z1H-HBrenoH( zR>w}9#9T1Ih(X^;_)=Ir5P$H%D^Vr=IH~i9KONT1`EBIbDYGVgZ#@W1fYcGI5wt_K z4!iCO;6f0+z`K>kE3E{`xfvzW#@7|=>Y-b;nPTKC<+S?kx& z9XDe1lo@~g(%ozqM~mu6V1<-$;pzZ+FEsq^Pj;j;F{CR`8 zM5GsoWxeETMFnZ#@M-pI9L9|tJ#pI95nZ~idyb+oP)AVfYOMI+Ay1_s$}OtPh&AFe zFbNrmA31gm7spCopL!K1Y+kpi%a<>lI(+2#=~Ksi+v&GwQnVVu%iaa3gVFLW}dgn^b=rexn5+5h+XtJX{# zJ#yUC8K8TN^N;~*orG(-=(U`=ZFx%BqJ=;TKGYUdVloldk8FMNZN3rI<`i-P?QIOxxx2 zej71n(u~PNZTjy{M70>@OV)W9nhO*QG!|fRF{uLwlMUsvGDua5Vc|C-u`2)ksIGr3 zTx>ge#Hc@JP94#wio&#^NVv{pg`6D6RoM&(4D(*9Tto7=204xT_YuAWHY290gqeBE`M}*z~J4k zex4rAo~~XbPZuu>Z`YF-a4E39gRzNv?A)~rD-w(K;=#)V3Ky5+2w{E~S}s!}208J>k`dw7lB~_IQ6xffJD=$7Gij_f(6lc)XEJwMK6L%b-OoDic%-^jZQwFE_hV zz~?ebvtB-UPnDJ5IIuga3dLTVN1^6il3Sf34d43LUmx-IVY7vDfxf9Z0wM3|bD50C zPJi+s2|U7zOJWb~j*wR=z(fP=@!GM<4fHu z+`lF|qxi#{4`~#!Od-PcWE#0#Q|*C5)s9t=)){T9#q$LS2ARxMaND*ISP2pKPX@sg zY)MhnFJ@DMKHmRWA(n!5KJIUxHgeXl+|2P z%gtMj%7cx{9Ob*MJt2$r_e;4v5ty_g72-ves+FpDex&n=BLGEg&clh=RI@6bn)|}j z3-+=0^1hy~#vK61UpUxmD0)|;19sKzA?^Av4@ebAVPSWXNP;^E#~j2R+qic9`VAW# z*W0XK`$UC%P|>dawFBO5y>qumg390lk|SU^SkvH}w`{?kz@Xk;@CHA@)BG4TLz zHpd(wK)<8@g0d=~pNY-o2m~-60uDMF^;Jsc{ex>(xU8~Sx;#z=UQlVYD(3xDr{Qzf zXU>AhZA2=)nrF!Eu1%!Ca^k;X&Y@)*d)0 zx(*shtddF*Fmnf%5#?>b1G1yqOapG@1Td`-D>=+1$}MXP4sSF!s_NV2NI8dF38wi~ zR>HWhjX_qV1T%rK!Xi}&xDP{Bh{ggR5|L3twHB>7;|!!B1!5{rShr!r7wW_I=P)?f zmnlrW6S%Mf5g#wKNC9rsu&6B<3xTH-SW1?)1AWR?3ruE|P-@ z;ojTHU#qTL_YOn}%tkm}an)T(G`z(4>?v>+J7TT9e^;0o%!7*Ev0M-igE*Mmk?B6Vfo;?*Z|tS+CNJ;wG-U}P9EyiEl5(Txxp z9_Z=m9|cF7U-b3_`4I88^76lWJtijV(j}+hwoWU~-BQ*ST)o;TNVt05e%kZ}c3un3 z?QCuBkcE)l1zR(_h43P1p|c%f{`_U+J9SQnSDDwGeaG+6j&0kvcx^V{vUTegWHb0~ zxz%jTW_S~{*?9|L!{)<559^#wSg~@Y@pOwv(OxdjFI@>v&R$oaHeyI%GC2Uf1AP_& zcO5dyE11j5qg%j-J>0XH@ToB&Irxsa-k z7sAqI%igH<(P#;tAZiMR2oUgSkBAY8nN;cyd=XVdHOU}g+DR5KTlN}!9mH;`4G17o zG8a)0^$K_azBqsB(gx2*K*JEhodA&`auA$K4{$c|i!Qo&$&y#5-oc|C-mX~ju}ULg zIy-hY=HE?41Win;4RLs}x$$HxtnS#!;GTr=>z++ikd)5gY^;Nr+&2mKix<}?Km?uG z)IAXto}_eCk?_KQA>iQfwEz|u#^xs)%1=^w0WkQKWUT#{rxQWjVW+#{r<4*gLPLlhAQ@?mjm}h6##Ho7EB)Jbb)#NFL zFwfQ&oGBv;tb{^AB@dgwjfFT_;skOHQSJ(w$yH$qX5<(imCfhd+CFtwn}hY)l!59e zDsu^*7cA!5+MZQLsN+@UnfM>t&R$?^>-xzt+cn2G*CQ_ie8abRxC|T$fS?65TWAPa z>2U$Y)@;Gdi%`b}3+68XT<_eubLPyRJqxT|V?JZX^y$QDW`F*POeIe7n~Y3Brow+B z)6Az&pD_cT*>2XX*|X=&nG0r@&L=K_=An@B|BzOqqLrv0^QYAKi%szqT?{W&rO~@$Y#xaS3Zp0E$50pfE2d$8EcBd`OB*!2pU!fzDBn z>jNnIe+^Jz&HR;qU4G(b46^sYP7f+I`N=!bPkDt8-Mz0otIJRH`vH9GVXYLU4Qm9Khf`NegboVeYpbN)&yGmik~<#ezI$( zypjs|iA;>2pr>BB5OC{7U4Eh;{1ra|9Ox-4%z*{=VHkgp^ff>6^THGn&QH8blH>fu zyDL5+jqnqljr>H72N+O2*az;00g6jvEe23zy?UbuD9YYl2?%|V-xxsAnPC7ZhMYFw zVl{Wo#`%fD4=*x{%jtlhD18+h5uH%nC_nK9>tkAxrT~h2cj8`VfJIL8KirSF*(gBK z!AKq8*8`TBW1rA*5Tt2<;(h#+M~|O>%%x_%e|zUzBLGERCl;6!;AKqH07WSPDB|M) zK=C;%J?(Yey>|@)6zz>{19nAVsRfSa7%+|I5ERMpUOs#BG&wV|AT#`Wg9L?jtrtXM zj)60ECz1g_@%n6I{Dg^< zHoyri?}POe@M*p|_ync6K#xzH!9H5+ag(p`iJAb$zA(eGemL8pY$iUzVbQ^gg-ziT zMi)3VgUI@T&{An-A18Hb5qhG70YMPpybLVuhds$C)GdThv@-$@IA79FpN}*xgio}u zAskHAwJn2BSl5apfO5b}4tn&zrzbiX=n1J9<4Is?ZOy$*KZGZKFd`42g4oh;^05v`*ZcZkLl^y4@cKknvCr(uYOiWZsDJT^QStT!gHq4nk@*A7Q zH#BJV71W&5G&ljOB@l?&xy4K{U5Hnj;J#_U5j{eesqv;-&$pHcLgTFGM2D3qd)G2St!M+}`XXRhBIuelbp z7VXD~3sb~lM18mfC<(tbub9qZFldDz9zA)Tl;S%4mvwg^-MfDexlexJ{LsCoc}&HA zt(TVo-;>f)7;Gl3G$%3cMgm2i>ookQlQF0{-?1(!F|=M%LMY-tye|+is2^^}zNK(w z;?Lv}gOAElJtu*|SME9^UxtAV;P!8PO>RO;d~cuwPIASZj6EwNlCobsOGqvg%T=N* zOi!khE3{rHz$A3dz$A+Xe1jGm)D#LnSn3x5_%QfEAcSEi z#z+a3kV#@$@}!zZNeLr^agwWgyRipkvF3I$mk*Y=6zj#0NOfxU-QCOVU6$A^ba;S6 z4Am-X$kOHTD(e-i&OK2!ib-@cHUvj^>u0Ne%luM=a`3UClURlq{fJbn)?AwQ!?!Nq z+4Sijs#jO!pX&E5Jji;$cS|A^O(PPWaRA^1M;qPy``y_B34j=coke1q0Bak}fjVT? zFWKywVpI}=S@X(ISDp9=N(%EC?r_W6{7&9 z1}9ZY<#WeF`F7^>wI{ z%A_Rl$N_^dgb)r%0G7`ZpsLNHB#u(R&+}A*{|8^#F?ytfl%Ih$jaUOnO*M=!sEbs$ z0m}#@8dwc!08vSA9wBicmkH<#y>cgv8s(pHA>~>H4ckB?XBkSXQL{)N7o+YK7^h>EOh!>w3dzN0+H`r#zt6TY=qs}ph!3zjxdXi zM4~!HMn#3VpFHk-`AYPaAP+ZJk{i(-Fcl z&Hd{Sv$Hb`p7@X(U238!LV|YJ<4I;Qi=LmGlW{xp*&B?IaQ66DgoN9PfG6pN#ravE z^NQ0SdS6c|D$kDfbZK~*i3YI)10k_)*X8?fGv2;R$}TF&d*KtClty8tTyY8fmxRQT zt8p*mqoNbCiV8BG_}xx=RV1Ok4Ra0p_k=_g?D{Y%J2O7Y^KMdHmQ+~wCeW?L2#Emi z;JeRXzlpl|JQ*V-WP+l{!5)_%wIm@Cdo?`jR%mQRdCJrGr3zJLUYxIA%MlWx?gtJB zy)I*xrN4LsR+x~nGwufZ$2@IOLSnLAOo_CTn*H`wI+)cdrKMgE489%Tl7z%yJDiXx zOn!x}FrkrDyotFK(ZYnpMLi*5Tw+30`aU)!;y)rJ3JipVSXlb{&ebdb2_ZqvdUfy4 zqlEMd0Xr}0N%XB3jV&=z7hY&CAt7X!Wxap#^wFc|iFwq_k0}rSBSNAqH}&0%xO$%&(BPGpYZ(Yv*h%TB?S@x5g|b>%1KZD@b=Az7P7uW#?)|K0KuI3b~sM=c!C zfApfov&a7P20-Hwo9=H;(^h%=FQKkch?BC5mnek?4=34HzP!{Osg@?RCQA2cBzx8!`5~ zE(1JrIh6=LY2TUW!EZhzp?SZ~E8+RW8&M(74xJn`NW@PHJ`(&WCOp8)`PAkKLwv|%$4s%c^RxA`vzWhR zf8FIIhSkSMREi}0Yp}=VTah6b&aPju_EgwgpRpr0-+%Ie^pG6q{K);W#q%3@!!$`p zaD`I7(_fL-uUzstwQcbd=KBh3)PC;BVD?|y{x;xxxFRqGfOBk@DWmd4J1`+wbzh#<}L&q zsEv;vjZhR4e;o>supT;M{nh595scJ0hRzg?$Z{Dw{DcIc5sy#*wS~0JZ2LBNyTzt0 z&kS?~`|yQZarF~er=p2fB=9v8hMr*a0m)DaI0geAp?9GHcmy{68e2uefJcyZ z&0Ry{D5a9e$A1ylKu1UfS{Pl7SU#%RG2(SwiIzr4hC@U1fw$r8%|8$vVHGVS#Rmvi# z{7Ifkm@#{CbLfaGi}-kH z`)2QgveL2(4s&O@%z@@2bF8Lq&Eir@!NtIg2X3){`MVM|6}K*Z*4tw2O85YY-mv;q}wJqVGagF!ieo^Ny|1oHblZ&gnho=|#>1NZD`*M zKHgrQ9`0@~U^_Ck&6ghQ`BsK}4g9uWpKp3~@7AT0 zO?zw0w#{&BS`@Q3Z3)(R8M^i8^-Z6?SSbc!#rXM`Uxy4CI&|2u;loE5w&BBu0k1=T z{pIJuKmGW__uma1&>wT%vwPRhdf(<|rqa#dZ(~ld#0t@=bJuR&dxBzM<@k2Mz=7Wl z8ub15-~XWBz}}!ig9Z*9FyPz%{rX~#dvxpCrBg?&+60R>|Il|$Db27_ShZ{4!3LD0 zOV@7Qy7%bWvsbTg@U3@m{6D>V_3YWBd-rZ#L5(}wbZFnMMLgFO0oySH<**=FT3T7R gYu6qW25cSm8@Ah_efxIptgS6A32n{W{GBTQe;3Xj<^TWy literal 0 HcmV?d00001 diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp index 5e0dbc7c13..0c38c9d0ac 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp @@ -308,19 +308,9 @@ void DIALOG_MODULE_BOARD_EDITOR::InitModeditProperties() m_CostRot180Ctrl->SetValue( m_CurrentModule->GetPlacementCost180() ); // Initialize 3D parameters - - wxBoxSizer* BoxSizer = new wxBoxSizer( wxVERTICAL ); - m_3D_Scale = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Scale:" ), BoxSizer ); - m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); - - BoxSizer = new wxBoxSizer( wxVERTICAL ); - m_3D_Offset = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Offset (inch):" ), BoxSizer ); - m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); - - BoxSizer = new wxBoxSizer( wxVERTICAL ); - m_3D_Rotation = new VERTEX_VALUE_CTRL( m_Panel3D, - _( "Shape Rotation (degrees):" ), BoxSizer ); - m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); + m_3D_Scale = new VERTEX_VALUE_CTRL( m_Panel3D, m_bSizerShapeScale ); + m_3D_Offset = new VERTEX_VALUE_CTRL( m_Panel3D, m_bSizerShapeOffset ); + m_3D_Rotation = new VERTEX_VALUE_CTRL( m_Panel3D, m_bSizerShapeRotation ); // if m_3D_ShapeNameListBox is not empty, preselect first 3D shape if( m_3D_ShapeNameListBox->GetCount() > 0 ) diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp index 6505496345..c8b532004d 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.cpp @@ -307,6 +307,33 @@ DIALOG_MODULE_BOARD_EDITOR_BASE::DIALOG_MODULE_BOARD_EDITOR_BASE( wxWindow* pare m_Sizer3DValues = new wxStaticBoxSizer( new wxStaticBox( m_Panel3D, wxID_ANY, _("3D Scale and Position") ), wxVERTICAL ); + m_bSizerShapeScale = new wxBoxSizer( wxVERTICAL ); + + m_staticTextShapeScale = new wxStaticText( m_Panel3D, wxID_ANY, _("Shape Scale:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShapeScale->Wrap( -1 ); + m_bSizerShapeScale->Add( m_staticTextShapeScale, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_Sizer3DValues->Add( m_bSizerShapeScale, 0, wxEXPAND, 5 ); + + m_bSizerShapeOffset = new wxBoxSizer( wxVERTICAL ); + + m_staticTextShapeOffset = new wxStaticText( m_Panel3D, wxID_ANY, _("Shape Offset (inch):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShapeOffset->Wrap( -1 ); + m_bSizerShapeOffset->Add( m_staticTextShapeOffset, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_Sizer3DValues->Add( m_bSizerShapeOffset, 0, wxEXPAND, 5 ); + + m_bSizerShapeRotation = new wxBoxSizer( wxVERTICAL ); + + m_staticTextShapeRotation = new wxStaticText( m_Panel3D, wxID_ANY, _("Shape Rotation (degrees):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShapeRotation->Wrap( -1 ); + m_bSizerShapeRotation->Add( m_staticTextShapeRotation, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_Sizer3DValues->Add( m_bSizerShapeRotation, 0, wxEXPAND, 5 ); + bLowerSizer3D->Add( m_Sizer3DValues, 1, wxALL|wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp index 0a57dcca75..9d1de2b965 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp +++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.fbp @@ -4435,6 +4435,288 @@ wxVERTICAL public + + 5 + wxEXPAND + 0 + + + m_bSizerShapeScale + wxVERTICAL + protected + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape Scale: + + 0 + + + 0 + + 1 + m_staticTextShapeScale + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + m_bSizerShapeOffset + wxVERTICAL + protected + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape Offset (inch): + + 0 + + + 0 + + 1 + m_staticTextShapeOffset + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + m_bSizerShapeRotation + wxVERTICAL + protected + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape Rotation (degrees): + + 0 + + + 0 + + 1 + m_staticTextShapeRotation + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h index cb655d156a..79806831cc 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h +++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor_base.h @@ -104,6 +104,12 @@ class DIALOG_MODULE_BOARD_EDITOR_BASE : public DIALOG_SHIM wxPanel* m_Panel3D; wxStaticText* m_staticText3Dname; wxListBox* m_3D_ShapeNameListBox; + wxBoxSizer* m_bSizerShapeScale; + wxStaticText* m_staticTextShapeScale; + wxBoxSizer* m_bSizerShapeOffset; + wxStaticText* m_staticTextShapeOffset; + wxBoxSizer* m_bSizerShapeRotation; + wxStaticText* m_staticTextShapeRotation; wxButton* m_buttonBrowse; wxButton* m_buttonAdd; wxButton* m_buttonRemove; diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp index 1268a15f04..f69176f329 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp @@ -151,18 +151,9 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties() m_CostRot180Ctrl->SetValue( m_currentModule->GetPlacementCost180() ); // Initialize 3D parameters - - wxBoxSizer* BoxSizer = new wxBoxSizer( wxVERTICAL ); - m_3D_Scale = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Scale:" ), BoxSizer ); - m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); - - BoxSizer = new wxBoxSizer( wxVERTICAL ); - m_3D_Offset = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Offset (inch):" ), BoxSizer ); - m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); - - BoxSizer = new wxBoxSizer( wxVERTICAL ); - m_3D_Rotation = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Rotation (degrees):" ), BoxSizer ); - m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); + m_3D_Scale = new VERTEX_VALUE_CTRL( m_Panel3D, m_bSizerShapeScale ); + m_3D_Offset = new VERTEX_VALUE_CTRL( m_Panel3D, m_bSizerShapeOffset ); + m_3D_Rotation = new VERTEX_VALUE_CTRL( m_Panel3D, m_bSizerShapeRotation ); // Initialize dialog relative to masks clearances m_NetClearanceUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.cpp b/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.cpp index 1cf349199e..fd62e5b8da 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.cpp @@ -250,6 +250,33 @@ DIALOG_MODULE_MODULE_EDITOR_BASE::DIALOG_MODULE_MODULE_EDITOR_BASE( wxWindow* pa m_Sizer3DValues = new wxStaticBoxSizer( new wxStaticBox( m_Panel3D, wxID_ANY, _("3D Scale and Position") ), wxVERTICAL ); + m_bSizerShapeScale = new wxBoxSizer( wxVERTICAL ); + + m_staticTextShapeScale = new wxStaticText( m_Panel3D, wxID_ANY, _("Shape Scale:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShapeScale->Wrap( -1 ); + m_bSizerShapeScale->Add( m_staticTextShapeScale, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_Sizer3DValues->Add( m_bSizerShapeScale, 0, wxEXPAND, 5 ); + + m_bSizerShapeOffset = new wxBoxSizer( wxVERTICAL ); + + m_staticTextShapeOffset = new wxStaticText( m_Panel3D, wxID_ANY, _("Shape Offset (inch):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShapeOffset->Wrap( -1 ); + m_bSizerShapeOffset->Add( m_staticTextShapeOffset, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_Sizer3DValues->Add( m_bSizerShapeOffset, 0, wxEXPAND, 5 ); + + m_bSizerShapeRotation = new wxBoxSizer( wxVERTICAL ); + + m_staticTextShapeRotation = new wxStaticText( m_Panel3D, wxID_ANY, _("Shape Rotation (degrees):"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShapeRotation->Wrap( -1 ); + m_bSizerShapeRotation->Add( m_staticTextShapeRotation, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_Sizer3DValues->Add( m_bSizerShapeRotation, 0, wxEXPAND, 5 ); + bLowerSizer3D->Add( m_Sizer3DValues, 1, wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.fbp b/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.fbp index db0759a5fd..aa3c448b54 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.fbp +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.fbp @@ -3640,8 +3640,290 @@ m_Sizer3DValues wxVERTICAL - public + protected + + 5 + wxEXPAND + 0 + + + m_bSizerShapeScale + wxVERTICAL + protected + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape Scale: + + 0 + + + 0 + + 1 + m_staticTextShapeScale + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + m_bSizerShapeOffset + wxVERTICAL + protected + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape Offset (inch): + + 0 + + + 0 + + 1 + m_staticTextShapeOffset + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + m_bSizerShapeRotation + wxVERTICAL + protected + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape Rotation (degrees): + + 0 + + + 0 + + 1 + m_staticTextShapeRotation + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.h b/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.h index 02ed724b28..9491f0b965 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.h +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit_base.h @@ -90,6 +90,13 @@ class DIALOG_MODULE_MODULE_EDITOR_BASE : public DIALOG_SHIM wxPanel* m_Panel3D; wxStaticText* m_staticText3Dname; wxListBox* m_3D_ShapeNameListBox; + wxStaticBoxSizer* m_Sizer3DValues; + wxBoxSizer* m_bSizerShapeScale; + wxStaticText* m_staticTextShapeScale; + wxBoxSizer* m_bSizerShapeOffset; + wxStaticText* m_staticTextShapeOffset; + wxBoxSizer* m_bSizerShapeRotation; + wxStaticText* m_staticTextShapeRotation; wxButton* m_buttonBrowse; wxButton* m_buttonRemove; wxStdDialogButtonSizer* m_sdbSizerStdButtons; @@ -107,7 +114,6 @@ class DIALOG_MODULE_MODULE_EDITOR_BASE : public DIALOG_SHIM public: - wxStaticBoxSizer* m_Sizer3DValues; DIALOG_MODULE_MODULE_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Module Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 486,462 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_MODULE_MODULE_EDITOR_BASE(); diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 2897af7bb3..eab18aa97f 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -591,8 +591,11 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, // Deflate: remove the extra margin, to create the actual shapes // Here I am using polygon:resize, because this function creates better shapes // than deflate algo. - // Use here deflate with arc creation and 16 segments per circle to create arcs - areas = resize( areas, -inflate , true, 16 ); + // Use here deflate with arc creation and 18 segments per circle to create arcs + // In boost polygon (at least v 1.54 and previous) in very rare cases resize crashes + // with 16 segments (perhaps related to 45 degrees pads). So using 18 segments + // is a workaround to try to avoid these crashes + areas = resize( areas, -inflate , true, 18 ); // Resize slightly changes shapes. So *ensure* initial shapes are kept areas |= initialAreas; From 8765d96c4baa321e6437ad6fba31344ece694600 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 28 Aug 2013 09:29:48 +0200 Subject: [PATCH 02/29] Add missing file --- pagelayout_editor/pl_editor.icns | Bin 0 -> 12539 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pagelayout_editor/pl_editor.icns diff --git a/pagelayout_editor/pl_editor.icns b/pagelayout_editor/pl_editor.icns new file mode 100644 index 0000000000000000000000000000000000000000..c84b0a172eacb81c64f5aa2d6de389d056b521b9 GIT binary patch literal 12539 zcmeI1cUV-%`o|a0m_&^&YBVOfDPEJ@B#N3~H)@w568?wy?dIb7#)(0?IG}-sZwM zA4_iwnoJ~o(Z`EkwD!VSez0x-=o>GLn#Fb820cdr6l^C_qAxl65tgb=$ONZeMExK zVvqn^%d)|yj=1FK6HrD436PITK&(ZpOg1(FZ&);=j^AwftR9u%6>p+R=52k~w|<(8 zs_^JZIR6%=%;Vepw{G92`1w+Nye#V)YMU&A^YaR_pQION23!ujI3&2zPd;ZAgqB(4 z=A0>H@_83p}nT`m!<%ub)WVt?rH)sgx8 z`}*I*+0YC%^A{=y3LBGy=X*A3=g$nSEzFDeyX3E(zjyebk;Q}5u$#L1V+)|;@pJQU zC@6n2X8vj!11x}6sr1yC1pw#oyk^5^b=vu#?yfN1^m&qQ{^o7TF`Ku9-1hbLyL-pa z-}_AEEyoAee-;%M=Otv7JPrKacVC0TzTfe;BNVjoa7ON#e71yhnMMu1myI?*Y)U&` z0p@Stc=6E5U0xN34qIdI|1y66kN^A+OZ$EMf4{WmtThg2@H(pdQ=&0ABOFfmh=O$* zjGHp%8C9akaZ^U)C@45GHjb)M{+DCppo#A1o>8^>`DdW`U;eYQfg8f~MTRk68=?)Xju}1o8i21O)xIj#FYxr zmqOf~lhOWwQdyRnm8Feq>&ww9%Z!RDZbxW!zt_F`s`S)!O?^#Vj=H8CzNlVRQ zx4VYbG~{aP3$^vpQy2ErB0~L%CB2z6w1P;jY0H5P@HGMn>i2>91<&XMW(r1eJ*vzl zC$Z3xxJ-=Zy!V6YQnPcWgKA#;)6!N>X29b+AT9*;5s4Gp^ZDj|E50>eQjW?b?B?wF z%x5`|Q=K>Ug18XOP;tQc$SRY~GlEcsS|MV0)#PQ@CkA10flw?$uP@oZVU_93lc-XS z0s(iRyR|pP9mEAZfsl_zF4}MU)s7|WcrcEtlu{vYSYG7myr~Dod8+0wUjKgYms`Gi zzX??!>UU98tx|v?S7-!0G4I>u`&Vw5k)HQ&rm2W`S0ozXd(CcF4_x=4`r(+oE?8{r!W1b87qG)I7z zf}wWuyZbpqe6Q6v2zW99ah^+b1R3t+bPsa-OYAc~~DC2B@#O*V2U&>SeB=t`w;_QdKr6mr7|hb@i%B59f89-@eWl zaEHazOFZGlU3>TJ`FUF!DwQ}NK4HzSb0=)-%o~)lhKEJe%RFJI=WTCq%8gpJRF)G% zO^|}=ZEWN-hFEO2Fzzx(s3xKB$Yt=IpyfA+>xvolAqJDlkG;s|rawmF-%ChHj_+0# zQj-$0{6M@yFwEl%1oGtTVzGmnCEjAO)zK>Sk)tcg?e|+mlWUY)US43MC)radf7lZo zW?r}V47fog5y>`g!56HE=2I-sn44RX&KOvn##~o;K6e9s$iS^f zb#A50B{I3zt)lE4raIjzKGwj>cF=Mc%qf z?F{uPFUr8&IwmehtB;32bP935($IG&sHQj-x^*-T-AXRSKAr_9a>mal%Soy&20-<1H zyY>o!UDeHBOypKzcfN%8?TU%q%ALfmJpwlB`?nX|I$z_~9-gRn(^lx#_d9@F<%oiy zoUc-8?Ap!amDGiquKi|C1}X<;b$Db&Rm2yi=%)WPnWR0 zgV8f|4(bLJe}eN-ym`NrH&x}M!6Z0gDzl(C10Wge@!LT588ODpSNb5W@@ghck{fqiUa zlYq%!53{A9eGxFMfkKX;t5s+PG%Ry~!DKPTH&?QGiILIKF)^`^qdU<*?Va&%wl{%c zg&g=s)xH}ckznLg82nWyAsc2)$`^ali2 z7w9pqTb|Fun(&0D%nqN3imDvFroD45o1WdKs`7bU`AnZ_51J{NC3UF0@NQzCe$xWP z=9IOui^Ah3G;QF;;^4q&LPQ%hB+Jpu^=zG+Rdc|MG_BOB7KPv2!9wlIpGm!93DYt5gq)TH}-bhMB5$>SNg37 zeznB_yPkQ^V5diyLhiMWBg~0UN=i<7(xH$@ijq<@q|mSYJxep>e3s06El=D3q!O4w_`BlUkf`0W{H|kfw zcIejY(-x&-}x+RD=UfYz;6HsH8SjhwQmL)H!FDe*Ms20Unqj7T^aoTf`_T;YPG0St`HA5 zp9{)zn@BZ7T^5rTmn2}f7utkmyN;2G$2K-|D5`HrR216T)SP4+_0&bbZnjFLeAvKL zvice$s*2kmIZ!7M&QYnZ-LGM=`uf=ock^g8igOZaOp{~gF<13ucSw9`dOeHT7Ftlq zttYyt67@^xb!_pXRQze5-Px5MSdzeHmtXbGaMq_?s8otJU%lD*#5XKDrRaWVWm2n* zQE)jZi!iDdjtt@*rE>qeN8Ajr#}8dBqPpny8C5E2f8v!;aCf20JxIPTU5k|db9b3} zU5WG$FnhmP$fgzKt5xEz2&bs02<{8byMiwZ>cPuWC~9YK+xhdVEk5Da>u)N=oWANb zv05phJs?vNoYQl9_;MA)i;UMES+`>CahvadRx9NKc3VzdQX!q&5b2YI!(n=CF^DDD zVoXg-Ga)Xot2E<&8m8xJ^qL7c%s2h@`{gUQu3a*_ z1>6=KR?0=30a|roR!VAhVQpY0=wJY=pq+8n>>qyIv%+}O=1*okg7;2fNJ7p~M`KlK zVL@f3168Nj%vjntZ_UPoYmC?L_fX=K0m#kyk~R;)4oYL*EeC<#D`sF$eJYMl)0 zf5&@U&9<-j`n%N&7O)gh=M0Vx3pJ8qI7B{q-VcX&Enm51{rfYk5KKZ+6SNXKl<*2> z?fBuRmByR4{Cx%mJ980KZfZ>%K)~Vl&R@0m@H*plJHME@TMq6}2ugy=Rs9au37rj^ zco^bxatl})E9ZW|2P+FIh$^Cb0jB5&3g$CTchZ@aTi3iht3@h9FvSg(rV9`s?(7$E zSx?Vx{&+?dT+C45taMY&*EGOl4?pAbhM7b0M`!LWC@e&ZkYaKPsdO$D?qji84LlBO zh~De9^kRVRJY8u|8;8vp=q(D$w!P%xN_Kl!6JWBQ4X_!5&teKVRkn5_xI1B85*4n> zC0fbQyVsmCGGJ1meg&~JsU9k|Bf!U6CQ zzM()M#mijen$bNQ7!?8?SSX-hL}VZqBNDvSRrcO_xNvhZ71r%ARPp$2EiJ9BG#b)| zv`_7jN`=+c&NT~9VOsjA7-&JCj$}(C8;OKPA}lo5Ds;WF%YlNcQHY^pnt4Rfu2tlu zWF*BPH4UFWEj}5mqU!28gd}~;i2u}rc<{ci;DMf4ksBBJd^$% z(uIeNkZuUh7<;u~$&QeY*CYd^YZ)Qk5J=z)su}9ElNT-g`0V!Lb2`%Lkkv+P+YJd`E*%Hd-QcJ>Bb2G>1==VydUK2f1hNLPoo7BwWJ%T z)Q~RS-Zd!5^LQa3owts37?q9@Gg%hh3N9=m2wtgk_7b>r`z)T6%GL8O9sH zss<_pI>cNpVc+6ATFmu8$^jTcx*XJiaaYh|vj& zq@T2G;Q_5e*X1x!fQ6}5^pTcLKL8nbGdU$C6+>J`v=bpSGwU9~7xBaU8wKR$WfI+{ z;`jb1Ar}#HR(G6xVHejP=L8+_I7d6LJI;;c0-~CsE((kciW9IqO3qIPxq-WNO+AUe zod9x|Cxe`llH0;)tt+@wRni_a8RV{bSry@3n#f_7dHyxzq9YT$x~fuW(xH6Mmw?=fyPfog%qo?nFU9+1AP0_fZH3@C zC+dv#e_6<3$2op0HQ*&7*PcsFF6!sjXFqsJ$hDSbB~tUdO6tR27IJMh#o1};HATJm z;BoFHAlKPgT~=IFRqOcDkfVX)9PKJ})+@;U4?%9b@$!R{Lay;(5_$Eqi6M8_JwG{o z@3M&@cQ`dICfNJC4`-OhQSpzFC**ii!U*Jgf6Ao(>Emku$wz@EBan-^8XxL^!{OkU zu_kLh_L28%AlJ`gTL*>*cv!9fgYnd4s}5j@e9U2vHMk}!$aUAgXM91n$<`5mjXliu zF)35lnr(gpAqO=hqOp)$iJM~1z#s=C03ioIcKKu~9YU^{@Q=la7GHgg*Wb<4LJsPL zq90us;Q9dMatR9-+v*_K=rRJiER(GONkC=L2O(EU*tytC3%TAgkb|-bAqRiW*B%Ws zO}73u7)MB-mJx#|0meC!F5+#Cu0X;eQ|~XQ@xQA_broK0 zXu@Z0g$d*10-6friYG3>Doh+6AAuFdmrhdh->nB(ouqetp?_DeuZ>q_uQKo|1Ftgh KDg*xyGw?5jnr;XH literal 0 HcmV?d00001 From b7e9f8ce1e6cf3c3191eede9ee68a9af43d654d9 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 28 Aug 2013 18:14:39 +0200 Subject: [PATCH 03/29] Pcbnew: enhancements for blind/buried vias palcement, and save blind/buried vias allowed option in .kicad_pcb file --- common/pcb.keywords | 1 + include/class_board_design_settings.h | 1 + pcbnew/CMakeLists.txt | 3 +- pcbnew/class_board_design_settings.cpp | 1 + pcbnew/dialogs/dialog_design_rules.cpp | 8 +- pcbnew/dialogs/dialog_design_rules_base.cpp | 6 +- pcbnew/dialogs/dialog_design_rules_base.fbp | 6 +- .../dialogs/dialog_target_properties_base.cpp | 98 ++ .../dialogs/dialog_target_properties_base.fbp | 928 ++++++++++++++++++ .../dialogs/dialog_target_properties_base.h | 65 ++ pcbnew/edit.cpp | 19 +- pcbnew/hotkeys.cpp | 8 +- pcbnew/hotkeys.h | 3 +- pcbnew/hotkeys_board_editor.cpp | 12 +- pcbnew/kicad_plugin.cpp | 2 + pcbnew/onrightclick.cpp | 10 +- pcbnew/pcb_parser.cpp | 6 + pcbnew/pcbnew_id.h | 3 +- pcbnew/scripting/plugins/qfp_wizard.py | 230 +++++ pcbnew/{mirepcb.cpp => target_edit.cpp} | 72 +- 20 files changed, 1402 insertions(+), 80 deletions(-) create mode 100644 pcbnew/dialogs/dialog_target_properties_base.cpp create mode 100644 pcbnew/dialogs/dialog_target_properties_base.fbp create mode 100644 pcbnew/dialogs/dialog_target_properties_base.h create mode 100644 pcbnew/scripting/plugins/qfp_wizard.py rename pcbnew/{mirepcb.cpp => target_edit.cpp} (77%) diff --git a/common/pcb.keywords b/common/pcb.keywords index 93809b5d3a..0126f5602e 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -39,6 +39,7 @@ autoplace_cost90 autoplace_cost180 aux_axis_origin blind +blind_buried_vias_allowed bold bottom center diff --git a/include/class_board_design_settings.h b/include/class_board_design_settings.h index 75a22dc99d..9b516308b2 100644 --- a/include/class_board_design_settings.h +++ b/include/class_board_design_settings.h @@ -18,6 +18,7 @@ class BOARD_DESIGN_SETTINGS { public: bool m_MicroViasAllowed; ///< true to allow micro vias + bool m_BlindBuriedViaAllowed; ///< true to allow blind/buried vias int m_CurrentViaType; ///< via type (VIA_BLIND_BURIED, VIA_THROUGH VIA_MICROVIA) /// if true, when creating a new track starting on an existing track, use this track width diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 805ef45788..393740ae7b 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -101,6 +101,7 @@ set( PCBNEW_DIALOGS dialogs/dialog_SVG_print_base.cpp dialogs/dialog_set_grid.cpp dialogs/dialog_set_grid_base.cpp + dialogs/dialog_target_properties_base.cpp footprint_wizard.cpp footprint_wizard_frame.cpp dialogs/dialog_footprint_wizard_list_base.cpp @@ -172,7 +173,6 @@ set( PCBNEW_CLASS_SRCS menubar_modedit.cpp menubar_pcbframe.cpp minimun_spanning_tree.cpp - mirepcb.cpp modedit.cpp modedit_onclick.cpp modeditoptions.cpp @@ -200,6 +200,7 @@ set( PCBNEW_CLASS_SRCS specctra_import.cpp specctra_keywords.cpp swap_layers.cpp + target_edit.cpp tool_modedit.cpp tool_onrightclick.cpp tool_pcb.cpp diff --git a/pcbnew/class_board_design_settings.cpp b/pcbnew/class_board_design_settings.cpp index f1f5ce0c88..e98dc81ef1 100644 --- a/pcbnew/class_board_design_settings.cpp +++ b/pcbnew/class_board_design_settings.cpp @@ -70,6 +70,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() : // if true, when creating a new track starting on an existing track, use this track width m_UseConnectedTrackWidth = false; + m_BlindBuriedViaAllowed = false; // true to allow blind/buried vias m_MicroViasAllowed = false; // true to allow micro vias m_DrawSegmentWidth = DEFAULT_GRAPHIC_THICKNESS; // current graphic line width (not EDGE layer) diff --git a/pcbnew/dialogs/dialog_design_rules.cpp b/pcbnew/dialogs/dialog_design_rules.cpp index 07d6bef24e..c2a278aecb 100644 --- a/pcbnew/dialogs/dialog_design_rules.cpp +++ b/pcbnew/dialogs/dialog_design_rules.cpp @@ -276,7 +276,7 @@ void DIALOG_DESIGN_RULES::InitGlobalRules() PutValueInLocalUnits( *m_SetViasMinSizeCtrl, m_BrdSettings.m_ViasMinSize ); PutValueInLocalUnits( *m_SetViasMinDrillCtrl, m_BrdSettings.m_ViasMinDrill ); - if( m_BrdSettings.m_CurrentViaType != VIA_THROUGH ) + if( m_BrdSettings.m_BlindBuriedViaAllowed ) m_OptViaType->SetSelection( 1 ); m_AllowMicroViaCtrl->SetSelection( m_BrdSettings.m_MicroViasAllowed ? 1 : 0 ); @@ -286,7 +286,7 @@ void DIALOG_DESIGN_RULES::InitGlobalRules() // Initialize Vias and Tracks sizes lists. // note we display only extra values, never the current netclass value. - // (the first value in histories list) + // (the first value in history list) m_TracksWidthList = m_Parent->GetBoard()->m_TrackWidthList; m_TracksWidthList.erase( m_TracksWidthList.begin() ); // remove the netclass value m_ViasDimensionsList = m_Parent->GetBoard()->m_ViasDimensionsList; @@ -579,9 +579,7 @@ void DIALOG_DESIGN_RULES::CopyRulesListToBoard() void DIALOG_DESIGN_RULES::CopyGlobalRulesToBoard() /*************************************************/ { - m_BrdSettings.m_CurrentViaType = VIA_THROUGH; - if( m_OptViaType->GetSelection() > 0 ) - m_BrdSettings.m_CurrentViaType = VIA_BLIND_BURIED; + m_BrdSettings.m_BlindBuriedViaAllowed = m_OptViaType->GetSelection() > 0; // Update vias minimum values for DRC m_BrdSettings.m_ViasMinSize = ReturnValueFromTextCtrl( *m_SetViasMinSizeCtrl ); diff --git a/pcbnew/dialogs/dialog_design_rules_base.cpp b/pcbnew/dialogs/dialog_design_rules_base.cpp index d58d7b31a8..c9a61997dc 100644 --- a/pcbnew/dialogs/dialog_design_rules_base.cpp +++ b/pcbnew/dialogs/dialog_design_rules_base.cpp @@ -167,11 +167,11 @@ DIALOG_DESIGN_RULES_BASE::DIALOG_DESIGN_RULES_BASE( wxWindow* parent, wxWindowID wxStaticBoxSizer* sbViasOptionSizer; sbViasOptionSizer = new wxStaticBoxSizer( new wxStaticBox( m_panelGolbalDesignRules, wxID_ANY, _("Via Options:") ), wxVERTICAL ); - wxString m_OptViaTypeChoices[] = { _("Through via"), _("Blind or buried via") }; + wxString m_OptViaTypeChoices[] = { _("Do not allow blind/buried vias"), _("Allow blind/buried vias") }; int m_OptViaTypeNChoices = sizeof( m_OptViaTypeChoices ) / sizeof( wxString ); - m_OptViaType = new wxRadioBox( m_panelGolbalDesignRules, wxID_ANY, _("Default Via Type:"), wxDefaultPosition, wxDefaultSize, m_OptViaTypeNChoices, m_OptViaTypeChoices, 1, wxRA_SPECIFY_COLS ); + m_OptViaType = new wxRadioBox( m_panelGolbalDesignRules, wxID_ANY, _("Blind/buried Vias:"), wxDefaultPosition, wxDefaultSize, m_OptViaTypeNChoices, m_OptViaTypeChoices, 1, wxRA_SPECIFY_COLS ); m_OptViaType->SetSelection( 0 ); - m_OptViaType->SetToolTip( _("Select the current via type.\nTrough via is the usual selection") ); + m_OptViaType->SetToolTip( _("Allows or not blind/buried vias.\nDo not allow is the usual selection\nNote: micro vias are a special type of blind vias and are not managed here") ); sbViasOptionSizer->Add( m_OptViaType, 0, wxALL|wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_design_rules_base.fbp b/pcbnew/dialogs/dialog_design_rules_base.fbp index 54321e8484..d0808ee3ac 100644 --- a/pcbnew/dialogs/dialog_design_rules_base.fbp +++ b/pcbnew/dialogs/dialog_design_rules_base.fbp @@ -1604,7 +1604,7 @@ 1 0 - "Through via" "Blind or buried via" + "Do not allow blind/buried vias" "Allow blind/buried vias" 1 1 @@ -1619,7 +1619,7 @@ 0 0 wxID_ANY - Default Via Type: + Blind/buried Vias: 1 0 @@ -1642,7 +1642,7 @@ wxRA_SPECIFY_COLS 0 - Select the current via type. Trough via is the usual selection + Allows or not blind/buried vias. Do not allow is the usual selection Note: micro vias are a special type of blind vias and are not managed here wxFILTER_NONE wxDefaultValidator diff --git a/pcbnew/dialogs/dialog_target_properties_base.cpp b/pcbnew/dialogs/dialog_target_properties_base.cpp new file mode 100644 index 0000000000..4027e64c0c --- /dev/null +++ b/pcbnew/dialogs/dialog_target_properties_base.cpp @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 8 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_target_properties_base.h" + +/////////////////////////////////////////////////////////////////////////// + +TARGET_PROPERTIES_DIALOG_EDITOR_BASE::TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerUpper; + bSizerUpper = new wxBoxSizer( wxVERTICAL ); + + wxFlexGridSizer* fgSizer; + fgSizer = new wxFlexGridSizer( 0, 3, 0, 0 ); + fgSizer->AddGrowableCol( 1 ); + fgSizer->SetFlexibleDirection( wxBOTH ); + fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticTextSize = new wxStaticText( this, wxID_ANY, wxT("Size"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSize->Wrap( -1 ); + fgSizer->Add( m_staticTextSize, 0, wxALL, 5 ); + + m_MireWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer->Add( m_MireWidthCtrl, 0, wxALL|wxEXPAND, 5 ); + + m_staticTextSizeUnits = new wxStaticText( this, wxID_ANY, wxT("unit"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSizeUnits->Wrap( -1 ); + fgSizer->Add( m_staticTextSizeUnits, 0, wxALL, 5 ); + + m_staticTextThickness = new wxStaticText( this, wxID_ANY, wxT("Thickness"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextThickness->Wrap( -1 ); + fgSizer->Add( m_staticTextThickness, 0, wxALL, 5 ); + + m_MireSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer->Add( m_MireSizeCtrl, 0, wxALL|wxEXPAND, 5 ); + + m_staticTextThicknessUnits = new wxStaticText( this, wxID_ANY, wxT("unit"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextThicknessUnits->Wrap( -1 ); + fgSizer->Add( m_staticTextThicknessUnits, 0, wxALL, 5 ); + + m_staticTextShape = new wxStaticText( this, wxID_ANY, wxT("Shape"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextShape->Wrap( -1 ); + fgSizer->Add( m_staticTextShape, 0, wxALL, 5 ); + + wxString m_MireShapeChoices[] = { wxT("+"), wxT("X") }; + int m_MireShapeNChoices = sizeof( m_MireShapeChoices ) / sizeof( wxString ); + m_MireShape = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_MireShapeNChoices, m_MireShapeChoices, 0 ); + m_MireShape->SetSelection( 0 ); + fgSizer->Add( m_MireShape, 0, wxALL|wxEXPAND, 5 ); + + + fgSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + + + bSizerUpper->Add( fgSizer, 1, wxEXPAND, 5 ); + + + bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); + + m_sdbSizerButts = new wxStdDialogButtonSizer(); + m_sdbSizerButtsOK = new wxButton( this, wxID_OK ); + m_sdbSizerButts->AddButton( m_sdbSizerButtsOK ); + m_sdbSizerButtsCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizerButts->AddButton( m_sdbSizerButtsCancel ); + m_sdbSizerButts->Realize(); + + bSizerMain->Add( m_sdbSizerButts, 0, wxALIGN_RIGHT|wxEXPAND, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + m_sdbSizerButtsCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TARGET_PROPERTIES_DIALOG_EDITOR_BASE::OnCancelClick ), NULL, this ); + m_sdbSizerButtsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TARGET_PROPERTIES_DIALOG_EDITOR_BASE::OnOkClick ), NULL, this ); +} + +TARGET_PROPERTIES_DIALOG_EDITOR_BASE::~TARGET_PROPERTIES_DIALOG_EDITOR_BASE() +{ + // Disconnect Events + m_sdbSizerButtsCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TARGET_PROPERTIES_DIALOG_EDITOR_BASE::OnCancelClick ), NULL, this ); + m_sdbSizerButtsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TARGET_PROPERTIES_DIALOG_EDITOR_BASE::OnOkClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_target_properties_base.fbp b/pcbnew/dialogs/dialog_target_properties_base.fbp new file mode 100644 index 0000000000..e10ec98e5b --- /dev/null +++ b/pcbnew/dialogs/dialog_target_properties_base.fbp @@ -0,0 +1,928 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_target_properties_base + 1000 + none + 0 + dialog_target_properties_base + + . + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + TARGET_PROPERTIES_DIALOG_EDITOR_BASE + + 285,170 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Target Properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizerMain + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + + bSizerUpper + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + 3 + wxBOTH + 1 + + 0 + + fgSizer + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Size + + 0 + + + 0 + + 1 + m_staticTextSize + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_MireWidthCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + unit + + 0 + + + 0 + + 1 + m_staticTextSizeUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Thickness + + 0 + + + 0 + + 1 + m_staticTextThickness + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_MireSizeCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + unit + + 0 + + + 0 + + 1 + m_staticTextThicknessUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shape + + 0 + + + 0 + + 1 + m_staticTextShape + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "+" "X" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_MireShape + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + + + + + 5 + wxEXPAND | wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_RIGHT|wxEXPAND + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizerButts + protected + + OnCancelClick + + + + OnOkClick + + + + + + + + diff --git a/pcbnew/dialogs/dialog_target_properties_base.h b/pcbnew/dialogs/dialog_target_properties_base.h new file mode 100644 index 0000000000..e8a815dd7a --- /dev/null +++ b/pcbnew/dialogs/dialog_target_properties_base.h @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 8 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_TARGET_PROPERTIES_BASE_H__ +#define __DIALOG_TARGET_PROPERTIES_BASE_H__ + +#include +#include +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class TARGET_PROPERTIES_DIALOG_EDITOR_BASE +/////////////////////////////////////////////////////////////////////////////// +class TARGET_PROPERTIES_DIALOG_EDITOR_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticTextSize; + wxTextCtrl* m_MireWidthCtrl; + wxStaticText* m_staticTextSizeUnits; + wxStaticText* m_staticTextThickness; + wxTextCtrl* m_MireSizeCtrl; + wxStaticText* m_staticTextThicknessUnits; + wxStaticText* m_staticTextShape; + wxChoice* m_MireShape; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizerButts; + wxButton* m_sdbSizerButtsOK; + wxButton* m_sdbSizerButtsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + TARGET_PROPERTIES_DIALOG_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Target Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 285,170 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~TARGET_PROPERTIES_DIALOG_EDITOR_BASE(); + +}; + +#endif //__DIALOG_TARGET_PROPERTIES_BASE_H__ diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index a74c844019..a154b8677f 100755 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -94,9 +94,10 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_PCB_STOP_CURRENT_DRAWING: case ID_POPUP_PCB_BEGIN_TRACK: case ID_POPUP_PCB_END_TRACK: - case ID_POPUP_PCB_PLACE_VIA: - case ID_POPUP_PCB_SWITCH_TRACK_POSTURE: + case ID_POPUP_PCB_PLACE_THROUGH_VIA: + case ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA: case ID_POPUP_PCB_PLACE_MICROVIA: + case ID_POPUP_PCB_SWITCH_TRACK_POSTURE: case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: @@ -379,8 +380,9 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_PCB_PLACE_MICROVIA: if( !IsMicroViaAcceptable() ) break; - - case ID_POPUP_PCB_PLACE_VIA: + // fall through + case ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA: + case ID_POPUP_PCB_PLACE_THROUGH_VIA: m_canvas->MoveCursorToCrossHair(); if( GetCurItem()->IsDragging() ) @@ -390,11 +392,14 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) else { int v_type = GetDesignSettings().m_CurrentViaType; - - // place micro via and switch layer. - if( id == ID_POPUP_PCB_PLACE_MICROVIA ) + if( id == ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA ) + GetDesignSettings().m_CurrentViaType = VIA_BLIND_BURIED; + else if( id == ID_POPUP_PCB_PLACE_MICROVIA ) GetDesignSettings().m_CurrentViaType = VIA_MICROVIA; + else + GetDesignSettings().m_CurrentViaType = VIA_THROUGH; + // place via and switch layer. Other_Layer_Route( (TRACK*) GetCurItem(), &dc ); GetDesignSettings().m_CurrentViaType = v_type; diff --git a/pcbnew/hotkeys.cpp b/pcbnew/hotkeys.cpp index c0a3830388..ff10c1945d 100644 --- a/pcbnew/hotkeys.cpp +++ b/pcbnew/hotkeys.cpp @@ -60,11 +60,12 @@ static EDA_HOTKEY HkLoadfile( wxT( "Load board" ), HK_LOAD_BOARD, 'L' + GR_KB_CT static EDA_HOTKEY HkFindItem( wxT( "Find Item" ), HK_FIND_ITEM, 'F' + GR_KB_CTRL ); static EDA_HOTKEY HkBackspace( wxT( "Delete track segment" ), HK_BACK_SPACE, WXK_BACK ); static EDA_HOTKEY HkAddNewTrack( wxT( "Add new track" ), HK_ADD_NEW_TRACK, 'X' ); -static EDA_HOTKEY HkAddVia( wxT( "Add Via" ), HK_ADD_VIA, 'V' ); +static EDA_HOTKEY HkAddThroughVia( wxT( "Add Through Via" ), HK_ADD_THROUGH_VIA, 'V' ); +static EDA_HOTKEY HkAddMicroVia( wxT( "Add MicroVia" ), HK_ADD_MICROVIA, 'V' + GR_KB_CTRL ); +static EDA_HOTKEY HkAddBlindBuriedVia( wxT( "Add Blind/Buried Via" ), HK_ADD_BLIND_BURIED_VIA, 'V' + GR_KB_ALT ); static EDA_HOTKEY HkSwitchTrackPosture( wxT( "Switch Track Posture" ), HK_SWITCH_TRACK_POSTURE, '/' ); static EDA_HOTKEY HkDragTrackKeepSlope( wxT( "Drag track keep slope" ), HK_DRAG_TRACK_KEEP_SLOPE, 'D' ); static EDA_HOTKEY HkPlaceItem( wxT( "Place Item" ), HK_PLACE_ITEM, 'P' ); -static EDA_HOTKEY HkAddMicroVia( wxT( "Add MicroVia" ), HK_ADD_MICROVIA, 'V' + GR_KB_CTRL ); static EDA_HOTKEY HkEndTrack( wxT( "End Track" ), HK_END_TRACK, WXK_END ); static EDA_HOTKEY HkEditBoardItem( wxT( "Edit Item" ), HK_EDIT_ITEM, 'E' ); static EDA_HOTKEY HkFlipItem( wxT( "Flip Item" ), HK_FLIP_ITEM, 'F' ); @@ -207,7 +208,8 @@ EDA_HOTKEY* board_edit_Hotkey_List[] = { &HkTrackDisplayMode, &HkDelete, &HkBackspace, - &HkAddNewTrack, &HkAddVia, &HkAddMicroVia, + &HkAddNewTrack, &HkAddThroughVia, &HkAddBlindBuriedVia, + &HkAddMicroVia, &HkSwitchTrackPosture, &HkDragTrackKeepSlope, &HkPlaceItem, &HkCopyItem, diff --git a/pcbnew/hotkeys.h b/pcbnew/hotkeys.h index dca43f3aa0..9e2c1fa5d1 100644 --- a/pcbnew/hotkeys.h +++ b/pcbnew/hotkeys.h @@ -21,7 +21,8 @@ enum hotkey_id_commnand { HK_GET_AND_MOVE_FOOTPRINT, HK_LOCK_UNLOCK_FOOTPRINT, HK_ADD_NEW_TRACK, - HK_ADD_VIA, + HK_ADD_THROUGH_VIA, + HK_ADD_BLIND_BURIED_VIA, HK_ADD_MICROVIA, HK_SWITCH_TRACK_POSTURE, HK_DRAG_TRACK_KEEP_SLOPE, diff --git a/pcbnew/hotkeys_board_editor.cpp b/pcbnew/hotkeys_board_editor.cpp index c7e42649f7..5f961d5e28 100644 --- a/pcbnew/hotkeys_board_editor.cpp +++ b/pcbnew/hotkeys_board_editor.cpp @@ -458,7 +458,14 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit break; - case HK_ADD_VIA: // Switch to alternate layer and Place a via if a track is in progress + case HK_ADD_BLIND_BURIED_VIA: + case HK_ADD_THROUGH_VIA: // Switch to alternate layer and Place a via if a track is in progress + if( GetBoard()->GetDesignSettings().m_BlindBuriedViaAllowed && + hk_id == HK_ADD_BLIND_BURIED_VIA ) + GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_BLIND_BURIED; + else + GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_THROUGH; + if( !itemCurrentlyEdited ) // no track in progress: switch layer only { Other_Layer_Route( NULL, aDC ); @@ -476,7 +483,8 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit if( !GetCurItem()->IsNew() ) return; - evt_type = ID_POPUP_PCB_PLACE_VIA; + evt_type = hk_id == HK_ADD_BLIND_BURIED_VIA ? + ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA : ID_POPUP_PCB_PLACE_THROUGH_VIA; break; case HK_SWITCH_TRACK_POSTURE: diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 815472e1d1..847571940c 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -510,6 +510,8 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const FMTIU( aBoard->m_ViasDimensionsList[ii].m_Drill ).c_str() ); // for old versions compatibility: + if( aBoard->GetDesignSettings().m_BlindBuriedViaAllowed ) + m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" ); m_out->Print( aNestLevel+1, "(uvia_size %s)\n", FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() ); m_out->Print( aNestLevel+1, "(uvia_drill %s)\n", diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index 1d482743fe..44545393cf 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -515,8 +515,14 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu ) AddMenuItem( PopMenu, ID_POPUP_PCB_END_TRACK, msg, KiBitmap( apply_xpm ) ); } - msg = AddHotkeyName( _( "Place Via" ), g_Board_Editor_Hokeys_Descr, HK_ADD_VIA ); - AddMenuItem( PopMenu, ID_POPUP_PCB_PLACE_VIA, msg, KiBitmap( via_xpm ) ); + msg = AddHotkeyName( _( "Place Through Via" ), g_Board_Editor_Hokeys_Descr, HK_ADD_THROUGH_VIA ); + AddMenuItem( PopMenu, ID_POPUP_PCB_PLACE_THROUGH_VIA, msg, KiBitmap( via_xpm ) ); + + if( GetBoard()->GetDesignSettings().m_BlindBuriedViaAllowed ) + { + msg = AddHotkeyName( _( "Place Blind/Buried Via" ), g_Board_Editor_Hokeys_Descr, HK_ADD_BLIND_BURIED_VIA ); + AddMenuItem( PopMenu, ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA, msg, KiBitmap( via_xpm ) ); + } msg = AddHotkeyName( _( "Switch Track Posture" ), g_Board_Editor_Hokeys_Descr, HK_SWITCH_TRACK_POSTURE ); diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index bd255e84b2..0c4c77358e 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 CERN + * @author Wayne Stambaugh * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -906,6 +907,11 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) NeedRIGHT(); break; + case T_blind_buried_vias_allowed: + designSettings.m_BlindBuriedViaAllowed = parseBool(); + NeedRIGHT(); + break; + case T_uvia_min_size: designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size ); NeedRIGHT(); diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index a579b9ecbe..f4e5caa83b 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -120,7 +120,8 @@ enum pcbnew_ids ID_POPUP_PCB_EDIT_DIMENSION, ID_POPUP_PCB_END_TRACK, - ID_POPUP_PCB_PLACE_VIA, + ID_POPUP_PCB_PLACE_THROUGH_VIA, + ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA, ID_POPUP_PCB_PLACE_MICROVIA, ID_POPUP_PCB_SWITCH_TRACK_POSTURE, diff --git a/pcbnew/scripting/plugins/qfp_wizard.py b/pcbnew/scripting/plugins/qfp_wizard.py new file mode 100644 index 0000000000..680c7faf35 --- /dev/null +++ b/pcbnew/scripting/plugins/qfp_wizard.py @@ -0,0 +1,230 @@ +import pcbnew + +def abs(x): + if x < 0: + return -x + + return x + +class QFPWizard(pcbnew.FootprintWizardPlugin): + def __init__(self): + pcbnew.FootprintWizardPlugin.__init__(self) + self.name = "QFP" + self.description = "QFP Footprint Wizard" + self.parameters = { + "Pads": { + "*n": 100, + "pitch": pcbnew.FromMM(0.5), + "width": pcbnew.FromMM(0.25), + "length": pcbnew.FromMM(1.5), + "horizontal pitch": pcbnew.FromMM(15), + "vertical pitch": pcbnew.FromMM(15), + "*oval": "True" + }, + "Package": { + "width": pcbnew.FromMM(14), + "height": pcbnew.FromMM(14) + } + } + + self.ClearErrors() + + def smd_rect_pad(self, module, size, pos, name): + pad = pcbnew.D_PAD(module) + + pad.SetSize(size) + + if self.parameters['Pads'].get('*oval', "true").lower() == "true": + pad.SetShape(pcbnew.PAD_OVAL) + else: + pad.SetShape(pcbnew.PAD_RECT) + + pad.SetAttribute(pcbnew.PAD_SMD) + pad.SetLayerMask(pcbnew.PAD_SMD_DEFAULT_LAYERS) + pad.SetPos0(pos) + pad.SetPosition(pos) + pad.SetPadName(name) + + return pad + + def CheckParameters(self): + errors = "" + pads = self.parameters + + num_pads = pads["Pads"]["*n"] + if (num_pads < 1): + self.parameter_errors["Pads"]["*n"] = "Must be positive" + errors +="Pads/n has wrong value, " + pads["Pads"]["*n"] = int(num_pads) # Reset to int instead of float + + return errors + + def BuildFootprint(self): + if self.has_errors(): + print "Cannot build footprint: Parameters have errors:" + print self.parameter_errors + return + + print "Building new QFP footprint with the following parameters:" + self.print_parameter_table() + + self.module = pcbnew.MODULE(None) # create a new module + + pads = self.parameters + num_pads = int(pads["Pads"]["*n"]) + pad_width = pads["Pads"]["width"] + pad_length = pads["Pads"]["length"] + pad_pitch = pads["Pads"]["pitch"] + pad_horizontal_pitch = pads["Pads"]["horizontal pitch"] + pad_vertical_pitch = pads["Pads"]["vertical pitch"] + + package_width = pads["Package"]["width"] + package_height = pads["Package"]["height"] + + side_length = pad_pitch * ((num_pads / 4) - 1) + + offsetX = pad_pitch * ((num_pads / 4) - 1) / 2 + text_size = pcbnew.wxSize(pcbnew.FromMM(0.8), pcbnew.FromMM(0.8)) + + self.module.SetReference("QFP %d" % int(num_pads)) + self.module.Reference().SetPos0(pcbnew.wxPoint(0, pcbnew.FromMM(-0.8))) + self.module.Reference().SetTextPosition(self.module.Reference().GetPos0()) + self.module.Reference().SetSize(text_size) + + self.module.SetValue("U**") + self.module.Value().SetPos0(pcbnew.wxPoint(0, pcbnew.FromMM(+0.8))) + self.module.Value().SetTextPosition(self.module.Value().GetPos0()) + self.module.Value().SetSize(text_size) + + self.module.SetLibRef("QFP-%d" % int(num_pads)) + + pad_size_left_right = pcbnew.wxSize(pad_length, pad_width) + pad_size_bottom_top = pcbnew.wxSize(pad_width, pad_length) + + for cur_pad in range(0, num_pads): + side = int(cur_pad / (num_pads / 4)) # 0 -> left, 1 -> bottom, 2 -> right, 3 -> top + + if side == 0 or side == 2: + pad_size = pad_size_left_right + + pad_pos_x = -(pad_horizontal_pitch / 2) + if side == 2: + pad_pos_x = -pad_pos_x + + pad_pos_y = (cur_pad % (num_pads / 4)) * pad_pitch - (side_length / 2) + else: + pad_size = pad_size_bottom_top + + pad_pos_x = (cur_pad % (num_pads / 4)) * pad_pitch - (side_length / 2) + + pad_pos_y = -(pad_vertical_pitch / 2) + if side == 1: + pad_pos_y = -pad_pos_y + + pad_pos = pcbnew.wxPoint(pad_pos_x, pad_pos_y) + + pad = self.smd_rect_pad(self.module, pad_size, pad_pos, str(cur_pad + 1)) + + self.module.Add(pad) + + half_package_width = package_width / 2 + half_package_height = package_height / 2 + + package_pad_height_offset = abs(package_height - side_length) / 2 - pad_pitch + package_pad_width_offset = abs(package_width - side_length) / 2 - pad_pitch + + # Bottom Left Edge, vertical line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(-half_package_width, half_package_height - package_pad_height_offset) + end = pcbnew.wxPoint(-half_package_width, half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + # Bottom Left Edge, horizontal line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(-half_package_width, half_package_height) + end = pcbnew.wxPoint(-half_package_width + package_pad_width_offset, half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + # Bottom Right Edge, vertical line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(half_package_width, half_package_height - package_pad_height_offset) + end = pcbnew.wxPoint(half_package_width, half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + # Bottom Right Edge, horizontal line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(half_package_width, half_package_height) + end = pcbnew.wxPoint(half_package_width - package_pad_width_offset, half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + # Top Right Edge, vertical line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(half_package_width, -half_package_height + package_pad_height_offset) + end = pcbnew.wxPoint(half_package_width, -half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + # Top Right Edge, horizontal line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(half_package_width, -half_package_height) + end = pcbnew.wxPoint(half_package_width - package_pad_width_offset, -half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + # Top Left Edge, straight line + outline = pcbnew.EDGE_MODULE(self.module) + outline.SetWidth(pcbnew.FromMM(0.2)) + outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT) + outline.SetShape(pcbnew.S_SEGMENT) + start = pcbnew.wxPoint(-half_package_width, -half_package_height + package_pad_height_offset) + end = pcbnew.wxPoint(-half_package_width + package_pad_width_offset, -half_package_height) + outline.SetStartEnd(start, end) + self.module.Add(outline) + + def print_parameter_table(self): + for name, section in self.parameters.iteritems(): + print " %s:" % name + + for key, value in section.iteritems(): + unit = "" + if (type(value) is int or type(value) is float) and not "*" in key: + unit = "mm" + + if "*" in key: + key = key[1:] + else: + value = pcbnew.ToMM(value) + + print " %s: %s%s" % (key, value, unit) + + def has_errors(self): + for name, section in self.parameter_errors.iteritems(): + for k, v in section.iteritems(): + if v: + return True + + return False + +QFPWizard().register() \ No newline at end of file diff --git a/pcbnew/mirepcb.cpp b/pcbnew/target_edit.cpp similarity index 77% rename from pcbnew/mirepcb.cpp rename to pcbnew/target_edit.cpp index d937793e73..348f56b102 100644 --- a/pcbnew/mirepcb.cpp +++ b/pcbnew/target_edit.cpp @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr - * Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors. * * * This program is free software; you can redistribute it and/or @@ -24,7 +24,7 @@ */ /** - * @file mirepcb.cpp + * @file dialog_target_properties.cpp * @brief Functions to edit targets (class #PCB_TARGET). */ @@ -32,13 +32,15 @@ #include #include #include +#include #include +#include #include #include #include -#include +#include // Routines Locales @@ -61,16 +63,12 @@ static PCB_TARGET s_TargetCopy( NULL ); /* Used to store "old" values of the /* class TARGET_PROPERTIES_DIALOG_EDITOR */ /*****************************************/ -class TARGET_PROPERTIES_DIALOG_EDITOR : public wxDialog +class TARGET_PROPERTIES_DIALOG_EDITOR : public TARGET_PROPERTIES_DIALOG_EDITOR_BASE { private: - PCB_EDIT_FRAME* m_Parent; wxDC* m_DC; PCB_TARGET* m_Target; - EDA_VALUE_CTRL* m_MireWidthCtrl; - EDA_VALUE_CTRL* m_MireSizeCtrl; - wxRadioBox* m_MireShape; public: TARGET_PROPERTIES_DIALOG_EDITOR( PCB_EDIT_FRAME* parent, PCB_TARGET* Mire, wxDC* DC ); @@ -79,15 +77,8 @@ public: private: void OnOkClick( wxCommandEvent& event ); void OnCancelClick( wxCommandEvent& event ); - - DECLARE_EVENT_TABLE() }; -BEGIN_EVENT_TABLE( TARGET_PROPERTIES_DIALOG_EDITOR, wxDialog ) - EVT_BUTTON( wxID_OK, TARGET_PROPERTIES_DIALOG_EDITOR::OnOkClick ) - EVT_BUTTON( wxID_CANCEL, TARGET_PROPERTIES_DIALOG_EDITOR::OnCancelClick ) -END_EVENT_TABLE() - void PCB_EDIT_FRAME::ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ) { @@ -101,52 +92,26 @@ void PCB_EDIT_FRAME::ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ) TARGET_PROPERTIES_DIALOG_EDITOR::TARGET_PROPERTIES_DIALOG_EDITOR( PCB_EDIT_FRAME* parent, PCB_TARGET* aTarget, wxDC* DC ) : - wxDialog( parent, wxID_ANY, wxString( _( "Target Properties" ) ) ) + TARGET_PROPERTIES_DIALOG_EDITOR_BASE( parent ) { - wxString number; - wxButton* Button; - m_Parent = parent; m_DC = DC; - Centre(); - m_Target = aTarget; - wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxHORIZONTAL ); - SetSizer( MainBoxSizer ); - wxBoxSizer* LeftBoxSizer = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* RightBoxSizer = new wxBoxSizer( wxVERTICAL ); - MainBoxSizer->Add( LeftBoxSizer, 0, wxGROW | wxALL, 5 ); - MainBoxSizer->Add( RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 ); - - // Create of the command buttons. - Button = new wxButton( this, wxID_OK, _( "OK" ) ); - RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); - - Button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); - RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); - // Size: - m_MireSizeCtrl = new EDA_VALUE_CTRL( this, _( "Size" ), - m_Target->GetSize(), - g_UserUnit, LeftBoxSizer ); + m_staticTextSizeUnits->SetLabel( GetUnitsLabel( g_UserUnit ) ); + m_MireSizeCtrl->SetValue( ReturnStringFromValue( g_UserUnit, m_Target->GetSize() ) ); - // Width: - m_MireWidthCtrl = new EDA_VALUE_CTRL( this, _( "Width" ), - m_Target->GetWidth(), - g_UserUnit, LeftBoxSizer ); + // Thickness: + m_staticTextThicknessUnits->SetLabel( GetUnitsLabel( g_UserUnit ) ); + m_MireWidthCtrl->SetValue( ReturnStringFromValue( g_UserUnit, m_Target->GetWidth() ) ); // Shape - wxString shape_list[2] = { _( "shape +" ), _( "shape X" ) }; - m_MireShape = new wxRadioBox( this, wxID_ANY, - _( "Target Shape:" ), - wxDefaultPosition, wxSize( -1, -1 ), - 2, shape_list, 1 ); m_MireShape->SetSelection( m_Target->GetShape() ? 1 : 0 ); - LeftBoxSizer->Add( m_MireShape, 0, wxGROW | wxALL, 5 ); GetSizer()->Fit( this ); GetSizer()->SetSizeHints( this ); + Centre(); } @@ -170,9 +135,12 @@ void TARGET_PROPERTIES_DIALOG_EDITOR::OnOkClick( wxCommandEvent& event ) m_Target->SetFlags( IN_EDIT ); // set flag in edit to force // undo/redo/abort proper operation - m_Target->SetWidth( m_MireWidthCtrl->GetValue() ); - MireDefaultSize = m_MireSizeCtrl->GetValue(); - m_Target->SetSize( m_MireSizeCtrl->GetValue() ); + int tmp = ReturnValueFromString( g_UserUnit, m_MireWidthCtrl->GetValue() ); + m_Target->SetWidth( tmp ); + + MireDefaultSize = ReturnValueFromString( g_UserUnit, m_MireSizeCtrl->GetValue() ); + m_Target->SetSize( MireDefaultSize ); + m_Target->SetShape( m_MireShape->GetSelection() ? 1 : 0 ); m_Target->Draw( m_Parent->GetCanvas(), m_DC, ( m_Target->IsMoving() ) ? GR_XOR : GR_OR ); From 7546333fbc4a0bff8b780f9c44bb7a5e9529f75d Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 29 Aug 2013 09:20:09 +0200 Subject: [PATCH 04/29] Pl_Editor: fix some minor issues. --- pagelayout_editor/dialogs/properties_frame_base.cpp | 8 ++++---- pagelayout_editor/dialogs/properties_frame_base.fbp | 10 +++++----- pagelayout_editor/files.cpp | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pagelayout_editor/dialogs/properties_frame_base.cpp b/pagelayout_editor/dialogs/properties_frame_base.cpp index bd12ffdd3f..ab6543c85b 100644 --- a/pagelayout_editor/dialogs/properties_frame_base.cpp +++ b/pagelayout_editor/dialogs/properties_frame_base.cpp @@ -15,7 +15,7 @@ PANEL_PROPERTIES_BASE::PANEL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, c bSizerpanel = new wxBoxSizer( wxVERTICAL ); m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_swItemProperties = new wxScrolledWindow( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_swItemProperties = new wxScrolledWindow( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL ); m_swItemProperties->SetScrollRate( 5, 5 ); wxBoxSizer* bSizerMain; bSizerMain = new wxBoxSizer( wxVERTICAL ); @@ -121,7 +121,7 @@ PANEL_PROPERTIES_BASE::PANEL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, c wxBoxSizer* bSizerTsizeX; bSizerTsizeX = new wxBoxSizer( wxVERTICAL ); - m_staticTexTsizeX = new wxStaticText( m_swItemProperties, wxID_ANY, _("Text Height (mm)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTexTsizeX = new wxStaticText( m_swItemProperties, wxID_ANY, _("Text Width (mm)"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTexTsizeX->Wrap( -1 ); bSizerTsizeX->Add( m_staticTexTsizeX, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -134,7 +134,7 @@ PANEL_PROPERTIES_BASE::PANEL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, c wxBoxSizer* bSizerTsizeY; bSizerTsizeY = new wxBoxSizer( wxVERTICAL ); - m_staticTextTsizeY = new wxStaticText( m_swItemProperties, wxID_ANY, _("Text Width (mm)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTsizeY = new wxStaticText( m_swItemProperties, wxID_ANY, _("Text Height (mm)"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextTsizeY->Wrap( -1 ); bSizerTsizeY->Add( m_staticTextTsizeY, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -436,7 +436,7 @@ PANEL_PROPERTIES_BASE::PANEL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, c m_swItemProperties->Layout(); bSizerMain->Fit( m_swItemProperties ); m_notebook->AddPage( m_swItemProperties, _("Item Properties"), true ); - m_swGeneralOpts = new wxScrolledWindow( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_swGeneralOpts = new wxScrolledWindow( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL ); m_swGeneralOpts->SetScrollRate( 5, 5 ); wxBoxSizer* bSizerGeneralOpts; bSizerGeneralOpts = new wxBoxSizer( wxVERTICAL ); diff --git a/pagelayout_editor/dialogs/properties_frame_base.fbp b/pagelayout_editor/dialogs/properties_frame_base.fbp index 7e6b956090..cdbfedd814 100644 --- a/pagelayout_editor/dialogs/properties_frame_base.fbp +++ b/pagelayout_editor/dialogs/properties_frame_base.fbp @@ -167,7 +167,7 @@ Item Properties 1 - + 1 1 1 @@ -219,7 +219,7 @@ - wxHSCROLL|wxVSCROLL + wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL @@ -1491,7 +1491,7 @@ 0 0 wxID_ANY - Text Height (mm) + Text Width (mm) 0 @@ -1676,7 +1676,7 @@ 0 0 wxID_ANY - Text Width (mm) + Text Height (mm) 0 @@ -5488,7 +5488,7 @@ - wxHSCROLL|wxVSCROLL + wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL diff --git a/pagelayout_editor/files.cpp b/pagelayout_editor/files.cpp index 8598ea9de3..45749ae016 100644 --- a/pagelayout_editor/files.cpp +++ b/pagelayout_editor/files.cpp @@ -185,6 +185,10 @@ void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event ) return; filename = openFileDialog.GetPath(); + // Ensure the file has the right extension: + wxFileName fn(filename); + fn.SetExt( PageLayoutDescrFileExtension ); + filename = fn.GetFullPath(); if( !SavePageLayoutDescrFile( filename ) ) { wxString msg; From ce983ec34acf29c8899192a575b4021d1d338376 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 30 Aug 2013 21:28:31 +0200 Subject: [PATCH 05/29] Pcbnew: Redesign layer selection and layer pair selection (give them a look near the Layer selector in toolbarr) --- common/class_layer_box_selector.cpp | 82 ++-- include/class_layer_box_selector.h | 60 ++- pagelayout_editor/files.cpp | 9 +- pcbnew/CMakeLists.txt | 1 + pcbnew/edit.cpp | 8 + pcbnew/sel_layer.cpp | 686 +++++++++++++++++----------- 6 files changed, 502 insertions(+), 344 deletions(-) diff --git a/common/class_layer_box_selector.cpp b/common/class_layer_box_selector.cpp index 66b40377cf..2dadd15585 100644 --- a/common/class_layer_box_selector.cpp +++ b/common/class_layer_box_selector.cpp @@ -11,6 +11,46 @@ #include + +LAYER_SELECTOR::LAYER_SELECTOR() +{ + m_layerorder = true; + m_layerhotkeys = true; + m_hotkeys = NULL; +} + + +bool LAYER_SELECTOR::SetLayersOrdered( bool value ) +{ + m_layerorder = value; + return m_layerorder; +} + + +bool LAYER_SELECTOR::SetLayersHotkeys( bool value ) +{ + m_layerhotkeys = value; + return m_layerhotkeys; +} + + +void LAYER_SELECTOR::SetBitmapLayer( wxBitmap& aLayerbmp, LAYER_NUM aLayer ) +{ + wxMemoryDC bmpDC; + wxBrush brush; + + // Prepare Bitmap + bmpDC.SelectObject( aLayerbmp ); + brush.SetColour( MakeColour( GetLayerColor( aLayer ) ) ); + brush.SetStyle( wxSOLID ); + + bmpDC.SetBrush( brush ); + bmpDC.DrawRectangle( 0, 0, aLayerbmp.GetWidth(), aLayerbmp.GetHeight() ); + bmpDC.SetBrush( *wxTRANSPARENT_BRUSH ); + bmpDC.SetPen( *wxBLACK_PEN ); + bmpDC.DrawRectangle( 0, 0, aLayerbmp.GetWidth(), aLayerbmp.GetHeight() ); +} + /* class to display a layer list. * */ @@ -18,12 +58,9 @@ LAYER_BOX_SELECTOR::LAYER_BOX_SELECTOR( wxAuiToolBar* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, int n, const wxString choices[] ) : + LAYER_SELECTOR(), wxBitmapComboBox( parent, id, wxEmptyString, pos, size, n, choices, wxCB_READONLY ) { - m_layerorder = true; - m_layerhotkeys = true; - m_hotkeys = NULL; - if( choices != NULL ) ResyncBitmapOnly(); } @@ -32,31 +69,14 @@ LAYER_BOX_SELECTOR::LAYER_BOX_SELECTOR( wxAuiToolBar* parent, wxWindowID id, LAYER_BOX_SELECTOR::LAYER_BOX_SELECTOR( wxAuiToolBar* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, const wxArrayString& choices ) : + LAYER_SELECTOR(), wxBitmapComboBox( parent, id, wxEmptyString, pos, size, choices, wxCB_READONLY ) { - m_layerorder = true; - m_layerhotkeys = true; - m_hotkeys = NULL; - if( !choices.IsEmpty() ) ResyncBitmapOnly(); } -bool LAYER_BOX_SELECTOR::SetLayersOrdered( bool value ) -{ - m_layerorder = value; - return m_layerorder; -} - - -bool LAYER_BOX_SELECTOR::SetLayersHotkeys( bool value ) -{ - m_layerhotkeys = value; - return m_layerhotkeys; -} - - // Get Current Item # int LAYER_BOX_SELECTOR::GetChoice() { @@ -104,21 +124,3 @@ void LAYER_BOX_SELECTOR::ResyncBitmapOnly() SetBitmapLayer( layerbmp, i ); } } - - -void LAYER_BOX_SELECTOR::SetBitmapLayer( wxBitmap& aLayerbmp, LAYER_NUM aLayer ) -{ - wxMemoryDC bmpDC; - wxBrush brush; - - // Prepare Bitmap - bmpDC.SelectObject( aLayerbmp ); - brush.SetColour( MakeColour( GetLayerColor( aLayer ) ) ); - brush.SetStyle( wxSOLID ); - - bmpDC.SetBrush( brush ); - bmpDC.DrawRectangle( 0, 0, aLayerbmp.GetWidth(), aLayerbmp.GetHeight() ); - bmpDC.SetBrush( *wxTRANSPARENT_BRUSH ); - bmpDC.SetPen( *wxBLACK_PEN ); - bmpDC.DrawRectangle( 0, 0, aLayerbmp.GetWidth(), aLayerbmp.GetHeight() ); -} diff --git a/include/class_layer_box_selector.h b/include/class_layer_box_selector.h index e313b6242a..a45c60eccf 100644 --- a/include/class_layer_box_selector.h +++ b/include/class_layer_box_selector.h @@ -9,11 +9,11 @@ class wxAuiToolBar; -/* class to display a layer list. - * +/* Basic class to build a layer list. + * this is an basic abstract class to build a layer list selector. + * To display this list, you should therefore derive this class */ - -class LAYER_BOX_SELECTOR : public wxBitmapComboBox +class LAYER_SELECTOR { protected: bool m_layerhotkeys; @@ -23,6 +23,37 @@ public: // Hotkey Info struct EDA_HOTKEY_CONFIG* m_hotkeys; +public: + LAYER_SELECTOR(); + + // Returns a color index from the layer id + // Virtual function because GerbView uses its own functions in a derived class + virtual EDA_COLOR_T GetLayerColor( LAYER_NUM aLayer ) const = 0; + + // Returns the name of the layer id + // Virtual pure function because GerbView uses its own functions in a derived class + virtual wxString GetLayerName( LAYER_NUM aLayer ) const = 0; + + // Returns true if the layer id is enabled (i.e. is it should be displayed) + // Virtual function pure because GerbView uses its own functions in a derived class + virtual bool IsLayerEnabled( LAYER_NUM aLayer ) const = 0; + + bool SetLayersOrdered(bool value); + bool SetLayersHotkeys(bool value); + +protected: + // Fills the layer bitmap aLayerbmp with the layer color + void SetBitmapLayer( wxBitmap& aLayerbmp, LAYER_NUM aLayer ); +}; + +/* class to display a layer list in a wxBitmapComboBox. + */ +class LAYER_BOX_SELECTOR : public LAYER_SELECTOR, public wxBitmapComboBox +{ +public: + // Hotkey Info + struct EDA_HOTKEY_CONFIG* m_hotkeys; + public: LAYER_BOX_SELECTOR( wxAuiToolBar* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, @@ -33,19 +64,7 @@ public: const wxPoint& pos, const wxSize& size, const wxArrayString& choices ); - // Returns a color index from the layer id - // Virtual function because GerbView uses its own functions in a derived class - virtual EDA_COLOR_T GetLayerColor( LAYER_NUM aLayer ) const = 0; - - // Returns the name of the layer id - // Virtual pure function because GerbView uses its own functions in a derived class - virtual wxString GetLayerName( LAYER_NUM aLayer ) const = 0; - - // Returns true if the layer id is enabled (i.e. is it should be displayed) - // Virtual function pure because GerbView uses its own functions in a derived class - virtual bool IsLayerEnabled( LAYER_NUM aLayer ) const = 0; - - // Get Current Item # + // Get Current Item # int GetChoice(); // Get Current Layer @@ -60,13 +79,6 @@ public: // Reload the Layers bitmaps colors void ResyncBitmapOnly(); - - bool SetLayersOrdered(bool value); - bool SetLayersHotkeys(bool value); - -protected: - // Fills the layer bitmap aLayerbmp with the layer color - void SetBitmapLayer( wxBitmap& aLayerbmp, LAYER_NUM aLayer ); }; #define DECLARE_LAYERS_HOTKEY(list) int list[NB_LAYERS] = \ diff --git a/pagelayout_editor/files.cpp b/pagelayout_editor/files.cpp index 45749ae016..cc6ef4de7d 100644 --- a/pagelayout_editor/files.cpp +++ b/pagelayout_editor/files.cpp @@ -186,9 +186,14 @@ void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event ) filename = openFileDialog.GetPath(); // Ensure the file has the right extension: + // because a name like name.subname.subsubname is legal, + // add the right extension without replacing the wxFileName + // extension wxFileName fn(filename); - fn.SetExt( PageLayoutDescrFileExtension ); - filename = fn.GetFullPath(); + + if( fn.GetExt() != PageLayoutDescrFileExtension ) + filename << wxT(".") << PageLayoutDescrFileExtension; + if( !SavePageLayoutDescrFile( filename ) ) { wxString msg; diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 393740ae7b..59fcb0209c 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -76,6 +76,7 @@ set( PCBNEW_DIALOGS dialogs/dialog_global_deletion_base.cpp dialogs/dialog_keepout_area_properties.cpp dialogs/dialog_keepout_area_properties_base.cpp + dialogs/dialog_layer_selection_base.cpp dialogs/dialog_layers_setup.cpp dialogs/dialog_layers_setup_base.cpp dialogs/dialog_netlist.cpp diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index a154b8677f..ae445f1d8b 100755 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -925,7 +925,15 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) itmp = SelectLayer( getActiveLayer(), UNDEFINED_LAYER, UNDEFINED_LAYER ); if( itmp >= 0 ) + { + // if user changed colors and we are in high contrast mode, then redraw + // because the PAD_SMD pads may change color. + if( DisplayOpt.ContrastModeDisplay && getActiveLayer() != itmp ) + { + m_canvas->Refresh(); + } setActiveLayer( itmp ); + } m_canvas->MoveCursorToCrossHair(); break; diff --git a/pcbnew/sel_layer.cpp b/pcbnew/sel_layer.cpp index 5e265a26dc..0634c7fb28 100644 --- a/pcbnew/sel_layer.cpp +++ b/pcbnew/sel_layer.cpp @@ -1,7 +1,31 @@ /** * @file sel_layer.cpp - * @brief Set up the basic primitives for Layer control. + * @brief dialogs for one layer selection and a layer pair selection. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + #include #include @@ -9,340 +33,446 @@ #include #include #include - +#include #include +#include -enum layer_sel_id { - ID_LAYER_SELECT_TOP = 1800, - ID_LAYER_SELECT_BOTTOM, - ID_LAYER_SELECT -}; - - -class SELECT_LAYER_DIALOG : public wxDialog +/* classes to display a layer list using a wxGrid. + */ +class PCB_LAYER_SELECTOR: public LAYER_SELECTOR { -private: - PCB_BASE_FRAME* m_Parent; - wxRadioBox* m_LayerList; - LAYER_NUM m_LayerId[int(NB_PCB_LAYERS) + 1]; // One extra element for "(Deselect)" radiobutton + BOARD * m_brd; public: - // Constructor and destructor - SELECT_LAYER_DIALOG( PCB_BASE_FRAME* parent, LAYER_NUM default_layer, - LAYER_NUM min_layer, LAYER_NUM max_layer, bool null_layer ); - ~SELECT_LAYER_DIALOG() { }; + PCB_LAYER_SELECTOR( BOARD* aBrd ):LAYER_SELECTOR() + { + m_brd = aBrd; + } -private: - void OnLayerSelected( wxCommandEvent& event ); - void OnCancelClick( wxCommandEvent& event ); +protected: + // Returns true if the layer id is enabled (i.e. is it should be displayed) + bool IsLayerEnabled( LAYER_NUM aLayer ) const + { + return m_brd->IsLayerEnabled( aLayer ); + } + + // Returns a color index from the layer id + // Virtual function + EDA_COLOR_T GetLayerColor( LAYER_NUM aLayer ) const + { + return m_brd->GetLayerColor( aLayer ); + } + + // Returns the name of the layer id + // Virtual function + wxString GetLayerName( LAYER_NUM aLayer ) const + { + return m_brd->GetLayerName( aLayer ); + } - DECLARE_EVENT_TABLE() }; +/* + * This class display a pcb layers list in adialog, + * to select one layer from this list + */ +class PCB_ONE_LAYER_SELECTOR : public PCB_LAYER_SELECTOR, + public DIALOG_LAYER_SELECTION_BASE +{ + LAYER_NUM m_layerSelected; + LAYER_NUM m_minLayer; + LAYER_NUM m_maxLayer; -BEGIN_EVENT_TABLE( SELECT_LAYER_DIALOG, wxDialog ) - EVT_BUTTON( wxID_OK, SELECT_LAYER_DIALOG::OnLayerSelected ) - EVT_BUTTON( wxID_CANCEL, SELECT_LAYER_DIALOG::OnCancelClick ) - EVT_RADIOBOX( ID_LAYER_SELECT, SELECT_LAYER_DIALOG::OnLayerSelected ) -END_EVENT_TABLE() +public: + PCB_ONE_LAYER_SELECTOR( wxWindow* aParent, BOARD * aBrd, + LAYER_NUM aDefaultLayer, + LAYER_NUM aMinLayer = -1, LAYER_NUM aMaxLayer = -1, + bool aClearTool = false ) + :PCB_LAYER_SELECTOR( aBrd ), DIALOG_LAYER_SELECTION_BASE( aParent ) + { + m_layerSelected = (int) aDefaultLayer; + // When not needed, remove the "Clear" button + m_buttonClear->Show( aClearTool ); + m_minLayer = aMinLayer; + m_maxLayer = aMaxLayer; + BuildList(); + Layout(); + GetSizer()->SetSizeHints(this); + SetFocus(); + } + LAYER_NUM GetLayerSelection() { return m_layerSelected; } + +private: + // Event handlers + void OnLeftGridClick( wxGridEvent& event ); + void OnRightGridClick( wxGridEvent& event ); + void OnClearSelection( wxCommandEvent& event ) + { + m_layerSelected = NB_PCB_LAYERS; + EndModal( NB_PCB_LAYERS ); + } + + void BuildList(); +}; + +// Build the layers list +// Column position by function: +#define SELECT_COLNUM 0 +#define COLOR_COLNUM 1 +#define LAYERNAME_COLNUM 2 +#define LAYERID_COLNUM 3 +static DECLARE_LAYERS_ORDER_LIST( layertranscode ); + +void PCB_ONE_LAYER_SELECTOR::BuildList() +{ + m_leftGridLayers->SetColFormatNumber( LAYERID_COLNUM ); + m_rightGridLayers->SetColFormatNumber( LAYERID_COLNUM ); + m_leftGridLayers->HideCol( LAYERID_COLNUM ); + m_rightGridLayers->HideCol( LAYERID_COLNUM ); + m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 ); + m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 ); + + // Select a not show cell, to avoid a wrong cell selection for user + m_leftGridLayers->GoToCell( 0, LAYERID_COLNUM ); + m_rightGridLayers->GoToCell( 0, LAYERID_COLNUM ); + + int left_row = 0; + int right_row = 0; + wxString layernum; + wxString layername; + for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i ) + { + LAYER_NUM layerid = i; + + if( m_layerorder ) + layerid = layertranscode[i]; + + if( ! IsLayerEnabled( layerid ) ) + continue; + + if( m_minLayer >= 0 && layerid < m_minLayer ) + continue; + + if( m_maxLayer >= 0 && layerid > m_maxLayer ) + continue; + + wxColour color = MakeColour( GetLayerColor( layerid ) ); + layername = GetLayerName( layerid ); + layernum.Printf( wxT("%d"), layerid ); + + if( layerid <= LAST_COPPER_LAYER ) + { + if( left_row ) + m_leftGridLayers->AppendRows( 1 ); + + m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, + color ); + m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, + layername ); + m_leftGridLayers->SetCellValue( left_row, LAYERID_COLNUM, + layernum ); + + if( m_layerSelected == layerid ) + { + m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, + wxT("X") ); + m_leftGridLayers->SetCellBackgroundColour ( left_row, SELECT_COLNUM, + color ); + } + + left_row++; + } + else + { + if( right_row ) + m_rightGridLayers->AppendRows( 1 ); + + m_rightGridLayers->SetCellBackgroundColour ( right_row, COLOR_COLNUM, + color ); + m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, + layername ); + m_rightGridLayers->SetCellValue( right_row, LAYERID_COLNUM, + layernum ); + + if( m_layerSelected == layerid ) + { + m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, + wxT("X") ); + m_rightGridLayers->SetCellBackgroundColour ( right_row, SELECT_COLNUM, + color ); + } + + right_row++; + } + } + + // Show only populated lists: + if( left_row <= 0 ) + m_leftGridLayers->Show( false ); + + if( right_row <= 0 ) + m_rightGridLayers->Show( false ); + + m_leftGridLayers->AutoSizeColumn(LAYERNAME_COLNUM); + m_rightGridLayers->AutoSizeColumn(LAYERNAME_COLNUM); + m_leftGridLayers->AutoSizeColumn(SELECT_COLNUM); + m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM); +} + +void PCB_ONE_LAYER_SELECTOR::OnLeftGridClick( wxGridEvent& event ) +{ + wxString text = m_leftGridLayers->GetCellValue(event.GetRow(), LAYERID_COLNUM); + long layer; + text.ToLong( &layer ); + m_layerSelected = layer; + EndModal( 1 ); +} + +void PCB_ONE_LAYER_SELECTOR::OnRightGridClick( wxGridEvent& event ) +{ + wxString text = m_rightGridLayers->GetCellValue(event.GetRow(), LAYERID_COLNUM); + long layer; + text.ToLong( &layer ); + m_layerSelected = layer; + EndModal( 2 ); +} /** Install the dialog box for layer selection - * @param default_layer = Preselection (NB_PCB_LAYERS for "(Deselect)" layer) - * @param min_layer = min layer value (-1 if no min value) - * @param max_layer = max layer value (-1 if no max value) - * @param null_layer = display a "(Deselect)" radiobutton (when set to true) + * @param aDefaultLayer = Preselection (NB_PCB_LAYERS for "(Deselect)" layer) + * @param aMinlayer = min layer id value (-1 if no min value) + * @param aMaxLayer = max layer id value (-1 if no max value) + * @param aDeselectTool = display a "Clear" button when true * @return new layer value (NB_PCB_LAYERS when "(Deselect)" radiobutton selected), * or -1 if canceled * - * Providing the option to also display a "(Deselect)" radiobutton makes the - * "Swap Layers" command (and GerbView's "Export to Pcbnew" command) more "user - * friendly", by permitting any layer to be "deselected" immediately after its + * Providing the option to also display a "Clear" button makes the + * "Swap Layers" command more "user friendly", + * by permitting any layer to be "deselected" immediately after its * corresponding radiobutton has been clicked on. (It would otherwise be * necessary to first cancel the "Select Layer:" dialog box (invoked after a * different radiobutton is clicked on) prior to then clicking on the - * "Deselect" - * button provided within the "Swap Layers:" or "Layer selection:" dialog box). + * "Clear" button provided within the "Swap Layers:" + * or "Layer selection:" dialog box). */ -LAYER_NUM PCB_BASE_FRAME::SelectLayer( LAYER_NUM default_layer, - LAYER_NUM min_layer, - LAYER_NUM max_layer, - bool null_layer ) +LAYER_NUM PCB_BASE_FRAME::SelectLayer( LAYER_NUM aDefaultLayer, + LAYER_NUM aMinlayer, + LAYER_NUM aMaxLayer, + bool aDeselectTool ) { - SELECT_LAYER_DIALOG* frame = new SELECT_LAYER_DIALOG( this, - default_layer, - min_layer, - max_layer, - null_layer ); - - LAYER_NUM layer = frame->ShowModal(); - frame->Destroy(); + PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), + aDefaultLayer, aMinlayer, aMaxLayer, + aDeselectTool ); + dlg.ShowModal(); + LAYER_NUM layer = dlg.GetLayerSelection(); return layer; } /* - * The "OK" and "Cancel" buttons are positioned (in a horizontal line) - * beneath the "Layer" radiobox, unless that contains only one column of - * radiobuttons, in which case they are positioned (in a vertical line) - * to the right of that radiobox. + * This class display a double pcb copper layers list in a dialog, + * to select a layer pair from this list */ -SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( PCB_BASE_FRAME* parent, - LAYER_NUM default_layer, LAYER_NUM min_layer, - LAYER_NUM max_layer, bool null_layer ) : - wxDialog( parent, -1, _( "Select Layer:" ), wxPoint( -1, -1 ), - wxSize( 470, 250 ), - DIALOG_STYLE ) -{ - BOARD* board = parent->GetBoard(); - wxButton* Button; - LAYER_NUM ii; - wxString LayerList[NB_PCB_LAYERS + 1]; // One extra element for "(Deselect)" - // radiobutton - int LayerCount, LayerSelect = -1; - - m_Parent = parent; - - // Build the layer list - LayerCount = 0; - LAYER_MSK Masque_Layer = g_TabAllCopperLayerMask[board->GetCopperLayerCount() - 1]; - Masque_Layer |= ALL_NO_CU_LAYERS; - - for( ii = FIRST_LAYER; ii < NB_PCB_LAYERS; ++ii ) - { - m_LayerId[ii] = FIRST_LAYER; - - if( GetLayerMask( ii ) & Masque_Layer ) - { - if( min_layer > ii ) - continue; - - if( ( max_layer >= 0 ) && ( max_layer < ii ) ) - break; - - LayerList[LayerCount] = board->GetLayerName( ii ); - - if( ii == default_layer ) - LayerSelect = LayerCount; - - m_LayerId[LayerCount] = ii; - LayerCount++; - } - } - - // When appropriate, also provide a "(Deselect)" radiobutton - if( null_layer ) - { - LayerList[LayerCount] = _( "(Deselect)" ); - - if( NB_PCB_LAYERS == default_layer ) - LayerSelect = LayerCount; - - m_LayerId[LayerCount] = NB_PCB_LAYERS; - LayerCount++; - } - - m_LayerList = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ), - wxPoint( -1, -1 ), wxSize( -1, -1 ), - LayerCount, LayerList, - (LayerCount < 8) ? LayerCount : 8, - wxRA_SPECIFY_ROWS ); - - if( LayerSelect >= 0 ) - m_LayerList->SetSelection( LayerSelect ); - - wxBoxSizer* FrameBoxSizer = new wxBoxSizer( wxHORIZONTAL ); - SetSizer( FrameBoxSizer ); - FrameBoxSizer->Add( m_LayerList, 0, wxALIGN_TOP | wxALL, 5 ); - wxBoxSizer* ButtonBoxSizer = new wxBoxSizer( wxVERTICAL ); - FrameBoxSizer->Add( ButtonBoxSizer, 0, wxALIGN_BOTTOM | wxALL, 0 ); - - Button = new wxButton( this, wxID_OK, _( "OK" ) ); - Button->SetDefault(); - ButtonBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); - - Button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); - ButtonBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); - - SetFocus(); - - GetSizer()->SetSizeHints( this ); - - Center(); -} - - -void SELECT_LAYER_DIALOG::OnLayerSelected( wxCommandEvent& event ) -{ - int ii = m_LayerId[m_LayerList->GetSelection()]; - - EndModal( ii ); -} - - -void SELECT_LAYER_DIALOG::OnCancelClick( wxCommandEvent& event ) -{ - EndModal( -1 ); -} - - -/*********************************************/ -/* Dialog for the selecting pairs of layers. */ -/*********************************************/ - -class SELECT_LAYERS_PAIR_DIALOG : public wxDialog +class SELECT_COPPER_LAYERS_PAIR_DIALOG: public PCB_LAYER_SELECTOR, + public DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE { private: - PCB_BASE_FRAME* m_Parent; - wxRadioBox* m_LayerListTOP; - wxRadioBox* m_LayerListBOTTOM; - LAYER_NUM m_LayerId[NB_COPPER_LAYERS]; + BOARD* m_brd; + LAYER_NUM m_frontLayer; + LAYER_NUM m_backLayer; + int m_leftRowSelected; + int m_rightRowSelected; -public: SELECT_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* parent ); - ~SELECT_LAYERS_PAIR_DIALOG() { }; +public: + SELECT_COPPER_LAYERS_PAIR_DIALOG( wxWindow* aParent, BOARD * aPcb, + LAYER_NUM aFrontLayer, LAYER_NUM aBackLayer ); + + void GetLayerPair( LAYER_NUM& aFrontLayer, LAYER_NUM& aBackLayer ) + { + aFrontLayer = m_frontLayer; + aBackLayer = m_backLayer; + } private: - void OnOkClick( wxCommandEvent& event ); - void OnCancelClick( wxCommandEvent& event ); + void OnLeftGridClick( wxGridEvent& event ); + void OnRightGridClick( wxGridEvent& event ); + + void OnOkClick( wxCommandEvent& event ) + { + EndModal( wxID_OK ); + } + + void OnCancelClick( wxCommandEvent& event ) + { + EndModal( wxID_CANCEL ); + } + + void BuildList(); - DECLARE_EVENT_TABLE() }; - -BEGIN_EVENT_TABLE( SELECT_LAYERS_PAIR_DIALOG, wxDialog ) - EVT_BUTTON( wxID_OK, SELECT_LAYERS_PAIR_DIALOG::OnOkClick ) - EVT_BUTTON( wxID_CANCEL, SELECT_LAYERS_PAIR_DIALOG::OnCancelClick ) -END_EVENT_TABLE() - - -/* Display a list of two copper layers for selection of a pair of layers +/* Display a list of two copper layers to choose a pair of layers * for auto-routing, vias ... */ void PCB_BASE_FRAME::SelectLayerPair() { - // Check whether more than one copper layer has been enabled for the - // current PCB file, as Layer Pairs can only meaningfully be defined - // within PCB files which contain at least two copper layers. - if( GetBoard()->GetCopperLayerCount() < 2 ) + PCB_SCREEN* screen = GetScreen(); + SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( this, GetBoard(), + screen->m_Route_Layer_TOP, + screen->m_Route_Layer_BOTTOM ); + + if( dlg.ShowModal() == wxID_OK ) { - wxString InfoMsg; - InfoMsg = _( "Less than two copper layers are being used." ); - InfoMsg << wxT( "\n" ) << _( "Hence layer pairs cannot be specified." ); - DisplayInfoMessage( this, InfoMsg ); - return; + dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM ); + + // select the same layer for both layers is allowed (normal in some boards) + // but could be a mistake. So display an info message + if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM ) + DisplayInfoMessage( this, + _( "Warning: The Top Layer and Bottom Layer are same." ) ); } - SELECT_LAYERS_PAIR_DIALOG* frame = new SELECT_LAYERS_PAIR_DIALOG( this ); - - int result = frame->ShowModal(); - frame->Destroy(); m_canvas->MoveCursorToCrossHair(); - - // if user changed colors and we are in high contrast mode, then redraw - // because the PAD_SMD pads may change color. - if( result >= 0 && DisplayOpt.ContrastModeDisplay ) - { - m_canvas->Refresh(); - } } - -SELECT_LAYERS_PAIR_DIALOG::SELECT_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* parent ) : - wxDialog( parent, -1, _( "Select Layer Pair:" ), wxPoint( -1, -1 ), - wxSize( 470, 250 ), DIALOG_STYLE ) +SELECT_COPPER_LAYERS_PAIR_DIALOG:: + SELECT_COPPER_LAYERS_PAIR_DIALOG( wxWindow* aParent, BOARD * aPcb, + LAYER_NUM aFrontLayer, LAYER_NUM aBackLayer) : + PCB_LAYER_SELECTOR( aPcb ), + DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( aParent ) { - BOARD* board = parent->GetBoard(); - wxButton* Button; - wxString LayerList[NB_COPPER_LAYERS]; - LAYER_NUM LayerTopSelect = FIRST_LAYER, LayerBottomSelect = FIRST_LAYER; - - m_Parent = parent; - - PCB_SCREEN* screen = (PCB_SCREEN*) m_Parent->GetScreen(); - LAYER_MSK Masque_Layer = g_TabAllCopperLayerMask[board->GetCopperLayerCount() - 1]; - Masque_Layer |= ALL_NO_CU_LAYERS; - - LAYER_NUM LayerCount = FIRST_LAYER; - for( LAYER_NUM ii = FIRST_COPPER_LAYER; ii < NB_COPPER_LAYERS; ++ii ) - { - m_LayerId[ii] = FIRST_LAYER; - - if( (GetLayerMask( ii ) & Masque_Layer) ) - { - LayerList[LayerCount] = board->GetLayerName( ii ); - - if( ii == screen->m_Route_Layer_TOP ) - LayerTopSelect = LayerCount; - - if( ii == screen->m_Route_Layer_BOTTOM ) - LayerBottomSelect = LayerCount; - - m_LayerId[LayerCount] = ii; - ++LayerCount; - } - } - - m_LayerListTOP = new wxRadioBox( this, ID_LAYER_SELECT_TOP, - _( "Top Layer" ), - wxPoint( -1, -1 ), wxSize( -1, -1 ), - LayerCount, LayerList, - (LayerCount < 8) ? LayerCount : 8, - wxRA_SPECIFY_ROWS ); - m_LayerListTOP->SetSelection( LayerTopSelect ); - - m_LayerListBOTTOM = new wxRadioBox( this, ID_LAYER_SELECT_BOTTOM, - _( "Bottom Layer" ), - wxPoint( -1, -1 ), wxSize( -1, -1 ), - LayerCount, LayerList, - (LayerCount < 8) ? LayerCount : 8, - wxRA_SPECIFY_ROWS ); - m_LayerListBOTTOM->SetSelection( LayerBottomSelect ); - - wxBoxSizer* FrameBoxSizer = new wxBoxSizer( wxVERTICAL ); - SetSizer( FrameBoxSizer ); - - wxBoxSizer* RadioBoxSizer = new wxBoxSizer( wxHORIZONTAL ); - FrameBoxSizer->Add( RadioBoxSizer, 0, wxALIGN_LEFT | wxALL, 0 ); - - wxBoxSizer* ButtonBoxSizer = new wxBoxSizer( wxHORIZONTAL ); - FrameBoxSizer->Add( ButtonBoxSizer, 0, wxALIGN_RIGHT | wxALL, 0 ); - - RadioBoxSizer->Add( m_LayerListTOP, 0, wxALIGN_TOP | wxALL, 5 ); - RadioBoxSizer->Add( m_LayerListBOTTOM, 0, wxALIGN_TOP | wxALL, 5 ); - - Button = new wxButton( this, wxID_OK, _( "OK" ) ); - Button->SetDefault(); - ButtonBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); - - Button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); - ButtonBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); + m_frontLayer = aFrontLayer; + m_backLayer = aBackLayer; + m_leftRowSelected = 0; + m_rightRowSelected = 0; + BuildList(); SetFocus(); - GetSizer()->SetSizeHints( this ); Center(); } - -void SELECT_LAYERS_PAIR_DIALOG::OnOkClick( wxCommandEvent& event ) +void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() { - // select the same layer for top and bottom is allowed (normal in some - // boards) - // but could be a mistake. So display an info message - if( m_LayerId[m_LayerListTOP->GetSelection()] == m_LayerId[m_LayerListBOTTOM->GetSelection()] ) - DisplayInfoMessage( this, - _( "Warning: The Top Layer and Bottom Layer are same." ) ); + m_leftGridLayers->SetColFormatNumber( LAYERID_COLNUM ); + m_rightGridLayers->SetColFormatNumber( LAYERID_COLNUM ); + m_leftGridLayers->HideCol( LAYERID_COLNUM ); + m_rightGridLayers->HideCol( LAYERID_COLNUM ); + m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 ); + m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 ); - PCB_SCREEN* screen = (PCB_SCREEN*) m_Parent->GetScreen(); + // Select a not show cell, to avoid a wrong cell selection for user + m_leftGridLayers->GoToCell( 0, LAYERID_COLNUM ); + m_rightGridLayers->GoToCell( 0, LAYERID_COLNUM ); - screen->m_Route_Layer_TOP = m_LayerId[m_LayerListTOP->GetSelection()]; - screen->m_Route_Layer_BOTTOM = m_LayerId[m_LayerListBOTTOM->GetSelection()]; + int row = 0; + wxString layernum; + wxString layername; + for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i ) + { + LAYER_NUM layerid = i; - EndModal( 0 ); + if( m_layerorder ) + layerid = layertranscode[i]; + + if( ! IsLayerEnabled( layerid ) ) + continue; + + if( layerid > LAST_COPPER_LAYER ) + continue; + + wxColour color = MakeColour( GetLayerColor( layerid ) ); + layername = GetLayerName( layerid ); + layernum.Printf( wxT("%d"), layerid ); + + if( row ) + m_leftGridLayers->AppendRows( 1 ); + m_leftGridLayers->SetCellBackgroundColour ( row, COLOR_COLNUM, + color ); + m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, + layername ); + m_leftGridLayers->SetCellValue( row, LAYERID_COLNUM, + layernum ); + + if( m_frontLayer == layerid ) + { + m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, + wxT("X") ); + m_leftGridLayers->SetCellBackgroundColour( row, SELECT_COLNUM, + color ); + m_leftRowSelected = row; + } + + if( row ) + m_rightGridLayers->AppendRows( 1 ); + m_rightGridLayers->SetCellBackgroundColour ( row, COLOR_COLNUM, + color ); + m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, + layername ); + m_rightGridLayers->SetCellValue( row, LAYERID_COLNUM, + layernum ); + + if( m_backLayer == layerid ) + { + m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, + wxT("X") ); + m_rightGridLayers->SetCellBackgroundColour ( row, SELECT_COLNUM, + color ); + m_rightRowSelected = row; + } + + row++; + } + + m_leftGridLayers->AutoSizeColumn(LAYERNAME_COLNUM); + m_rightGridLayers->AutoSizeColumn(LAYERNAME_COLNUM); + m_leftGridLayers->AutoSizeColumn(SELECT_COLNUM); + m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM); } - -void SELECT_LAYERS_PAIR_DIALOG::OnCancelClick( wxCommandEvent& event ) +void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridClick( wxGridEvent& event ) { - EndModal( -1 ); + int row = event.GetRow(); + wxString text = m_leftGridLayers->GetCellValue( row, LAYERID_COLNUM ); + long layer; + text.ToLong( &layer ); + + if( m_frontLayer == layer ) + return; + + m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, + wxEmptyString ); + m_leftGridLayers->SetCellBackgroundColour ( m_leftRowSelected, SELECT_COLNUM, + m_leftGridLayers->GetDefaultCellBackgroundColour() ); + + m_frontLayer = layer; + m_leftRowSelected = row; + m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, + wxT("X") ); + m_leftGridLayers->SetCellBackgroundColour( row, SELECT_COLNUM, + MakeColour( GetLayerColor( layer ) ) ); + +} + +void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridClick( wxGridEvent& event ) +{ + int row = event.GetRow(); + wxString text = m_rightGridLayers->GetCellValue( row, LAYERID_COLNUM ); + long layer; + text.ToLong( &layer ); + + if( m_backLayer == layer ) + return; + + m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, + wxEmptyString ); + m_rightGridLayers->SetCellBackgroundColour ( m_rightRowSelected, SELECT_COLNUM, + m_rightGridLayers->GetDefaultCellBackgroundColour() ); + + m_backLayer = layer; + m_rightRowSelected = row; + m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, + wxT("X") ); + m_rightGridLayers->SetCellBackgroundColour ( row, SELECT_COLNUM, + MakeColour( GetLayerColor( layer ) ) ); } From e4710f54f8c8f686c903cb0bb6d4c746a45c2dcd Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 30 Aug 2013 21:37:56 +0200 Subject: [PATCH 06/29] add missing files --- .../dialogs/dialog_layer_selection_base.cpp | 225 ++++++++++++++++++ pcbnew/dialogs/dialog_layer_selection_base.h | 87 +++++++ 2 files changed, 312 insertions(+) create mode 100644 pcbnew/dialogs/dialog_layer_selection_base.cpp create mode 100644 pcbnew/dialogs/dialog_layer_selection_base.h diff --git a/pcbnew/dialogs/dialog_layer_selection_base.cpp b/pcbnew/dialogs/dialog_layer_selection_base.cpp new file mode 100644 index 0000000000..ccb42218d5 --- /dev/null +++ b/pcbnew/dialogs/dialog_layer_selection_base.cpp @@ -0,0 +1,225 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 8 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_layer_selection_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_LAYER_SELECTION_BASE::DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerUpper; + bSizerUpper = new wxBoxSizer( wxHORIZONTAL ); + + m_leftGridLayers = new wxGrid( this, ID_LEFT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_leftGridLayers->CreateGrid( 1, 4 ); + m_leftGridLayers->EnableEditing( false ); + m_leftGridLayers->EnableGridLines( true ); + m_leftGridLayers->EnableDragGridSize( false ); + m_leftGridLayers->SetMargins( 0, 3 ); + + // Columns + m_leftGridLayers->EnableDragColMove( false ); + m_leftGridLayers->EnableDragColSize( false ); + m_leftGridLayers->SetColLabelSize( 0 ); + m_leftGridLayers->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_leftGridLayers->EnableDragRowSize( false ); + m_leftGridLayers->SetRowLabelSize( 0 ); + m_leftGridLayers->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + m_leftGridLayers->SetLabelBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + // Cell Defaults + m_leftGridLayers->SetDefaultCellBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); + m_leftGridLayers->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSizerUpper->Add( m_leftGridLayers, 0, wxALL|wxEXPAND, 5 ); + + m_rightGridLayers = new wxGrid( this, ID_RIGHT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_rightGridLayers->CreateGrid( 1, 4 ); + m_rightGridLayers->EnableEditing( false ); + m_rightGridLayers->EnableGridLines( true ); + m_rightGridLayers->EnableDragGridSize( false ); + m_rightGridLayers->SetMargins( 0, 3 ); + + // Columns + m_rightGridLayers->EnableDragColMove( false ); + m_rightGridLayers->EnableDragColSize( false ); + m_rightGridLayers->SetColLabelSize( 0 ); + m_rightGridLayers->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_rightGridLayers->EnableDragRowSize( false ); + m_rightGridLayers->SetRowLabelSize( 0 ); + m_rightGridLayers->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_rightGridLayers->SetDefaultCellBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); + m_rightGridLayers->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSizerUpper->Add( m_rightGridLayers, 0, wxALL|wxEXPAND, 5 ); + + + bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); + + m_buttonClear = new wxButton( this, wxID_ANY, _("Clear Selection"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerMain->Add( m_buttonClear, 0, wxALL|wxALIGN_RIGHT, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + m_leftGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftGridClick ), NULL, this ); + m_rightGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnRightGridClick ), NULL, this ); + m_buttonClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LAYER_SELECTION_BASE::OnClearSelection ), NULL, this ); +} + +DIALOG_LAYER_SELECTION_BASE::~DIALOG_LAYER_SELECTION_BASE() +{ + // Disconnect Events + m_leftGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftGridClick ), NULL, this ); + m_rightGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnRightGridClick ), NULL, this ); + m_buttonClear->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LAYER_SELECTION_BASE::OnClearSelection ), NULL, this ); + +} + +DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerUpper; + bSizerUpper = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizerLeft; + bSizerLeft = new wxBoxSizer( wxVERTICAL ); + + m_staticTextTopLayer = new wxStaticText( this, wxID_ANY, _("Top/Front Layer"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTopLayer->Wrap( -1 ); + bSizerLeft->Add( m_staticTextTopLayer, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_leftGridLayers = new wxGrid( this, ID_LEFT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_leftGridLayers->CreateGrid( 1, 4 ); + m_leftGridLayers->EnableEditing( false ); + m_leftGridLayers->EnableGridLines( true ); + m_leftGridLayers->EnableDragGridSize( false ); + m_leftGridLayers->SetMargins( 0, 3 ); + + // Columns + m_leftGridLayers->EnableDragColMove( false ); + m_leftGridLayers->EnableDragColSize( false ); + m_leftGridLayers->SetColLabelSize( 0 ); + m_leftGridLayers->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_leftGridLayers->EnableDragRowSize( false ); + m_leftGridLayers->SetRowLabelSize( 0 ); + m_leftGridLayers->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + m_leftGridLayers->SetLabelBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + // Cell Defaults + m_leftGridLayers->SetDefaultCellBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); + m_leftGridLayers->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSizerLeft->Add( m_leftGridLayers, 1, wxALL|wxEXPAND, 5 ); + + + bSizerUpper->Add( bSizerLeft, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizerRight; + bSizerRight = new wxBoxSizer( wxVERTICAL ); + + m_staticTextBottomLayer = new wxStaticText( this, wxID_ANY, _("Bottom/Back Layer"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBottomLayer->Wrap( -1 ); + bSizerRight->Add( m_staticTextBottomLayer, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_rightGridLayers = new wxGrid( this, ID_RIGHT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_rightGridLayers->CreateGrid( 1, 4 ); + m_rightGridLayers->EnableEditing( false ); + m_rightGridLayers->EnableGridLines( true ); + m_rightGridLayers->EnableDragGridSize( false ); + m_rightGridLayers->SetMargins( 0, 3 ); + + // Columns + m_rightGridLayers->EnableDragColMove( false ); + m_rightGridLayers->EnableDragColSize( false ); + m_rightGridLayers->SetColLabelSize( 0 ); + m_rightGridLayers->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_rightGridLayers->EnableDragRowSize( false ); + m_rightGridLayers->SetRowLabelSize( 0 ); + m_rightGridLayers->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_rightGridLayers->SetDefaultCellBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); + m_rightGridLayers->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + bSizerRight->Add( m_rightGridLayers, 1, wxALL|wxEXPAND, 5 ); + + + bSizerUpper->Add( bSizerRight, 1, wxEXPAND, 5 ); + + + bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + bSizerMain->Add( m_sdbSizer, 0, wxEXPAND, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + m_leftGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnLeftGridClick ), NULL, this ); + m_rightGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnRightGridClick ), NULL, this ); + m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnCancelClick ), NULL, this ); + m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnOKClick ), NULL, this ); +} + +DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::~DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE() +{ + // Disconnect Events + m_leftGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnLeftGridClick ), NULL, this ); + m_rightGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnRightGridClick ), NULL, this ); + m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnCancelClick ), NULL, this ); + m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::OnOKClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_layer_selection_base.h b/pcbnew/dialogs/dialog_layer_selection_base.h new file mode 100644 index 0000000000..a124524afa --- /dev/null +++ b/pcbnew/dialogs/dialog_layer_selection_base.h @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 8 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_LAYER_SELECTION_BASE_H__ +#define __DIALOG_LAYER_SELECTION_BASE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +#define ID_LEFT_LIST 1000 +#define ID_RIGHT_LIST 1001 + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_LAYER_SELECTION_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_LAYER_SELECTION_BASE : public wxDialog +{ + private: + + protected: + wxGrid* m_leftGridLayers; + wxGrid* m_rightGridLayers; + wxButton* m_buttonClear; + + // Virtual event handlers, overide them in your derived class + virtual void OnLeftGridClick( wxGridEvent& event ) { event.Skip(); } + virtual void OnRightGridClick( wxGridEvent& event ) { event.Skip(); } + virtual void OnClearSelection( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Layer:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 452,183 ), long style = wxCAPTION|wxCLOSE_BOX ); + ~DIALOG_LAYER_SELECTION_BASE(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE : public wxDialog +{ + private: + + protected: + wxStaticText* m_staticTextTopLayer; + wxGrid* m_leftGridLayers; + wxStaticText* m_staticTextBottomLayer; + wxGrid* m_rightGridLayers; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnLeftGridClick( wxGridEvent& event ) { event.Skip(); } + virtual void OnRightGridClick( wxGridEvent& event ) { event.Skip(); } + virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOKClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Cpper Layer Pair:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 332,175 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE(); + +}; + +#endif //__DIALOG_LAYER_SELECTION_BASE_H__ From 4d1dc14b45e00759d59fcfd71203498e448368c3 Mon Sep 17 00:00:00 2001 From: Brian Sidebotham Date: Sat, 31 Aug 2013 16:53:46 +0100 Subject: [PATCH 07/29] * Fix Bug 1219239 - EESCHEMA crashes when editing a template field in libedit through the context menu --- eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp index 19711d3b42..0244c0a406 100644 --- a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp +++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp @@ -495,7 +495,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers() // add a new field unconditionally to the UI only for this template fieldname // field id must not be in range 0 - MANDATORY_FIELDS, set before saving to disk - LIB_FIELD fld(-1); + LIB_FIELD fld( m_libEntry, -1 ); // See if field by same name already exists in component. LIB_FIELD* libField = findfield( cmpFields, it->m_Name ); From 3fcf44ae32e01b28e854c04da5822cf8a8d0c95d Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 1 Sep 2013 12:49:01 -0500 Subject: [PATCH 08/29] Clarify, extend, and rename ky*.py to kicad_netlist_reader.py. Significantly enhance the bom_csv_grouped_by_value.py BOM generator. IMO it at this moment, the best BOM production tool for KiCad. --- scripts/bom-in-python/bom-generation.py | 30 +- scripts/bom-in-python/bom_csv_by_ref.py | 14 +- scripts/bom-in-python/bom_csv_by_ref_v2.py | 12 +- .../bom-in-python/bom_csv_grouped_by_value.py | 102 ++- scripts/bom-in-python/bom_html_by_value.py | 28 +- .../bom_html_grouped_by_value.py | 24 +- scripts/bom-in-python/kicad_netlist_reader.py | 727 ++++++++++++++++++ .../ky_generic_netlist_reader.py | 450 ----------- scripts/bom-in-python/round_robin.py | 12 +- scripts/bom-in-python/round_value_robin.py | 12 +- 10 files changed, 897 insertions(+), 514 deletions(-) create mode 100644 scripts/bom-in-python/kicad_netlist_reader.py delete mode 100644 scripts/bom-in-python/ky_generic_netlist_reader.py diff --git a/scripts/bom-in-python/bom-generation.py b/scripts/bom-in-python/bom-generation.py index 8746575348..c0cda72fd8 100644 --- a/scripts/bom-in-python/bom-generation.py +++ b/scripts/bom-in-python/bom-generation.py @@ -4,8 +4,10 @@ # Example: Sorted and Grouped HTML BOM with more advanced grouping # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import sys # Start with a basic html template @@ -43,9 +45,9 @@ def myEqu(self, other): result = True if self.getValue() != other.getValue(): result = False - elif self.getLib() != other.getLib(): + elif self.getLibName() != other.getLibName(): result = False - elif self.getPart() != other.getPart(): + elif self.getPartName() != other.getPartName(): result = False elif self.getFootprint() != other.getFootprint(): result = False @@ -61,18 +63,18 @@ def myEqu(self, other): # Override the component equivalence operator - it is important to do this # before loading the netlist, otherwise all components will have the original # equivalency operator. -ky_generic_netlist_reader.component.__equ__ = myEqu +kicad_netlist_reader.comp.__equ__ = myEqu # Generate an instance of a generic netlist, and load the netlist tree from # video.tmp. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write too, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout # Output a set of rows for a header providing general information @@ -88,9 +90,11 @@ row += "Description" + "Vendor" html = html.replace('', row + "") +components = net.getInterestingComponents() + # Get all of the components in groups of matching parts + values -# (see ky_generic_netlist_reader.py) -grouped = net.groupComponents() +# (see kicad_netlist_reader.py) +grouped = net.groupComponents(components) # Output all of the component information for group in grouped: @@ -99,17 +103,19 @@ for group in grouped: # Add the reference of every component in the group and keep a reference # to the component so that the other data can be filled in once per group for component in group: - refs += component.getRef() + ", " + if len(refs) > 0: + refs += ", " + refs += component.getRef() c = component row = "\n " row += "" + refs +"" + str(len(group)) - row += "" + c.getValue() + "" + c.getLib() + "/" - row += c.getPart() + "" + c.getDatasheet() + "" + row += "" + c.getValue() + "" + c.getLibName() + ":" + row += c.getPartName() + "" + c.getDatasheet() + "" row += c.getDescription() + "" + c.getField("Vendor") row += "" html = html.replace('', row + "") # Print the formatted html to output file -print >> f, html +print(html, file=f) diff --git a/scripts/bom-in-python/bom_csv_by_ref.py b/scripts/bom-in-python/bom_csv_by_ref.py index ccc874fd16..51f8e34a39 100644 --- a/scripts/bom-in-python/bom_csv_by_ref.py +++ b/scripts/bom-in-python/bom_csv_by_ref.py @@ -4,21 +4,23 @@ # Example: Tab delimited list (The same as std output) Ungrouped # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import csv import sys # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout # Create a new csv writer object to use as the output formatter, although we @@ -32,7 +34,9 @@ out.writerow(['Tool:', net.getTool()]) out.writerow(['Component Count:', len(net.components)]) out.writerow(['Ref', 'Value', 'Part', 'Documentation', 'Description', 'Vendor']) +components = net.getInterestingComponents() + # Output all of the component information -for c in net.components: - out.writerow([c.getRef(), c.getValue(), c.getLib() + "/" + c.getPart(), +for c in components: + out.writerow([c.getRef(), c.getValue(), c.getLibName() + ":" + c.getPartName(), c.getDatasheet(), c.getDescription(), c.getField("Vendor")]) diff --git a/scripts/bom-in-python/bom_csv_by_ref_v2.py b/scripts/bom-in-python/bom_csv_by_ref_v2.py index 38e6f0c75f..e3bef12118 100644 --- a/scripts/bom-in-python/bom_csv_by_ref_v2.py +++ b/scripts/bom-in-python/bom_csv_by_ref_v2.py @@ -4,21 +4,23 @@ # Example: Ungrouped (One component per row) CSV output # +from __future__ import print_function + # Import the KiCad python helper module -import ky_generic_netlist_reader +import kicad_netlist_reader import csv import sys # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout # Create a new csv writer object to use as the output formatter @@ -31,8 +33,10 @@ out.writerow(['Tool:', net.getTool()]) out.writerow(['Component Count:', len(net.components)]) out.writerow(['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor']) +components = net.getInterestingComponents() + # Output all of the component information (One component per row) -for c in net.components: +for c in components: out.writerow([c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(), c.getField("Manufacturer"), c.getField("Vendor")]) diff --git a/scripts/bom-in-python/bom_csv_grouped_by_value.py b/scripts/bom-in-python/bom_csv_grouped_by_value.py index 81d3acecf6..dba801bc06 100644 --- a/scripts/bom-in-python/bom_csv_grouped_by_value.py +++ b/scripts/bom-in-python/bom_csv_grouped_by_value.py @@ -4,49 +4,123 @@ # Example: Sorted and Grouped CSV BOM # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import csv import sys + +if len(sys.argv) != 3: + print("Usage ", __file__, " ", file=sys.stderr) + sys.exit(1) + + # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout -# Create a new csv writer object to use as the output formatter -out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL) +# subset the components to those wanted in the BOM, controlled +# by block in kicad_netlist_reader.py +components = net.getInterestingComponents() -# Output a set of rows for a header providing general information +compfields = net.gatherComponentFieldUnion(components) +partfields = net.gatherLibPartFieldUnion() + +# remove Reference, Value, Datasheet, and Footprint, they will come from 'columns' below +partfields -= set( ['Reference', 'Value', 'Datasheet', 'Footprint'] ) + +columnset = compfields | partfields # union + +# prepend an initial 'hard coded' list and put the enchillada into list 'columns' +columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) + +# Create a new csv writer object to use as the output formatter +out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL) + +# Output a set of rows as a header providing general information out.writerow(['Source:', net.getSource()]) out.writerow(['Date:', net.getDate()]) out.writerow(['Tool:', net.getTool()]) -out.writerow(['Component Count:', len(net.components)]) -out.writerow(['Ref', 'Qnty', 'Value', 'Part', 'Datasheet', 'Description', 'Vendor']) +out.writerow(['Component Count:', len(components)]) +out.writerow([]) +out.writerow(['Individual Components:']) +out.writerow([]) # blank line +out.writerow(columns) + +# Output all the interesting components individually first: +row = [] +for c in components: + del row[:] + row.append('') # item is blank in individual table + row.append('') # Qty is always 1, why print it + row.append( c.getRef() ) # Reference + row.append( c.getValue() ) # Value + row.append( c.getLibName() + ":" + c.getPartName() ) # LibPart + #row.append( c.getDescription() ) + row.append( c.getFootprint() ) + row.append( c.getDatasheet() ) + + # from column 7 upwards, use the fieldnames to grab the data + for field in columns[7:]: + row.append( c.getField( field ) ); + + out.writerow(row) + + +out.writerow([]) # blank line +out.writerow([]) # blank line +out.writerow([]) # blank line + +out.writerow(['Collated Components:']) +out.writerow([]) # blank line +out.writerow(columns) # reuse same columns + + # Get all of the components in groups of matching parts + values -# (see ky_generic_netlist_reader.py) -grouped = net.groupComponents() +# (see kicad_netlist_reader.py) +grouped = net.groupComponents(components) -# Output all of the component information + +# Output component information organized by group, aka as collated: +item = 0 for group in grouped: + del row[:] refs = "" # Add the reference of every component in the group and keep a reference # to the component so that the other data can be filled in once per group for component in group: - refs += component.getRef() + ", " + if len(refs) > 0: + refs += ", " + refs += component.getRef() c = component # Fill in the component groups common data - out.writerow([refs, len(group), c.getValue(), c.getLib() + "/" + c.getPart(), c.getDatasheet(), - c.getDescription(), c.getField("Vendor")]) + # columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) + item += 1 + row.append( item ) + row.append( len(group) ) + row.append( refs ); + row.append( c.getValue() ) + row.append( c.getLibName() + ":" + c.getPartName() ) + row.append( net.getGroupFootprint(group) ) + row.append( net.getGroupDatasheet(group) ) + # from column 7 upwards, use the fieldnames to grab the data + for field in columns[7:]: + row.append( net.getGroupField(group, field) ); + out.writerow( row ) + +f.close() diff --git a/scripts/bom-in-python/bom_html_by_value.py b/scripts/bom-in-python/bom_html_by_value.py index 4c7fa5f2a5..244248ad71 100644 --- a/scripts/bom-in-python/bom_html_by_value.py +++ b/scripts/bom-in-python/bom_html_by_value.py @@ -4,8 +4,10 @@ # Example: Sorted and Grouped HTML BOM with more advanced grouping # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import sys # Start with a basic html template @@ -43,9 +45,9 @@ def myEqu(self, other): result = True if self.getValue() != other.getValue(): result = False - elif self.getLib() != other.getLib(): + elif self.getLibName() != other.getLibName(): result = False - elif self.getPart() != other.getPart(): + elif self.getPartName() != other.getPartName(): result = False elif self.getFootprint() != other.getFootprint(): result = False @@ -61,18 +63,18 @@ def myEqu(self, other): # Override the component equivalence operator - it is important to do this # before loading the netlist, otherwise all components will have the original # equivalency operator. -ky_generic_netlist_reader.component.__equ__ = myEqu +kicad_netlist_reader.comp.__equ__ = myEqu # Generate an instance of a generic netlist, and load the netlist tree from # video.xml. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write too, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout # Output a set of rows for a header providing general information @@ -90,9 +92,11 @@ row += "PartNumber" + "Vendor" html = html.replace('', row + "") +components = net.getInterestingComponents() + # Get all of the components in groups of matching parts + values -# (see ky_generic_netlist_reader.py) -grouped = net.groupComponents() +# (see kicad_netlist_reader.py) +grouped = net.groupComponents(components) # Output all of the component information for group in grouped: @@ -101,12 +105,14 @@ for group in grouped: # Add the reference of every component in the group and keep a reference # to the component so that the other data can be filled in once per group for component in group: - refs += component.getRef() + ", " + if len(refs) > 0: + refs += ", " + refs += component.getRef() c = component row = "" + refs +"" + str(len(group)) row += "" + c.getValue() + "" - row += c.getLib() + "/" + c.getPart() + "" + row += c.getLibName() + ":" + c.getPartName() + "" #row += c.getDatasheet() + "" row += c.getDescription() + "" row += c.getField("PartNumber") + "" @@ -116,4 +122,4 @@ for group in grouped: html = html.replace('', row + "") # Print the formatted html to output file -print >> f, html +print(html, file=f) diff --git a/scripts/bom-in-python/bom_html_grouped_by_value.py b/scripts/bom-in-python/bom_html_grouped_by_value.py index d1cb8912f7..11bcc5dfb0 100644 --- a/scripts/bom-in-python/bom_html_grouped_by_value.py +++ b/scripts/bom-in-python/bom_html_grouped_by_value.py @@ -4,8 +4,10 @@ # Example: Sorted and Grouped HTML BOM # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import sys # Start with a basic html template @@ -30,14 +32,14 @@ html = """ # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout # Output a set of rows for a header providing general information @@ -53,9 +55,11 @@ row += "Description" + "Vendor" html = html.replace('', row + "") +components = net.getInterestingComponents() + # Get all of the components in groups of matching parts + values -# (see ky_generic_netlist_reader.py) -grouped = net.groupComponents() +# (see kicad_netlist_reader.py) +grouped = net.groupComponents(components) # Output all of the component information for group in grouped: @@ -64,16 +68,18 @@ for group in grouped: # Add the reference of every component in the group and keep a reference # to the component so that the other data can be filled in once per group for component in group: - refs += component.getRef() + ", " + if len(refs) > 0: + refs += ", " + refs += component.getRef() c = component row = "" + refs +"" + str(len(group)) - row += "" + c.getValue() + "" + c.getLib() + "/" - row += c.getPart() + "" + c.getDatasheet() + "" + row += "" + c.getValue() + "" + c.getLibName() + ":" + row += c.getPartName() + "" + c.getDatasheet() + "" row += c.getDescription() + "" + c.getField("Vendor") row += "" html = html.replace('', row + "") # Print the formatted html to the file -print >> f, html +print(html, file=f) diff --git a/scripts/bom-in-python/kicad_netlist_reader.py b/scripts/bom-in-python/kicad_netlist_reader.py new file mode 100644 index 0000000000..8a01adcd19 --- /dev/null +++ b/scripts/bom-in-python/kicad_netlist_reader.py @@ -0,0 +1,727 @@ +# +# KiCad python module for interpreting generic netlists which can be used +# to generate Bills of materials, etc. +# +# No string formatting is used on purpose as the only string formatting that +# is current compatible with python 2.4+ to 3.0+ is the '%' method, and that +# is due to be deprecated in 3.0+ soon +# + +from __future__ import print_function +import sys +import xml.sax as sax +import re +import pdb + +#--------------------------------------------------------------------- + +# excluded_fields is a list of regular expressions. If any one matches a field +# from either a component or a libpart, then that will not be included as a +# column in the BOM. Otherwise all columns from all used libparts and components +# will be unionized and will appear. Some fields are impossible to blacklist, such +# as Ref, Value, Footprint, and Datasheet. Additionally Qty and Item are supplied +# unconditionally as columns, and may not be removed. +excluded_fields = [ + #'Price@1000' + ] + + +# You may exlude components from the BOM by either: +# +# 1) adding a custom field named "Installed" to your components and filling it +# with a value of "NU" (Normally Uninstalled). +# See netlist.getInterestingComponents(), or +# +# 2) blacklisting it in any of the three following lists: + + +# regular expressions which match component 'Reference' fields of components that +# are to be excluded from the BOM. +excluded_references = [ + 'TP[0-9]+' # all test points + ] + + +# regular expressions which match component 'Value' fields of components that +# are to be excluded from the BOM. +excluded_values = [ + 'MOUNTHOLE', + 'SCOPETEST', + 'MOUNT_HOLE', + 'SOLDER_BRIDGE.*' + ] + + +# regular expressions which match component 'Footprint' fields of components that +# are to be excluded from the BOM. +excluded_footprints = [ + #'MOUNTHOLE' + ] + +#-------------------------------------------------------------------- + + +class xmlElement(): + """xml element which can represent all nodes of the netlist tree. It can be + used to easily generate various output formats by propogating format + requests to children recursively. + """ + def __init__(self, name, parent=None): + self.name = name + self.attributes = {} + self.parent = parent + self.chars = "" + self.children = [] + + def __str__(self): + """String representation of this netlist element + + """ + return self.name + "[" + self.chars + "]" + " attr_count:" + str(len(self.attributes)) + + def formatXML(self, nestLevel=0, amChild=False): + """Return this element formatted as XML + + Keywords: + nestLevel -- increases by one for each level of nesting. + amChild -- If set to True, the start of document is not returned. + + """ + s = "" + + indent = "" + for i in range(nestLevel): + indent += " " + + if not amChild: + s = "\n" + + s += indent + "<" + self.name + for a in self.attributes: + s += " " + a + "=\"" + self.attributes[a] + "\"" + + if (len(self.chars) == 0) and (len(self.children) == 0): + s += "/>" + else: + s += ">" + self.chars + + for c in self.children: + s += "\n" + s += c.formatXML(nestLevel+1, True) + + if (len(self.children) > 0): + s += "\n" + indent + + if (len(self.children) > 0) or (len(self.chars) > 0): + s += "" + + return s + + def formatHTML(self, amChild=False): + """Return this element formatted as HTML + + Keywords: + amChild -- If set to True, the start of document is not returned + + """ + s = "" + + if not amChild: + s = """ + + + + + + + + """ + + s += "\n" + + for c in self.children: + s += c.formatHTML(True) + + if not amChild: + s += """
" + self.name + "
" + self.chars + "
    " + for a in self.attributes: + s += "
  • " + a + " = " + self.attributes[a] + "
  • " + + s += "
+ + """ + + return s + + def addAttribute(self, attr, value): + """Add an attribute to this element""" + self.attributes[attr] = value + + def setAttribute(self, attr, value): + """Set an attributes value - in fact does the same thing as add + attribute + + """ + self.attributes[attr] = value + + def setChars(self, chars): + """Set the characters for this element""" + self.chars = chars + + def addChars(self, chars): + """Add characters (textual value) to this element""" + self.chars += chars + + def addChild(self, child): + """Add a child element to this element""" + self.children.append(child) + return self.children[len(self.children) - 1] + + def getParent(self): + """Get the parent of this element (Could be None)""" + return self.parent + + def getChild(self, name): + """Returns the first child element named 'name' + + Keywords: + name -- The name of the child element to return""" + for child in self.children: + if child.name == name: + return child + return None + + def getChildren(self, name=None): + if name: + # return _all_ children named "name" + ret = [] + for child in self.children: + if child.name == name: + ret.append(child) + return ret + else: + return self.children + + def get(self, elemName, attribute="", attrmatch=""): + """Return the text data for either an attribute or an xmlElement + """ + if (self.name == elemName): + if attribute != "": + try: + if attrmatch != "": + if self.attributes[attribute] == attrmatch: + return self.chars + else: + return self.attributes[attribute] + except AttributeError: + return "" + else: + return self.chars + + for child in self.children: + ret = child.get(elemName, attribute, attrmatch) + if ret != "": + return ret + + return "" + + + +class libpart(): + """Class for a library part, aka 'libpart' in the xml netlist file. + (Components in eeschema are instantiated from library parts.) + This part class is implemented by wrapping an xmlElement with accessors. + This xmlElement instance is held in field 'element'. + """ + def __init__(self, xml_element): + # + self.element = xml_element + + #def __str__(self): + # simply print the xmlElement associated with this part + #return str(self.element) + + def getLibName(self): + return self.element.get("libpart", "lib") + + def getPartName(self): + return self.element.get("libpart", "part") + + def getDescription(self): + return self.element.get("description") + + def getField(self, name): + return self.element.get("field", "name", name) + + def getFieldNames(self): + """Return a list of field names in play for this libpart. + """ + fieldNames = [] + fields = self.element.getChild('fields') + if fields: + for f in fields.getChildren(): + fieldNames.append( f.get('field','name') ) + return fieldNames + + def getDatasheet(self): + return self.getField("Datasheet") + + def getFootprint(self): + return self.getField("Footprint") + + def getAliases(self): + """Return a list of aliases or None""" + aliases = self.element.getChild("aliases") + if aliases: + ret = [] + children = aliases.getChildren() + # grab the text out of each child: + for child in children: + ret.append( child.get("alias") ) + return ret + return None + + +class comp(): + """Class for a component, aka 'comp' in the xml netlist file. + This component class is implemented by wrapping an xmlElement instance + with accessors. The xmlElement is held in field 'element'. + """ + + def __init__(self, xml_element): + self.element = xml_element + self.libpart = None + + # Set to true when this component is included in a component group + self.grouped = False + + def __eq__(self, other): + """Equlivalency operator, remember this can be easily overloaded""" + result = False + if self.getValue() == other.getValue(): + if self.getLibName() == other.getLibName(): + if self.getPartName() == other.getPartName(): + result = True + return result + + def setLibPart(self, part): + self.libpart = part + + def getLibPart(self): + return self.libpart + + def getPartName(self): + return self.element.get("libsource", "part") + + def getLibName(self): + return self.element.get("libsource", "lib") + + def setValue(self, value): + """Set the value of this component""" + v = self.element.getChild("value") + if v: + v.setChars(value) + + def getValue(self): + return self.element.get("value") + + def getField(self, name, libraryToo=True): + """Return the value of a field named name. The component is first + checked for the field, and then the components library part is checked + for the field. If the field doesn't exist in either, an empty string is + returned + + Keywords: + name -- The name of the field to return the value for + libraryToo -- look in the libpart's fields for the same name if not found + in component itself + """ + + field = self.element.get("field", "name", name) + if field == "" and libraryToo: + field = self.libpart.getField(name) + return field + + def getFieldNames(self): + """Return a list of field names in play for this component. Mandatory + fields are not included, and they are: Value, Footprint, Datasheet, Ref. + The netlist format only includes fields with non-empty values. So if a field + is empty, it will not be present in the returned list. + """ + fieldNames = [] + fields = self.element.getChild('fields') + if fields: + for f in fields.getChildren(): + fieldNames.append( f.get('field','name') ) + return fieldNames + + def getRef(self): + return self.element.get("comp", "ref") + + def getFootprint(self, libraryToo=True): + ret = self.element.get("footprint") + if ret =="" and libraryToo: + ret = self.libpart.getFootprint() + return ret + + def getDatasheet(self, libraryToo=True): + ret = self.element.get("datasheet") + if ret == '' and libraryToo: + ret = self.libpart.getDatasheet() + return ret + + def getTimestamp(self): + return self.element.get("tstamp") + + def getDescription(self): + return self.libpart.getDescription() + + +class netlist(): + """ Kicad generic netlist class. Generally loaded from a kicad generic + netlist file. Includes several helper functions to ease BOM creating + scripts + + """ + def __init__(self, fname=""): + """Initialiser for the genericNetlist class + + Keywords: + fname -- The name of the generic netlist file to open (Optional) + + """ + self.design = None + self.components = [] + self.libparts = [] + self.libraries = [] + self.nets = [] + + # The entire tree is loaded into self.tree + self.tree = [] + + self._curr_element = None + + # component blacklist regexs, made from exluded_* above. + self.excluded_references = [] + self.excluded_values = [] + self.excluded_footprints = [] + + if fname != "": + self.load(fname) + + def addChars(self, content): + """Add characters to the current element""" + self._curr_element.addChars(content) + + def addElement(self, name): + """Add a new kicad generic element to the list""" + if self._curr_element == None: + self.tree = xmlElement(name) + self._curr_element = self.tree + else: + self._curr_element = self._curr_element.addChild( + xmlElement(name, self._curr_element)) + + # If this element is a component, add it to the components list + if self._curr_element.name == "comp": + self.components.append(comp(self._curr_element)) + + # Assign the design element + if self._curr_element.name == "design": + self.design = self._curr_element + + # If this element is a library part, add it to the parts list + if self._curr_element.name == "libpart": + self.libparts.append(libpart(self._curr_element)) + + # If this element is a net, add it to the nets list + if self._curr_element.name == "net": + self.nets.append(self._curr_element) + + # If this element is a library, add it to the libraries list + if self._curr_element.name == "library": + self.libraries.append(self._curr_element) + + return self._curr_element + + def endDocument(self): + """Called when the netlist document has been fully parsed""" + # When the document is complete, the library parts must be linked to + # the components as they are seperate in the tree so as not to + # duplicate library part information for every component + for c in self.components: + for p in self.libparts: + if p.getLibName() == c.getLibName(): + if p.getPartName() == c.getPartName(): + c.setLibPart(p) + break + else: + aliases = p.getAliases() + if aliases and self.aliasMatch( c.getPartName(), aliases ): + c.setLibPart(p) + break; + + if not c.getLibPart(): + print( 'missing libpart for ref:', c.getRef(), c.getPartName(), c.getLibName() ) + + + def aliasMatch(self, partName, aliasList): + for alias in aliasList: + if partName == alias: + return True + return False + + def endElement(self): + """End the current element and switch to its parent""" + self._curr_element = self._curr_element.getParent() + + def getDate(self): + """Return the date + time string generated by the tree creation tool""" + return self.design.get("date") + + def getSource(self): + """Return the source string for the design""" + return self.design.get("source") + + def getTool(self): + """Return the tool string which was used to create the netlist tree""" + return self.design.get("tool") + + def gatherComponentFieldUnion(self, components=None): + """Gather the complete 'set' of unique component fields, fields found in any component. + """ + if not components: + components=self.components + + s = set() + for c in components: + s.update( c.getFieldNames() ) + + # omit anything matching any regex in excluded_fields + ret = set() + for field in s: + exclude = False + for rex in excluded_fields: + if re.match( rex, field ): + exclude = True + break + if not exclude: + ret.add(field) + + return ret # this is a python 'set' + + def gatherLibPartFieldUnion(self): + """Gather the complete 'set' of part fields, fields found in any part. + """ + s = set() + for p in self.libparts: + s.update( p.getFieldNames() ) + + # omit anything matching any regex in excluded_fields + ret = set() + for field in s: + exclude = False + for rex in excluded_fields: + if re.match( rex, field ): + exclude = True + break + if not exclude: + ret.add(field) + + return ret # this is a python 'set' + + def getInterestingComponents(self): + """Return a subset of all components, those that should show up in the BOM. + Omit those that should not, by consulting the blacklists: + excluded_values, excluded_refs, and excluded_footprints, which hold one + or more regular expressions. If any of the the regular expressions match + the corresponding field's value in a component, then the component is exluded. + """ + + # pre-compile all the regex expressions: + del self.excluded_references[:] + del self.excluded_values[:] + del self.excluded_footprints[:] + + for rex in excluded_references: + self.excluded_references.append( re.compile( rex ) ) + + for rex in excluded_values: + self.excluded_values.append( re.compile( rex ) ) + + for rex in excluded_footprints: + self.excluded_footprints.append( re.compile( rex ) ) + + # the subset of components to return, considered as "interesting". + ret = [] + + # run each component thru a series of tests, if it passes all, then add it + # to the interesting list 'ret'. + for c in self.components: + exclude = False + if not exclude: + for refs in self.excluded_references: + if refs.match(c.getRef()): + exclude = True + break; + if not exclude: + for vals in self.excluded_values: + if vals.match(c.getValue()): + exclude = True + break; + if not exclude: + for mods in self.excluded_footprints: + if mods.match(c.getFootprint()): + exclude = True + break; + + if not exclude: + # This is a fairly personal way to flag DNS (Do Not Stuff). NU for + # me means Normally Uninstalled. You can 'or in' another expression here. + if c.getField( "Installed" ) == 'NU': + exclude = True + + if not exclude: + ret.append(c) + + # Sort first by ref as this makes for easier to read BOM's + ret.sort(key=lambda g: g.getRef()) + + return ret + + + def groupComponents(self, components = None): + """Return a list of component lists. Components are grouped together + when the value, library and part identifiers match. + + Keywords: + components -- is a list of components, typically an interesting subset + of all components, or None. If None, then all components are looked at. + """ + if not components: + components = self.components + + groups = [] + + # Make sure to start off will all components ungrouped to begin with + for c in components: + c.grouped = False + + # Group components based on the value, library and part identifiers + for c in components: + if c.grouped == False: + c.grouped = True + newgroup = [] + newgroup.append(c) + + # Check every other ungrouped component against this component + # and add to the group as necessary + for ci in components: + if ci.grouped == False and ci == c: + newgroup.append(ci) + ci.grouped = True + + # Add the new component group to the groups list + groups.append(newgroup) + + # Each group is a list of components, we need to sort each list first + # to get them in order as this makes for easier to read BOM's + for g in groups: + g = sorted(g, key=lambda g: g.getRef()) + + # Finally, sort the groups to order the references alphabetically + groups = sorted(groups, key=lambda group: group[0].getRef()) + + return groups + + def getGroupField(self, group, field): + """Return the whatever is known about the given field by consulting each + component in the group. If any of them know something about the property/field, + then return that first non-blank value. + """ + for c in group: + ret = c.getField(field, False) + if ret != '': + return ret + return group[0].getLibPart().getField(field) + + def getGroupFootprint(self, group): + """Return the whatever is known about the Footprint by consulting each + component in the group. If any of them know something about the Footprint, + then return that first non-blank value. + """ + for c in group: + ret = c.getFootprint() + if ret != "": + return ret + return group[0].getLibPart().getFootprint() + + def getGroupDatasheet(self, group): + """Return the whatever is known about the Datasheet by consulting each + component in the group. If any of them know something about the Datasheet, + then return that first non-blank value. + """ + for c in group: + ret = c.getDatasheet() + if ret != "": + return ret + + if len(group) > 0: + return group[0].getLibPart().getDatasheet() + else: + print("NULL!") + return '' + + def formatXML(self): + """Return the whole netlist formatted in XML""" + return self.tree.formatXML() + + def formatHTML(self): + """Return the whole netlist formatted in HTML""" + return self.tree.formatHTML() + + def load(self, fname): + """Load a kicad generic netlist + + Keywords: + fname -- The name of the generic netlist file to open + + """ + try: + self._reader = sax.make_parser() + self._reader.setContentHandler(_gNetReader(self)) + self._reader.parse(fname) + except IOError as e: + print( __file__, ":", e, file=sys.stderr ) + sys.exit(-1) + + + +class _gNetReader(sax.handler.ContentHandler): + """SAX kicad generic netlist content handler - passes most of the work back + to the 'netlist' class which builds a complete tree in RAM for the design + + """ + def __init__(self, aParent): + self.parent = aParent + + def startElement(self, name, attrs): + """Start of a new XML element event""" + element = self.parent.addElement(name) + + for name in attrs.getNames(): + element.addAttribute(name, attrs.getValue(name)) + + def endElement(self, name): + self.parent.endElement() + + def characters(self, content): + # Ignore erroneous white space - ignoreableWhitespace does not get rid + # of the need for this! + if not content.isspace(): + self.parent.addChars(content) + + def endDocument(self): + """End of the XML document event""" + self.parent.endDocument() diff --git a/scripts/bom-in-python/ky_generic_netlist_reader.py b/scripts/bom-in-python/ky_generic_netlist_reader.py deleted file mode 100644 index 03fcaf3d73..0000000000 --- a/scripts/bom-in-python/ky_generic_netlist_reader.py +++ /dev/null @@ -1,450 +0,0 @@ -# -# KiCad python module for interpreting generic netlists which can be used -# to generate Bills of materials, etc. -# -# No string formatting is used on purpose as the only string formatting that -# is current compatible with python 2.4+ to 3.0+ is the '%' method, and that -# is due to be deprecated in 3.0+ soon -# - -import sys -import xml.sax as sax - - -class component(): - """Class for a set of component information""" - def __init__(self, element): - self.element = element - self.libpart = None - - # Set to true when this component is included in a component group - self.grouped = False - - def __eq__(self, other): - """Equlivalency operator, remember this can be easily overloaded""" - result = False - if self.getValue() == other.getValue(): - if self.getLib() == other.getLib(): - if self.getPart() == other.getPart(): - result = True - return result - - def setPart(self, part): - self.libpart = part - - def setValue(self, value): - """Set the value of this component""" - v = self.element.getChild("value") - if v: - v.setChars(value) - - def getValue(self): - return self.element.get("value") - - def getRef(self): - return self.element.get("comp", "ref") - - def getFootprint(self): - return self.element.get("footprint") - - def getDatasheet(self): - return self.element.get("datasheet") - - def getLib(self): - return self.element.get("libsource", "lib") - - def getPart(self): - return self.element.get("libsource", "part") - - def getTimestamp(self): - return self.element.get("tstamp") - - def getDescription(self): - # When attempting to access the part, we must take care in case the part - # cannot be found in the netlist - try: - d = self.libpart.getDescription() - except AttributeError: - d = "" - return d - - def getDatasheet(self): - # When attempting to access the part, we must take care in case the part - # cannot be found in the netlist - try: - d = self.libpart.getDatasheet() - except AttributeError: - d = "" - return d - - def getField(self, name): - """Return the value of a field named name. The component is first - checked for the field, and then the components library part is checked - for the field. If the field doesn't exist in either, an empty string is - returned - - Keywords: - name -- The name of the field to return the value for - - """ - field = self.element.get("field", "name", name) - if field == "": - try: - field = self.libpart.getField(name) - except AttributeError: - field = "" - return field - - -class netlistElement(): - """Generic netlist element. All elements for a netlist tree which can be - used to easily generate various output formats by propogating format - requests to all children - """ - def __init__(self, name, parent=None): - self.name = name - self.attributes = {} - self.parent = parent - self.chars = "" - self.children = [] - self.indent = "" - - def __str__(self): - """String representation of this netlist element - - """ - return (self.name + "[" + self.chars + "]" + " attr:" + - str(len(self.attributes[a]))) - - def formatXML(self, amChild=False): - """Return this element formatted as XML - - Keywords: - amChild -- If set to True, the start of document is not returned - - """ - s = "" - - if not amChild: - s = "\n" - - s += self.indent + "<" + self.name - for a in self.attributes: - s += " " + a + "=\"" + self.attributes[a] + "\"" - - if (len(self.chars) == 0) and (len(self.children) == 0): - s += "/>" - else: - s += ">" + self.chars - - for c in self.children: - c.indent += self.indent + " " - s += "\n" - s += c.formatXML(True) - - if (len(self.children) > 0): - s += "\n" + self.indent - - if (len(self.children) > 0) or (len(self.chars) > 0): - s += "" - - return s - - def formatHTML(self, amChild=False): - """Return this element formatted as HTML - - Keywords: - amChild -- If set to True, the start of document is not returned - - """ - s = "" - - if not amChild: - s = """ - - - - - - - - """ - - s += "\n" - - for c in self.children: - s += c.formatHTML(True) - - if not amChild: - s += """
" + self.name + "
" + self.chars + "
    " - for a in self.attributes: - s += "
  • " + a + " = " + self.attributes[a] + "
  • " - - s += "
- - """ - - return s - - def addAttribute(self, attr, value): - """Add an attribute to this element""" - self.attributes[attr] = value - - def setChars(self, chars): - """Set the characters for this element""" - self.chars = chars - - def addChars(self, chars): - """Add characters (textual value) to this element""" - self.chars += chars - - def addChild(self, child): - """Add a child element to this element""" - self.children.append(child) - return self.children[len(self.children) - 1] - - def getParent(self): - """Get the parent of this element (Could be None)""" - return self.parent - - def setAttribute(self, attr, value): - """Set an attributes value - in fact does the same thing as add - attribute - - """ - self.attributes[attr] = value - - def getChild(self, name): - """Returns a child element of name - - Keywords: - name -- The name of the child element to return""" - for child in self.children: - if child.name == name: - return child - - return None - - def get(self, element, attribute="", attrmatch=""): - """Return the data for either an attribute, or else an element""" - if (self.name == element): - if attribute != "": - if attrmatch != "": - if self.attributes[attribute] == attrmatch: - return self.chars - else: - return self.attributes[attribute] - else: - return self.chars - - for child in self.children: - if child.get(element, attribute, attrmatch) != "": - return child.get(element, attribute, attrmatch) - - return "" - - -class netlist(): - """ Kicad generic netlist class. Generally loaded from a kicad generic - netlist file. Includes several helper functions to ease BOM creating - scripts - - """ - def __init__(self, fname=""): - """Initialiser for the genericNetlist class - - Keywords: - fname -- The name of the generic netlist file to open (Optional) - - """ - self.design = None - self.components = [] - self.libparts = [] - self.libraries = [] - self.nets = [] - - # The entire tree is loaded into self.tree - self.tree = [] - - self._curr_element = None - - if fname != "": - self.load(fname) - - def addChars(self, content): - """Add characters to the current element""" - self._curr_element.addChars(content) - - def addElement(self, name): - """Add a new kicad generic element to the list""" - if self._curr_element == None: - self.tree = netlistElement(name) - self._curr_element = self.tree - else: - self._curr_element = self._curr_element.addChild( - netlistElement(name, self._curr_element)) - - # If this element is a component, add it to the components list - if self._curr_element.name == "comp": - self.components.append(component(self._curr_element)) - - # Assign the design element - if self._curr_element.name == "design": - self.design = self._curr_element - - # If this element is a library part, add it to the parts list - if self._curr_element.name == "libpart": - self.libparts.append(part(self._curr_element)) - - # If this element is a net, add it to the nets list - if self._curr_element.name == "net": - self.nets.append(self._curr_element) - - # If this element is a library, add it to the libraries list - if self._curr_element.name == "library": - self.libraries.append(self._curr_element) - - return self._curr_element - - def endDocument(self): - """Called when the netlist document has been fully parsed""" - # When the document is complete, the library parts must be linked to - # the components as they are seperate in the tree so as not to - # duplicate library part information for every component - for c in self.components: - for p in self.libparts: - if p.getPart() == c.getPart() and p.getLib() == c.getLib(): - c.setPart(p) - - def endElement(self): - """End the current element and switch to its parent""" - self._curr_element = self._curr_element.getParent() - - def getDate(self): - """Return the date + time string generated by the tree creation tool""" - return self.design.get("date") - - def getSource(self): - """Return the source string for the design""" - return self.design.get("source") - - def getTool(self): - """Return the tool string which was used to create the netlist tree""" - return self.design.get("tool") - - def groupComponents(self): - """Return a list of component lists. Components are grouped together - when the value, library and part identifiers match - - """ - groups = [] - - # Make sure to start off will all components ungrouped to begin with - for c in self.components: - c.grouped = False - - # Group components based on the value, library and part identifiers - for c in self.components: - if c.grouped == False: - c.grouped = True - newgroup = [] - newgroup.append(c) - - # Check every other ungrouped component against this component - # and add to the group as necessary - for ci in self.components: - if ci.grouped == False and ci == c: - newgroup.append(ci) - ci.grouped = True - - # Add the new component group to the groups list - groups.append(newgroup) - - # Each group is a list of components, we need to sort each list first - # to get them in order as this makes for easier to read BOM's - for g in groups: - g = sorted(g, key=lambda g: g.getRef()) - - # Finally, sort the groups to order the references alphabetically - groups = sorted(groups, key=lambda group: group[0].getRef()) - - return groups - - def formatXML(self): - """Return the whole netlist formatted in XML""" - return self.tree.formatXML() - - def formatHTML(self): - """Return the whole netlist formatted in HTML""" - return self.tree.formatHTML() - - def load(self, fname): - """Load a kicad generic netlist - - Keywords: - fname -- The name of the generic netlist file to open - - """ - try: - self._reader = sax.make_parser() - self._reader.setContentHandler(_gNetReader(self)) - self._reader.parse(fname) - except IOError as e: - print >> sys.stderr, __file__, ":", e - sys.exit(-1) - - -class part(): - """Class for a library part""" - def __init__(self, part): - # The part is a reference to a libpart generic netlist element - self.element = part - - def __str__(self): - # simply print the generic netlist element associated with this part - return str(self.element) - - def getDatasheet(self): - return self.element.get("docs") - - def getLib(self): - return self.element.get("libpart", "lib") - - def getPart(self): - return self.element.get("libpart", "part") - - def getDescription(self): - return self.element.get("description") - - def getField(self, name): - return self.element.get("field", "name", name) - - -class _gNetReader(sax.handler.ContentHandler): - """SAX kicad generic netlist content handler - passes most of the work back - to the gNetlist class which builds a complete tree in RAM for the design - - """ - def __init__(self, aParent): - self.parent = aParent - - def startElement(self, name, attrs): - """Start of a new XML element event""" - element = self.parent.addElement(name) - - for name in attrs.getNames(): - element.addAttribute(name, attrs.getValue(name)) - - def endElement(self, name): - self.parent.endElement() - - def characters(self, content): - # Ignore erroneous white space - ignoreableWhitespace does not get rid - # of the need for this! - if not content.isspace(): - self.parent.addChars(content) - - def endDocument(self): - """End of the XML document event""" - self.parent.endDocument() diff --git a/scripts/bom-in-python/round_robin.py b/scripts/bom-in-python/round_robin.py index 6aff7ef1a9..245f7ad16d 100644 --- a/scripts/bom-in-python/round_robin.py +++ b/scripts/bom-in-python/round_robin.py @@ -4,20 +4,24 @@ # Example: Round robin, XML to XML conversion # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import sys +import pdb + # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print( __file__, ":", e, file=sys.stderr) f = stdout -print >> f, net.formatXML() +print(net.formatXML(), file=f) diff --git a/scripts/bom-in-python/round_value_robin.py b/scripts/bom-in-python/round_value_robin.py index c7834420a7..536f5a1239 100644 --- a/scripts/bom-in-python/round_value_robin.py +++ b/scripts/bom-in-python/round_value_robin.py @@ -4,8 +4,10 @@ # Example: Round value robin, XML to XML conversion with partial value monging # +from __future__ import print_function + # Import the KiCad python helper module and the csv formatter -import ky_generic_netlist_reader +import kicad_netlist_reader import sys def checkvalue(self): @@ -51,21 +53,21 @@ def checkvalue(self): # Give components a new method for checking the values (this could easily be a # Company Part Number generator method instead) -ky_generic_netlist_reader.component.checkvalue = checkvalue +kicad_netlist_reader.comp.checkvalue = checkvalue # Generate an instance of a generic netlist, and load the netlist tree from # the command line option. If the file doesn't exist, execution will stop -net = ky_generic_netlist_reader.netlist(sys.argv[1]) +net = kicad_netlist_reader.netlist(sys.argv[1]) # Open a file to write to, if the file cannot be opened output to stdout # instead try: f = open(sys.argv[2], 'w') except IOError: - print >> sys.stderr, __file__, ":", e + print(__file__, ":", e, file=sys.stderr) f = stdout for c in net.components: c.checkvalue() -print >> f, net.formatXML() +print(net.formatXML(), file=f) From 0bc1c08d4f12a99cef2a9db3cb6f9a477c0fd2dd Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 1 Sep 2013 12:52:46 -0500 Subject: [PATCH 09/29] Add and to generic netlist XML format, required by new bom_csv_grouped_by_value.py support. --- eeschema/netform.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp index fbb16a245b..4cc33547c8 100644 --- a/eeschema/netform.cpp +++ b/eeschema/netform.cpp @@ -714,6 +714,8 @@ XNODE* NETLIST_EXPORT_TOOL::makeGenericLibParts() wxString sLibpart = wxT( "libpart" ); wxString sLib = wxT( "lib" ); wxString sPart = wxT( "part" ); + wxString sAliases = wxT( "aliases" ); + wxString sAlias = wxT( "alias" ); wxString sPins = wxT( "pins" ); // key for library component pins list wxString sPin = wxT( "pin" ); // key for one library component pin descr wxString sPinNum = wxT( "num" ); // key for one library component pin num @@ -744,6 +746,20 @@ XNODE* NETLIST_EXPORT_TOOL::makeGenericLibParts() xlibpart->AddAttribute( sLib, library->GetLogicalName() ); xlibpart->AddAttribute( sPart, lcomp->GetName() ); + if( lcomp->GetAliasCount() ) + { + wxArrayString aliases = lcomp->GetAliasNames( false ); + if( aliases.GetCount() ) + { + XNODE* xaliases = node( sAliases ); + xlibpart->AddChild( xaliases ); + for( unsigned i=0; iAddChild( node( sAlias, aliases[i] ) ); + } + } + } + //----- show the important properties ------------------------- if( !lcomp->GetAlias( 0 )->GetDescription().IsEmpty() ) xlibpart->AddChild( node( sDescr, lcomp->GetAlias( 0 )->GetDescription() ) ); From f99ca774610b256cda6de76804acaed1488c4813 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 1 Sep 2013 12:59:28 -0500 Subject: [PATCH 10/29] Use via layers which are determined in only one place, this is a cheap trick to support blind vias in the export. --- pcbnew/specctra.h | 4 ++ pcbnew/specctra_export.cpp | 93 +++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/pcbnew/specctra.h b/pcbnew/specctra.h index 819e5628cd..d160019cd2 100644 --- a/pcbnew/specctra.h +++ b/pcbnew/specctra.h @@ -3595,6 +3595,10 @@ class SPECCTRA_DB : public SPECCTRA_LEXER /// we don't want ownership here permanently, so we don't use boost::ptr_vector std::vector nets; + /// specctra cu layers, 0 based index: + int m_top_via_layer; + int m_bot_via_layer; + /** * Function buildLayerMaps diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index 65df8c00f8..57f063cd8d 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -150,6 +150,8 @@ void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event ) try { + + GetBoard()->SynchronizeNetsAndNetClasses(); db.FromBOARD( GetBoard() ); db.ExportPCB( fullFileName, true ); @@ -591,8 +593,6 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) polygon->AppendPoint( lowerRight ); } - D( printf( "m_DeltaSize: %d,%d\n", aPad->GetDelta().x, aPad->GetDelta().y ); ) - // this string _must_ be unique for a given physical shape snprintf( name, sizeof(name), "Trapz%sPad_%.6gx%.6g_%c%.6gx%c%.6g_um", uniqifier.c_str(), IU2um( aPad->GetSize().x ), IU2um( aPad->GetSize().y ), @@ -1727,13 +1727,32 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) { NETCLASSES& nclasses = aBoard->m_NetClasses; + // Assume the netclass vias are all the same kind of thru, blind, or buried vias. + // This is in lieu of either having each netclass via have its own layer pair in + // the netclass dialog, or such control in the specctra export dialog. + + + // if( aBoard->GetDesignSettings().m_CurrentViaType == VIA_THROUGH ) + { + m_top_via_layer = 0; // first specctra cu layer is number zero. + m_bot_via_layer = aBoard->GetCopperLayerCount()-1; + } + /* + else + { + // again, should be in the BOARD: + topLayer = kicadLayer2pcb[ GetScreen()->m_Route_Layer_TOP ]; + botLayer = kicadLayer2pcb[ GetScreen()->m_Route_Layer_BOTTOM ]; + } + */ + // Add the via from the Default netclass first. The via container // in pcb->library preserves the sequence of addition. NETCLASS* netclass = nclasses.GetDefault(); PADSTACK* via = makeVia( netclass->GetViaDiameter(), netclass->GetViaDrill(), - FIRST_LAYER, aBoard->GetCopperLayerCount()-1 ); + m_top_via_layer, m_bot_via_layer ); // we AppendVia() this first one, there is no way it can be a duplicate, // the pcb->library via container is empty at this point. After this, @@ -1742,10 +1761,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) pcb->library->AppendVia( via ); #if 0 - // Stock vias have drill diameter of zero, this is not sensible to freerouter + // I've seen no way to make stock vias useable by freerouter. Also the + // zero based diameter was leading to duplicates in the LookupVia() function. // User should use netclass based vias when going to freerouter. - // output the stock vias, but preserve uniqueness in the via container by + // Output the stock vias, but preserve uniqueness in the via container by // using LookupVia(). for( unsigned i = 0; i < aBoard->m_ViasDimensionsList.size(); ++i ) { @@ -1753,7 +1773,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) int viaDrill = aBoard->m_ViasDimensionsList[i].m_Drill; via = makeVia( viaSize, viaDrill, - FIRST_LAYER, aBoard->GetCopperLayerCount()-1 ); + m_top_via_layer, m_bot_via_layer ); // maybe add 'via' to the library, but only if unique. PADSTACK* registered = pcb->library->LookupVia( via ); @@ -1772,7 +1792,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) netclass = nc->second; via = makeVia( netclass->GetViaDiameter(), netclass->GetViaDrill(), - FIRST_LAYER, aBoard->GetCopperLayerCount()-1 ); + m_top_via_layer, m_bot_via_layer ); // maybe add 'via' to the library, but only if unique. PADSTACK* registered = pcb->library->LookupVia( via ); @@ -1854,8 +1874,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) //---------------------- { - // export all of them for now, later we'll decide what controls we need - // on this. + // Export all vias, once per unique size and drill diameter combo. static const KICAD_T scanVIAs[] = { PCB_VIA_T, EOT }; items.Collect( aBoard, scanVIAs ); @@ -1930,33 +1949,33 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard ) { -/* From page 11 of specctra spec: - * - * Routing and Placement Rule Hierarchies - * - * Routing and placement rules can be defined at multiple levels of design - * specification. When a routing or placement rule is defined for an object at - * multiple levels, a predefined routing or placement precedence order - * automatically determines which rule to apply to the object. The routing rule - * precedence order is - * - * pcb < layer < class < class layer < group_set < group_set layer < net < - * net layer < group < group layer < fromto < fromto layer < class_class < - * class_class layer < padstack < region < class region < net region < - * class_class region - * - * A pcb rule (global rule for the PCB design) has the lowest precedence in the - * hierarchy. A class-to-class region rule has the highest precedence. Rules - * set at one level of the hierarchy override conflicting rules set at lower - * levels. The placement rule precedence order is - * - * pcb < image_set < image < component < super cluster < room < - * room_image_set < family_family < image_image - * - * A pcb rule (global rule for the PCB design) has the lowest precedence in the - * hierarchy. An image-to-image rule has the highest precedence. Rules set at - * one level of the hierarchy override conflicting rules set at lower levels. - */ + /* From page 11 of specctra spec: + * + * Routing and Placement Rule Hierarchies + * + * Routing and placement rules can be defined at multiple levels of design + * specification. When a routing or placement rule is defined for an object at + * multiple levels, a predefined routing or placement precedence order + * automatically determines which rule to apply to the object. The routing rule + * precedence order is + * + * pcb < layer < class < class layer < group_set < group_set layer < net < + * net layer < group < group layer < fromto < fromto layer < class_class < + * class_class layer < padstack < region < class region < net region < + * class_class region + * + * A pcb rule (global rule for the PCB design) has the lowest precedence in the + * hierarchy. A class-to-class region rule has the highest precedence. Rules + * set at one level of the hierarchy override conflicting rules set at lower + * levels. The placement rule precedence order is + * + * pcb < image_set < image < component < super cluster < room < + * room_image_set < family_family < image_image + * + * A pcb rule (global rule for the PCB design) has the lowest precedence in the + * hierarchy. An image-to-image rule has the highest precedence. Rules set at + * one level of the hierarchy override conflicting rules set at lower levels. + */ char text[256]; @@ -1995,7 +2014,7 @@ void SPECCTRA_DB::exportNETCLASS( NETCLASS* aNetClass, BOARD* aBoard ) // this should never become a performance issue. PADSTACK* via = makeVia( aNetClass->GetViaDiameter(), aNetClass->GetViaDrill(), - FIRST_LAYER, aBoard->GetCopperLayerCount()-1 ); + m_top_via_layer, m_bot_via_layer ); snprintf( text, sizeof(text), "(use_via %s)", via->GetPadstackId().c_str() ); clazz->circuit.push_back( text ); From 9eeb56fe3e2c5a97721dd5c0802eedf390ca031c Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 2 Sep 2013 11:06:17 +0200 Subject: [PATCH 11/29] minor changes and refinement in class pcb layer box --- common/class_layer_box_selector.cpp | 12 +++++------ include/class_layer_box_selector.h | 2 +- pcbnew/class_pcb_layer_box_selector.cpp | 28 ++++++++++++++++++------- pcbnew/class_pcb_layer_box_selector.h | 5 +++-- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/common/class_layer_box_selector.cpp b/common/class_layer_box_selector.cpp index c5eb0b237a..a4676e91cf 100644 --- a/common/class_layer_box_selector.cpp +++ b/common/class_layer_box_selector.cpp @@ -50,15 +50,13 @@ void LAYER_SELECTOR::SetBitmapLayer( wxBitmap& aLayerbmp, LAYER_NUM aLayer ) bmpDC.DrawRectangle( 0, 0, aLayerbmp.GetWidth(), aLayerbmp.GetHeight() ); } -/* class to display a layer list. - * +/* class to display a layer list in a wxBitmapComboBox. */ - LAYER_BOX_SELECTOR::LAYER_BOX_SELECTOR( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, int n, const wxString choices[] ) : - LAYER_SELECTOR(), - wxBitmapComboBox( parent, id, wxEmptyString, pos, size, n, choices, wxCB_READONLY ) + wxBitmapComboBox( parent, id, wxEmptyString, pos, size, n, choices, wxCB_READONLY ), + LAYER_SELECTOR() { if( choices != NULL ) ResyncBitmapOnly(); @@ -68,8 +66,8 @@ LAYER_BOX_SELECTOR::LAYER_BOX_SELECTOR( wxWindow* parent, wxWindowID id, LAYER_BOX_SELECTOR::LAYER_BOX_SELECTOR( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, const wxArrayString& choices ) : - LAYER_SELECTOR(), - wxBitmapComboBox( parent, id, wxEmptyString, pos, size, choices, wxCB_READONLY ) + wxBitmapComboBox( parent, id, wxEmptyString, pos, size, choices, wxCB_READONLY ), + LAYER_SELECTOR() { if( !choices.IsEmpty() ) ResyncBitmapOnly(); diff --git a/include/class_layer_box_selector.h b/include/class_layer_box_selector.h index 4f6cf5d04e..27d19b8a18 100644 --- a/include/class_layer_box_selector.h +++ b/include/class_layer_box_selector.h @@ -46,7 +46,7 @@ protected: /* class to display a layer list in a wxBitmapComboBox. */ -class LAYER_BOX_SELECTOR : public LAYER_SELECTOR, public wxBitmapComboBox +class LAYER_BOX_SELECTOR :public wxBitmapComboBox, public LAYER_SELECTOR { public: // Hotkey Info diff --git a/pcbnew/class_pcb_layer_box_selector.cpp b/pcbnew/class_pcb_layer_box_selector.cpp index 807e8b0f78..30a3f56938 100644 --- a/pcbnew/class_pcb_layer_box_selector.cpp +++ b/pcbnew/class_pcb_layer_box_selector.cpp @@ -40,10 +40,7 @@ #include -/* class to display a layer list. - * - */ - +// class to display a layer list in a wxBitmapComboBox. // Reload the Layers void PCB_LAYER_BOX_SELECTOR::Resync() @@ -53,9 +50,16 @@ void PCB_LAYER_BOX_SELECTOR::Resync() static DECLARE_LAYERS_ORDER_LIST( layertranscode ); static DECLARE_LAYERS_HOTKEY( layerhk ); + // Tray to fix a minimum width fot the BitmapComboBox + int minwidth, h; + wxClientDC dc( GetParent() ); // The DC for "this" is not always initialized + wxString dummyText( wxT("XXXXXXXXXXXX") ); + dc.GetTextExtent ( dummyText, &minwidth, &h ); + + #define BM_SIZE 14 for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i ) { - wxBitmap layerbmp( 14, 14 ); + wxBitmap layerbmp( BM_SIZE, BM_SIZE ); wxString layername; LAYER_NUM layerid = i; @@ -73,10 +77,20 @@ void PCB_LAYER_BOX_SELECTOR::Resync() layername = GetLayerName( layerid ); if( m_layerhotkeys && m_hotkeys != NULL ) - layername = AddHotkeyName( layername, m_hotkeys, layerhk[layerid], IS_COMMENT ); + layername = AddHotkeyName( layername, m_hotkeys, + layerhk[layerid], IS_COMMENT ); Append( layername, layerbmp, (void*)(intptr_t) layerid ); - } + int w; + dc.GetTextExtent ( layername, &w, &h ); + + minwidth = std::max( minwidth, w ); + } + + minwidth += BM_SIZE + 12; // Take in account the bitmap size and margins +wxLogMessage( "minw %d min %d", minwidth, GetMinClientSize().x ); +// SetMinClientSize( wxSize( minwidth, -1 ) ); + Layout(); } diff --git a/pcbnew/class_pcb_layer_box_selector.h b/pcbnew/class_pcb_layer_box_selector.h index 0a63b65032..5ac87e5da4 100644 --- a/pcbnew/class_pcb_layer_box_selector.h +++ b/pcbnew/class_pcb_layer_box_selector.h @@ -19,9 +19,9 @@ public: public: // If you are thinking the constructor is a bit curious, - // just remember it is used by automaticallty generated by wxFormBuilder files, + // just remember it is used by automaticallty generated by wxFormBuilder files, // and it should mimic the wxBitmapComboBox constructor. - // Therefore, value, pos, size, n, choices and style are not yet used, + // Therefore, value, style are not yet used, // but they are here for compatibility PCB_LAYER_BOX_SELECTOR( wxWindow* parent, wxWindowID id, const wxString& value = wxEmptyString, @@ -49,6 +49,7 @@ public: // Virtual function void Resync(); +private: // Returns a color index from the layer id // Virtual function EDA_COLOR_T GetLayerColor( LAYER_NUM aLayer ) const; From 7bc9003fb8d5e2a87488d8b8da02ad3d3187e250 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 2 Sep 2013 17:26:52 +0200 Subject: [PATCH 12/29] pcb layer box selector: ajust size when modifying the layer names, to show the full name. --- include/wxPcbStruct.h | 10 +++++++++- pcbnew/class_pcb_layer_box_selector.cpp | 13 ++++--------- pcbnew/class_pcb_layer_widget.cpp | 2 +- pcbnew/dialogs/dialog_layers_setup.cpp | 2 +- pcbnew/files.cpp | 5 ++--- pcbnew/pcbframe.cpp | 2 +- pcbnew/pcbnew.cpp | 2 +- pcbnew/tool_pcb.cpp | 17 +++++++++++------ 8 files changed, 30 insertions(+), 23 deletions(-) diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 5fb8256601..7df4dfb73e 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -542,7 +542,15 @@ public: void ReCreateMicrowaveVToolbar(); void ReCreateOptToolbar(); void ReCreateMenuBar(); - PCB_LAYER_BOX_SELECTOR* ReCreateLayerBox( wxAuiToolBar* parent ); + + /** + * Re create the layer Box by clearing the old list, and building + * le new one, from the new layers names and cole layers + * @param aForceResizeToolbar = true to resize the parent toolbar + * false if not needed (mainly in parent toolbar creation, + * or when the layers names are not modified) + */ + void ReCreateLayerBox( bool aForceResizeToolbar = true ); /** * Function OnModify diff --git a/pcbnew/class_pcb_layer_box_selector.cpp b/pcbnew/class_pcb_layer_box_selector.cpp index 30a3f56938..4e4bc1f96d 100644 --- a/pcbnew/class_pcb_layer_box_selector.cpp +++ b/pcbnew/class_pcb_layer_box_selector.cpp @@ -51,10 +51,8 @@ void PCB_LAYER_BOX_SELECTOR::Resync() static DECLARE_LAYERS_HOTKEY( layerhk ); // Tray to fix a minimum width fot the BitmapComboBox - int minwidth, h; + int minwidth = 80, h; wxClientDC dc( GetParent() ); // The DC for "this" is not always initialized - wxString dummyText( wxT("XXXXXXXXXXXX") ); - dc.GetTextExtent ( dummyText, &minwidth, &h ); #define BM_SIZE 14 for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i ) @@ -83,14 +81,11 @@ void PCB_LAYER_BOX_SELECTOR::Resync() Append( layername, layerbmp, (void*)(intptr_t) layerid ); int w; dc.GetTextExtent ( layername, &w, &h ); - minwidth = std::max( minwidth, w ); - } + } - minwidth += BM_SIZE + 12; // Take in account the bitmap size and margins -wxLogMessage( "minw %d min %d", minwidth, GetMinClientSize().x ); -// SetMinClientSize( wxSize( minwidth, -1 ) ); - Layout(); + minwidth += BM_SIZE + 35; // Take in account the bitmap size and margins + SetMinClientSize( wxSize( minwidth, -1 ) ); } diff --git a/pcbnew/class_pcb_layer_widget.cpp b/pcbnew/class_pcb_layer_widget.cpp index a4dc99df80..e78f2043ca 100644 --- a/pcbnew/class_pcb_layer_widget.cpp +++ b/pcbnew/class_pcb_layer_widget.cpp @@ -341,7 +341,7 @@ void PCB_LAYER_WIDGET::ReFill() void PCB_LAYER_WIDGET::OnLayerColorChange( LAYER_NUM aLayer, EDA_COLOR_T aColor ) { myframe->GetBoard()->SetLayerColor( aLayer, aColor ); - myframe->ReCreateLayerBox( NULL ); + myframe->ReCreateLayerBox( false ); myframe->GetCanvas()->Refresh(); } diff --git a/pcbnew/dialogs/dialog_layers_setup.cpp b/pcbnew/dialogs/dialog_layers_setup.cpp index d06f501394..aded0cf5df 100644 --- a/pcbnew/dialogs/dialog_layers_setup.cpp +++ b/pcbnew/dialogs/dialog_layers_setup.cpp @@ -560,7 +560,7 @@ void DIALOG_LAYERS_SETUP::OnOkButtonClick( wxCommandEvent& event ) } m_Parent->OnModify(); - m_Parent->ReCreateLayerBox( NULL ); + m_Parent->ReCreateLayerBox(); m_Parent->ReFillLayerWidget(); EndModal( wxID_OK ); diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index bdd507fae0..e728f64d73 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -141,7 +141,7 @@ void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event ) fn.SetExt( PcbFileExtension ); GetBoard()->SetFileName( fn.GetFullPath() ); UpdateTitle(); - ReCreateLayerBox( NULL ); + ReCreateLayerBox(); } break; @@ -396,8 +396,7 @@ bool PCB_EDIT_FRAME::LoadOnePcbFile( const wxString& aFileName, bool aAppend, // Update info shown by the horizontal toolbars GetBoard()->SetCurrentNetClass( NETCLASS::Default ); ReFillLayerWidget(); - - ReCreateLayerBox( NULL ); + ReCreateLayerBox(); // upate the layer widget to match board visibility states, both layers and render columns. syncLayerVisibilities(); diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 0c8e065a21..e45b22075b 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -589,7 +589,7 @@ void PCB_EDIT_FRAME::ShowDesignRulesEditor( wxCommandEvent& event ) if( returncode == wxID_OK ) // New rules, or others changes. { - ReCreateLayerBox( NULL ); + ReCreateLayerBox(); updateTraceWidthSelectBox(); updateViaSizeSelectBox(); OnModify(); diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 061f465d4a..aa8887a2f1 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -301,7 +301,7 @@ bool EDA_APP::OnInit() frame->Clear_Pcb( false ); // update the layer names in the listbox - frame->ReCreateLayerBox( NULL ); + frame->ReCreateLayerBox( false ); /* For an obscure reason the focus is lost after loading a board file * when starting (i.e. only at this point) diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index 4a5e3310dc..d57011f534 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -281,7 +281,7 @@ void PCB_EDIT_FRAME::ReCreateHToolbar() m_SelLayerBox = new PCB_LAYER_BOX_SELECTOR( m_mainToolBar, ID_TOOLBARH_PCB_SELECT_LAYER ); m_SelLayerBox->SetBoardFrame( this ); } - ReCreateLayerBox( m_mainToolBar ); + ReCreateLayerBox( false ); m_mainToolBar->AddControl( m_SelLayerBox ); PrepareLayerIndicator(); // Initialize the bitmap with current @@ -663,14 +663,19 @@ void PCB_EDIT_FRAME::updateViaSizeSelectBox() } -PCB_LAYER_BOX_SELECTOR* PCB_EDIT_FRAME::ReCreateLayerBox( wxAuiToolBar* parent ) +void PCB_EDIT_FRAME::ReCreateLayerBox( bool aForceResizeToolbar ) { - if( m_SelLayerBox == NULL ) - return NULL; + if( m_SelLayerBox == NULL || m_mainToolBar == NULL ) + return; + m_SelLayerBox->SetToolTip( _( "+/- to switch" ) ); m_SelLayerBox->m_hotkeys = g_Board_Editor_Hokeys_Descr; m_SelLayerBox->Resync(); - m_SelLayerBox->SetToolTip( _( "+/- to switch" ) ); - return m_SelLayerBox; + if( aForceResizeToolbar ) + { + // the layer box can have its size changed + // Update the aui manager, to take in account the new size + m_auimgr.Update(); + } } From 1d74450216590bc81f09c6faa208470b01bccf20 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Tue, 3 Sep 2013 14:48:38 +0200 Subject: [PATCH 13/29] Pcbnew: use pcb layer box selector in dialog graphic item properties and pcb text properties. --- common/class_layer_box_selector.cpp | 3 ++ .../dialogs/dialog_dimension_editor_base.fbp | 4 +- pcbnew/dialogs/dialog_dimension_editor_base.h | 4 +- .../dialog_graphic_item_properties.cpp | 28 ++++++------- .../dialog_graphic_item_properties_base.cpp | 19 +++++---- .../dialog_graphic_item_properties_base.fbp | 17 ++++---- .../dialog_graphic_item_properties_base.h | 9 ++-- ...og_graphic_item_properties_for_Modedit.cpp | 41 ++++++------------- pcbnew/dialogs/dialog_pcb_text_properties.cpp | 25 ++++------- .../dialog_pcb_text_properties_base.cpp | 21 ++++++---- .../dialog_pcb_text_properties_base.fbp | 21 ++++++---- .../dialogs/dialog_pcb_text_properties_base.h | 10 +++-- 12 files changed, 101 insertions(+), 101 deletions(-) diff --git a/common/class_layer_box_selector.cpp b/common/class_layer_box_selector.cpp index a4676e91cf..401f8d3bb9 100644 --- a/common/class_layer_box_selector.cpp +++ b/common/class_layer_box_selector.cpp @@ -84,6 +84,9 @@ int LAYER_BOX_SELECTOR::GetChoice() // Get Current Layer LAYER_NUM LAYER_BOX_SELECTOR::GetLayerSelection() const { + if( GetSelection() < 0 ) + return UNDEFINED_LAYER; + return (LAYER_NUM)(intptr_t) GetClientData( GetSelection() ); } diff --git a/pcbnew/dialogs/dialog_dimension_editor_base.fbp b/pcbnew/dialogs/dialog_dimension_editor_base.fbp index c841d8509c..4373b4f5cf 100644 --- a/pcbnew/dialogs/dialog_dimension_editor_base.fbp +++ b/pcbnew/dialogs/dialog_dimension_editor_base.fbp @@ -42,7 +42,7 @@ DIALOG_DIMENSION_EDITOR_BASE - 378,328 + 417,328 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Dimension Properties @@ -1341,7 +1341,7 @@ 5 wxBOTTOM|wxRIGHT|wxLEFT 0 - + 1 1 1 diff --git a/pcbnew/dialogs/dialog_dimension_editor_base.h b/pcbnew/dialogs/dialog_dimension_editor_base.h index b0c5e063f4..62291b9a22 100644 --- a/pcbnew/dialogs/dialog_dimension_editor_base.h +++ b/pcbnew/dialogs/dialog_dimension_editor_base.h @@ -24,7 +24,7 @@ class PCB_LAYER_BOX_SELECTOR; #include #include #include -#include +#include #include #include #include @@ -67,7 +67,7 @@ class DIALOG_DIMENSION_EDITOR_BASE : public DIALOG_SHIM public: - DIALOG_DIMENSION_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Dimension Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 378,328 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_DIMENSION_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Dimension Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 417,328 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_DIMENSION_EDITOR_BASE(); }; diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index 352736df26..c4271c7b1c 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -24,6 +24,7 @@ #include #include +#include class DIALOG_GRAPHIC_ITEM_PROPERTIES: public DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE { @@ -127,7 +128,7 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) m_EndPointXLabel->SetLabel(_("Start Point X")); m_EndPointYLabel->SetLabel(_("Start Point Y")); - // Here the angle is a double, but the UI is still working + // Here the angle is a double, but the UI is still working // with integers msg << int( m_Item->GetAngle() ); m_Angle_Ctrl->SetValue(msg); @@ -159,20 +160,17 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) PutValueInLocalUnits( *m_DefaultThicknessCtrl, thickness ); - for( LAYER_NUM layer = FIRST_NON_COPPER_LAYER; - layer <= LAST_NON_COPPER_LAYER; ++layer ) + // Configure the layers list selector + m_LayerSelectionCtrl->SetLayersHotkeys( false ); + m_LayerSelectionCtrl->SetLayerMask( ALL_CU_LAYERS ); + m_LayerSelectionCtrl->SetBoardFrame( m_parent ); + m_LayerSelectionCtrl->Resync(); + if( m_LayerSelectionCtrl->SetLayerSelection( m_Item->GetLayer() ) < 0 ) { - m_LayerSelectionCtrl->Append( m_parent->GetBoard()->GetLayerName( layer ) ); + wxMessageBox( _("This item has an illegal layer id.\n" + "Now, forced on the drawings layer. Please, fix it") ); + m_LayerSelectionCtrl->SetLayerSelection( DRAW_N ); } - - LAYER_NUM layer = m_Item->GetLayer(); - - // It has to be an aux layer - if ( layer < FIRST_NON_COPPER_LAYER ) - layer = FIRST_NON_COPPER_LAYER; - if ( layer > LAST_NON_COPPER_LAYER ) - layer = LAST_NON_COPPER_LAYER; - m_LayerSelectionCtrl->SetSelection( layer - FIRST_NON_COPPER_LAYER ); } @@ -182,7 +180,7 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnLayerChoice( wxCommandEvent& event ) { int thickness; - if( (m_LayerSelectionCtrl->GetCurrentSelection() + FIRST_NON_COPPER_LAYER) == EDGE_N ) + if( m_LayerSelectionCtrl->GetLayerSelection() == EDGE_N ) thickness = m_brdSettings.m_EdgeSegmentWidth; else thickness = m_brdSettings.m_DrawSegmentWidth; @@ -221,7 +219,7 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::OnOkClick( wxCommandEvent& event ) msg = m_DefaultThicknessCtrl->GetValue(); int thickness = ReturnValueFromString( g_UserUnit, msg ); - m_Item->SetLayer( FIRST_NON_COPPER_LAYER + m_LayerSelectionCtrl->GetCurrentSelection() ); + m_Item->SetLayer( m_LayerSelectionCtrl->GetLayerSelection() ); if( m_Item->GetLayer() == EDGE_N ) m_brdSettings.m_EdgeSegmentWidth = thickness; diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp b/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp index 492623896a..3aa70b5b7b 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp @@ -1,10 +1,12 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 10 2012) +// C++ code generated with wxFormBuilder (version Oct 8 2012) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// +#include "class_pcb_layer_box_selector.h" + #include "dialog_graphic_item_properties_base.h" /////////////////////////////////////////////////////////////////////////// @@ -30,6 +32,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperLeftGridSizer->Add( m_StartPointXLabel, 0, wxALIGN_RIGHT|wxTOP|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); m_Center_StartXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_Center_StartXCtrl->SetMaxLength( 0 ); fgUpperLeftGridSizer->Add( m_Center_StartXCtrl, 0, wxEXPAND|wxALL, 5 ); m_StartPointXUnit = new wxStaticText( this, wxID_ANY, _("Unit"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -41,6 +44,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperLeftGridSizer->Add( m_StartPointYLabel, 0, wxALIGN_RIGHT|wxTOP|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); m_Center_StartYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_Center_StartYCtrl->SetMaxLength( 0 ); fgUpperLeftGridSizer->Add( m_Center_StartYCtrl, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); m_StartPointYUnit = new wxStaticText( this, wxID_ANY, _("Unit"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -52,6 +56,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperLeftGridSizer->Add( m_EndPointXLabel, 0, wxALIGN_RIGHT|wxTOP|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); m_EndX_Radius_Ctrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_EndX_Radius_Ctrl->SetMaxLength( 0 ); fgUpperLeftGridSizer->Add( m_EndX_Radius_Ctrl, 0, wxEXPAND|wxALL, 5 ); m_EndPointXUnit = new wxStaticText( this, wxID_ANY, _("Unit"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -63,6 +68,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperLeftGridSizer->Add( m_EndPointYLabel, 0, wxALIGN_RIGHT|wxTOP|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); m_EndY_Ctrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_EndY_Ctrl->SetMaxLength( 0 ); fgUpperLeftGridSizer->Add( m_EndY_Ctrl, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); m_EndPointYUnit = new wxStaticText( this, wxID_ANY, _("Unit"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -89,6 +95,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperRightGridSizer->Add( m_Angle_Text, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); m_Angle_Ctrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_Angle_Ctrl->SetMaxLength( 0 ); fgUpperRightGridSizer->Add( m_Angle_Ctrl, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); m_AngleUnit = new wxStaticText( this, wxID_ANY, _("0.1 degree"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -100,6 +107,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperRightGridSizer->Add( m_ThicknessLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); m_ThicknessCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_ThicknessCtrl->SetMaxLength( 0 ); fgUpperRightGridSizer->Add( m_ThicknessCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); m_ThicknessTextUnit = new wxStaticText( this, wxID_ANY, _("Unit"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -111,6 +119,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind fgUpperRightGridSizer->Add( m_DefaultThicknessLabel, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); m_DefaultThicknessCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_DefaultThicknessCtrl->SetMaxLength( 0 ); fgUpperRightGridSizer->Add( m_DefaultThicknessCtrl, 0, wxALL|wxEXPAND, 5 ); m_DefaulThicknessTextUnit = new wxStaticText( this, wxID_ANY, _("Unit"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -130,12 +139,8 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind m_LayerLabel->Wrap( -1 ); fgLowerRightSizer->Add( m_LayerLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - wxArrayString m_LayerSelectionCtrlChoices; - m_LayerSelectionCtrl = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_LayerSelectionCtrlChoices, 0 ); - m_LayerSelectionCtrl->SetSelection( 0 ); - m_LayerSelectionCtrl->SetToolTip( _("Select the layer on which text should lay.") ); - - fgLowerRightSizer->Add( m_LayerSelectionCtrl, 0, wxEXPAND|wxALL, 5 ); + m_LayerSelectionCtrl = new PCB_LAYER_BOX_SELECTOR( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + fgLowerRightSizer->Add( m_LayerSelectionCtrl, 0, wxALL, 5 ); bUpperRightSizer->Add( fgLowerRightSizer, 1, wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp b/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp index dd711328ef..b538865a4a 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp +++ b/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp @@ -2124,11 +2124,11 @@ - + 5 - wxEXPAND|wxALL + wxALL 0 - + 1 1 1 @@ -2172,22 +2172,23 @@ 1 Resizable - 0 + -1 1 - + PCB_LAYER_BOX_SELECTOR; class_pcb_layer_box_selector.h 0 - Select the layer on which text should lay. + wxFILTER_NONE wxDefaultValidator + - + @@ -2209,6 +2210,8 @@ + + diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_base.h b/pcbnew/dialogs/dialog_graphic_item_properties_base.h index 07961a4611..bb78ca4782 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_base.h +++ b/pcbnew/dialogs/dialog_graphic_item_properties_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 10 2012) +// C++ code generated with wxFormBuilder (version Oct 8 2012) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -11,6 +11,9 @@ #include #include #include +class DIALOG_SHIM; +class PCB_LAYER_BOX_SELECTOR; + #include "dialog_shim.h" #include #include @@ -21,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -59,7 +62,7 @@ class DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE : public DIALOG_SHIM wxTextCtrl* m_DefaultThicknessCtrl; wxStaticText* m_DefaulThicknessTextUnit; wxStaticText* m_LayerLabel; - wxChoice* m_LayerSelectionCtrl; + PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl; wxStaticLine* m_staticline1; wxStdDialogButtonSizer* m_StandardButtonsSizer; wxButton* m_StandardButtonsSizerOK; diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_for_Modedit.cpp b/pcbnew/dialogs/dialog_graphic_item_properties_for_Modedit.cpp index 3618570380..9c4fdd2dfe 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_for_Modedit.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties_for_Modedit.cpp @@ -24,6 +24,7 @@ #include #include +#include class DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES: public DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE { @@ -32,7 +33,6 @@ private: EDGE_MODULE* m_item; BOARD_DESIGN_SETTINGS m_brdSettings; MODULE * m_module; - std::vector m_layerId; // the layer Id with the same order as m_LayerSelectionCtrl widget public: DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES( FOOTPRINT_EDIT_FRAME* aParent, @@ -129,7 +129,7 @@ void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::initDlg() m_EndPointXLabel->SetLabel(_("Start Point X")); m_EndPointYLabel->SetLabel(_("Start Point Y")); - // Here the angle is a double, but the UI is still working + // Here the angle is a double, but the UI is still working // with integers msg << int( m_item->GetAngle() ); m_Angle_Ctrl->SetValue(msg); @@ -154,27 +154,16 @@ void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::initDlg() PutValueInLocalUnits( *m_DefaultThicknessCtrl, m_brdSettings.m_ModuleSegmentWidth ); - m_LayerSelectionCtrl->Append( m_parent->GetBoard()->GetLayerName( LAYER_N_BACK ) ); - m_layerId.push_back( LAYER_N_BACK ); - m_LayerSelectionCtrl->Append( m_parent->GetBoard()->GetLayerName( LAYER_N_FRONT ) ); - m_layerId.push_back( LAYER_N_FRONT ); - for( LAYER_NUM layer = FIRST_NON_COPPER_LAYER; layer <= LAST_NON_COPPER_LAYER; ++layer ) + // Configure the layers list selector + m_LayerSelectionCtrl->SetLayersHotkeys( false ); + m_LayerSelectionCtrl->SetLayerMask( INTERNAL_CU_LAYERS|EDGE_LAYER ); + m_LayerSelectionCtrl->SetBoardFrame( m_parent ); + m_LayerSelectionCtrl->Resync(); + if( m_LayerSelectionCtrl->SetLayerSelection( m_item->GetLayer() ) < 0 ) { - if( layer == EDGE_N ) - // Do not use pcb edge layer for footprints, this is a special layer - // So skip it in list - continue; - m_LayerSelectionCtrl->Append( m_parent->GetBoard()->GetLayerName( layer ) ); - m_layerId.push_back( layer ); - } - - for( unsigned ii = 0; ii < m_layerId.size(); ii++ ) - { - if( m_layerId[ii] == m_item->GetLayer() ) - { - m_LayerSelectionCtrl->SetSelection( ii ); - break; - } + wxMessageBox( _("This item has an illegal layer id.\n" + "Now, forced on the front silk screen layer. Please, fix it") ); + m_LayerSelectionCtrl->SetLayerSelection( SILKSCREEN_N_FRONT ); } } @@ -191,14 +180,8 @@ void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::OnOkClick( wxCommandEvent& event ) /* Copy values in text control to the item parameters */ { - int idx = m_LayerSelectionCtrl->GetCurrentSelection(); - if( idx < 0 ) - { - wxMessageBox( _("No valid layer selected for this item. Please, select a layer") ); - return; - } + LAYER_NUM layer = m_LayerSelectionCtrl->GetLayerSelection(); - LAYER_NUM layer = m_layerId[idx]; if( IsCopperLayer( layer ) ) { /* an edge is put on a copper layer: this it is very dangerous. a diff --git a/pcbnew/dialogs/dialog_pcb_text_properties.cpp b/pcbnew/dialogs/dialog_pcb_text_properties.cpp index 7a78102c41..ceaf62f5cc 100644 --- a/pcbnew/dialogs/dialog_pcb_text_properties.cpp +++ b/pcbnew/dialogs/dialog_pcb_text_properties.cpp @@ -41,6 +41,7 @@ #include #include #include +#include class PCB_EDIT_FRAME; @@ -56,7 +57,6 @@ private: PCB_EDIT_FRAME* m_Parent; wxDC* m_DC; TEXTE_PCB* m_SelectedPCBText; - std::vector layerList; void MyInit(); @@ -126,20 +126,13 @@ void DIALOG_PCB_TEXT_PROPERTIES::MyInit() PutValueInLocalUnits( *m_PositionXCtrl, m_SelectedPCBText->GetTextPosition().x ); PutValueInLocalUnits( *m_PositionYCtrl, m_SelectedPCBText->GetTextPosition().y ); - LAYER_MSK enabledLayers = m_Parent->GetBoard()->GetEnabledLayers(); - - for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer ) - { - if( enabledLayers & GetLayerMask( layer ) ) - { - layerList.push_back( layer ); - int itemIndex = - m_LayerSelectionCtrl->Append( m_Parent->GetBoard()->GetLayerName( layer ) ); - - if( m_SelectedPCBText->GetLayer() == layer ) - m_LayerSelectionCtrl->SetSelection( itemIndex ); - } - } + // Configure the layers list selector + m_LayerSelectionCtrl->SetLayersHotkeys( false ); + // A text has no sense on edge cut layer + m_LayerSelectionCtrl->SetLayerMask( EDGE_LAYER ); + m_LayerSelectionCtrl->SetBoardFrame( m_Parent ); + m_LayerSelectionCtrl->Resync(); + m_LayerSelectionCtrl->SetLayerSelection( m_SelectedPCBText->GetLayer() ); wxString orientationStr; orientationStr << m_SelectedPCBText->GetOrientation(); @@ -245,7 +238,7 @@ void DIALOG_PCB_TEXT_PROPERTIES::OnOkClick( wxCommandEvent& event ) } // Set the layer on which the PCB text is laying - m_SelectedPCBText->SetLayer( layerList[m_LayerSelectionCtrl->GetSelection()] ); + m_SelectedPCBText->SetLayer( m_LayerSelectionCtrl->GetLayerSelection() ); // Set whether the PCB text is mirrored (faced down from layer face perspective) m_SelectedPCBText->SetMirrored( m_DisplayCtrl->GetSelection() == 1 ); diff --git a/pcbnew/dialogs/dialog_pcb_text_properties_base.cpp b/pcbnew/dialogs/dialog_pcb_text_properties_base.cpp index c68284866e..d04c149bcf 100644 --- a/pcbnew/dialogs/dialog_pcb_text_properties_base.cpp +++ b/pcbnew/dialogs/dialog_pcb_text_properties_base.cpp @@ -1,10 +1,12 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 11 2012) +// C++ code generated with wxFormBuilder (version Oct 8 2012) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// +#include "class_pcb_layer_box_selector.h" + #include "dialog_pcb_text_properties_base.h" /////////////////////////////////////////////////////////////////////////// @@ -24,13 +26,14 @@ DIALOG_PCB_TEXT_PROPERTIES_BASE::DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* pare bSizer9->Add( m_TextLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_TextContentCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE ); + m_TextContentCtrl->SetMaxLength( 0 ); m_TextContentCtrl->SetToolTip( _("Enter the text placed on selected layer.") ); m_TextContentCtrl->SetMinSize( wxSize( 400,60 ) ); bSizer9->Add( m_TextContentCtrl, 1, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); wxFlexGridSizer* fgSizer1; - fgSizer1 = new wxFlexGridSizer( 6, 4, 0, 0 ); + fgSizer1 = new wxFlexGridSizer( 0, 4, 0, 0 ); fgSizer1->AddGrowableCol( 0 ); fgSizer1->AddGrowableCol( 1 ); fgSizer1->AddGrowableCol( 2 ); @@ -55,17 +58,15 @@ DIALOG_PCB_TEXT_PROPERTIES_BASE::DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* pare fgSizer1->Add( m_staticText10, 0, wxLEFT|wxRIGHT|wxTOP, 5 ); m_SizeXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeXCtrl->SetMaxLength( 0 ); fgSizer1->Add( m_SizeXCtrl, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); m_PositionXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_PositionXCtrl->SetMaxLength( 0 ); fgSizer1->Add( m_PositionXCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - wxArrayString m_LayerSelectionCtrlChoices; - m_LayerSelectionCtrl = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_LayerSelectionCtrlChoices, 0 ); - m_LayerSelectionCtrl->SetSelection( 0 ); - m_LayerSelectionCtrl->SetToolTip( _("Select the layer on which text should lay.") ); - - fgSizer1->Add( m_LayerSelectionCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_LayerSelectionCtrl = new PCB_LAYER_BOX_SELECTOR( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + fgSizer1->Add( m_LayerSelectionCtrl, 0, wxALL, 5 ); wxString m_DisplayCtrlChoices[] = { _("Normal"), _("Mirrored") }; int m_DisplayCtrlNChoices = sizeof( m_DisplayCtrlChoices ) / sizeof( wxString ); @@ -90,9 +91,11 @@ DIALOG_PCB_TEXT_PROPERTIES_BASE::DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* pare fgSizer1->Add( m_staticText11, 0, wxLEFT|wxRIGHT|wxTOP, 5 ); m_SizeYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeYCtrl->SetMaxLength( 0 ); fgSizer1->Add( m_SizeYCtrl, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); m_PositionYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_PositionYCtrl->SetMaxLength( 0 ); fgSizer1->Add( m_PositionYCtrl, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); wxString m_StyleCtrlChoices[] = { _("Normal"), _("Italic") }; @@ -122,9 +125,11 @@ DIALOG_PCB_TEXT_PROPERTIES_BASE::DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* pare fgSizer1->Add( 0, 0, 1, wxEXPAND, 5 ); m_ThicknessCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_ThicknessCtrl->SetMaxLength( 0 ); fgSizer1->Add( m_ThicknessCtrl, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); m_OrientationCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_OrientationCtrl->SetMaxLength( 0 ); fgSizer1->Add( m_OrientationCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); diff --git a/pcbnew/dialogs/dialog_pcb_text_properties_base.fbp b/pcbnew/dialogs/dialog_pcb_text_properties_base.fbp index ba2d76916c..18ad8d4662 100644 --- a/pcbnew/dialogs/dialog_pcb_text_properties_base.fbp +++ b/pcbnew/dialogs/dialog_pcb_text_properties_base.fbp @@ -42,7 +42,7 @@ -1,-1 DIALOG_PCB_TEXT_PROPERTIES_BASE - 433,450 + 483,450 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU DIALOG_SHIM; dialog_shim.h Text Properties @@ -288,7 +288,7 @@ fgSizer1 wxFLEX_GROWMODE_SPECIFIED none - 6 + 0 0 5 @@ -804,11 +804,11 @@ - + 5 - wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + wxALL 0 - + 1 1 1 @@ -852,22 +852,23 @@ 1 Resizable - 0 + -1 1 - + PCB_LAYER_BOX_SELECTOR; class_pcb_layer_box_selector.h 0 - Select the layer on which text should lay. + wxFILTER_NONE wxDefaultValidator + - + @@ -889,6 +890,8 @@ + + diff --git a/pcbnew/dialogs/dialog_pcb_text_properties_base.h b/pcbnew/dialogs/dialog_pcb_text_properties_base.h index e5062b8b94..c049515d48 100644 --- a/pcbnew/dialogs/dialog_pcb_text_properties_base.h +++ b/pcbnew/dialogs/dialog_pcb_text_properties_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Apr 11 2012) +// C++ code generated with wxFormBuilder (version Oct 8 2012) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -11,6 +11,9 @@ #include #include #include +class DIALOG_SHIM; +class PCB_LAYER_BOX_SELECTOR; + #include "dialog_shim.h" #include #include @@ -19,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +47,7 @@ class DIALOG_PCB_TEXT_PROPERTIES_BASE : public DIALOG_SHIM wxStaticText* m_staticText10; wxTextCtrl* m_SizeXCtrl; wxTextCtrl* m_PositionXCtrl; - wxChoice* m_LayerSelectionCtrl; + PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl; wxChoice* m_DisplayCtrl; wxStaticText* m_SizeYLabel; wxStaticText* m_PositionYLabel; @@ -69,7 +73,7 @@ class DIALOG_PCB_TEXT_PROPERTIES_BASE : public DIALOG_SHIM public: - DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Text Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 433,450 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU ); + DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Text Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 483,450 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU ); ~DIALOG_PCB_TEXT_PROPERTIES_BASE(); }; From 580d42a63ed2c316af638b79450b26365aad8644 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Tue, 3 Sep 2013 21:37:52 +0200 Subject: [PATCH 14/29] pcbnew: fix wxWidgets 2.8 compatibility issue (temporary fix, still have a minor cosmetic issue), and add missing file. --- pcbnew/class_pcb_layer_box_selector.cpp | 2 +- .../dialog_graphic_item_properties_base.cpp | 20 +- .../dialog_graphic_item_properties_base.fbp | 32 +- .../dialog_graphic_item_properties_base.h | 2 +- .../dialogs/dialog_layer_selection_base.cpp | 12 +- .../dialogs/dialog_layer_selection_base.fbp | 1143 +++++++++++++++++ pcbnew/dialogs/dialog_layer_selection_base.h | 4 +- pcbnew/hotkeys_module_editor.cpp | 6 + pcbnew/modedit.cpp | 14 - pcbnew/modedit_onclick.cpp | 27 +- pcbnew/moduleframe.cpp | 4 - pcbnew/pcbnew_id.h | 3 +- pcbnew/sel_layer.cpp | 61 +- 13 files changed, 1212 insertions(+), 118 deletions(-) create mode 100644 pcbnew/dialogs/dialog_layer_selection_base.fbp diff --git a/pcbnew/class_pcb_layer_box_selector.cpp b/pcbnew/class_pcb_layer_box_selector.cpp index 4e4bc1f96d..fb68ddbdb7 100644 --- a/pcbnew/class_pcb_layer_box_selector.cpp +++ b/pcbnew/class_pcb_layer_box_selector.cpp @@ -85,7 +85,7 @@ void PCB_LAYER_BOX_SELECTOR::Resync() } minwidth += BM_SIZE + 35; // Take in account the bitmap size and margins - SetMinClientSize( wxSize( minwidth, -1 ) ); + SetMinSize( wxSize( minwidth, -1 ) ); } diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp b/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp index 3aa70b5b7b..08498ae2a7 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties_base.cpp @@ -85,7 +85,7 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind bUpperRightSizer = new wxBoxSizer( wxVERTICAL ); wxFlexGridSizer* fgUpperRightGridSizer; - fgUpperRightGridSizer = new wxFlexGridSizer( 3, 3, 0, 0 ); + fgUpperRightGridSizer = new wxFlexGridSizer( 0, 3, 0, 0 ); fgUpperRightGridSizer->AddGrowableCol( 1 ); fgUpperRightGridSizer->SetFlexibleDirection( wxBOTH ); fgUpperRightGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); @@ -126,24 +126,18 @@ DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWind m_DefaulThicknessTextUnit->Wrap( -1 ); fgUpperRightGridSizer->Add( m_DefaulThicknessTextUnit, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - bUpperRightSizer->Add( fgUpperRightGridSizer, 0, wxEXPAND, 5 ); - - wxFlexGridSizer* fgLowerRightSizer; - fgLowerRightSizer = new wxFlexGridSizer( 1, 2, 0, 0 ); - fgLowerRightSizer->AddGrowableCol( 1 ); - fgLowerRightSizer->SetFlexibleDirection( wxBOTH ); - fgLowerRightSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_LayerLabel = new wxStaticText( this, wxID_ANY, _("Layer:"), wxDefaultPosition, wxDefaultSize, 0 ); m_LayerLabel->Wrap( -1 ); - fgLowerRightSizer->Add( m_LayerLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + fgUpperRightGridSizer->Add( m_LayerLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); m_LayerSelectionCtrl = new PCB_LAYER_BOX_SELECTOR( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - fgLowerRightSizer->Add( m_LayerSelectionCtrl, 0, wxALL, 5 ); + fgUpperRightGridSizer->Add( m_LayerSelectionCtrl, 0, wxALL, 5 ); - bUpperRightSizer->Add( fgLowerRightSizer, 1, wxEXPAND, 5 ); + fgUpperRightGridSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + + + bUpperRightSizer->Add( fgUpperRightGridSizer, 0, wxEXPAND, 5 ); bUpperSizer->Add( bUpperRightSizer, 1, wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp b/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp index b538865a4a..f661130d58 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp +++ b/pcbnew/dialogs/dialog_graphic_item_properties_base.fbp @@ -42,7 +42,7 @@ -1,-1 DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE - 537,215 + 576,215 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU DIALOG_SHIM; dialog_shim.h Graphic Item Properties @@ -1250,7 +1250,7 @@ fgUpperRightGridSizer wxFLEX_GROWMODE_SPECIFIED none - 3 + 0 0 5 @@ -2023,24 +2023,6 @@ - - - - 5 - wxEXPAND - 1 - - 2 - wxBOTH - 1 - - 0 - - fgLowerRightSizer - wxFLEX_GROWMODE_SPECIFIED - none - 1 - 0 5 wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT @@ -2215,6 +2197,16 @@ + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + +
diff --git a/pcbnew/dialogs/dialog_graphic_item_properties_base.h b/pcbnew/dialogs/dialog_graphic_item_properties_base.h index bb78ca4782..33857856d5 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties_base.h +++ b/pcbnew/dialogs/dialog_graphic_item_properties_base.h @@ -76,7 +76,7 @@ class DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE : public DIALOG_SHIM public: - DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Graphic Item Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 537,215 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU ); + DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Graphic Item Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 576,215 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU ); ~DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE(); }; diff --git a/pcbnew/dialogs/dialog_layer_selection_base.cpp b/pcbnew/dialogs/dialog_layer_selection_base.cpp index ccb42218d5..37e90f562b 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.cpp +++ b/pcbnew/dialogs/dialog_layer_selection_base.cpp @@ -22,7 +22,7 @@ DIALOG_LAYER_SELECTION_BASE::DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWi m_leftGridLayers = new wxGrid( this, ID_LEFT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); // Grid - m_leftGridLayers->CreateGrid( 1, 4 ); + m_leftGridLayers->CreateGrid( 1, 3 ); m_leftGridLayers->EnableEditing( false ); m_leftGridLayers->EnableGridLines( true ); m_leftGridLayers->EnableDragGridSize( false ); @@ -45,12 +45,12 @@ DIALOG_LAYER_SELECTION_BASE::DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWi // Cell Defaults m_leftGridLayers->SetDefaultCellBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); m_leftGridLayers->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); - bSizerUpper->Add( m_leftGridLayers, 0, wxALL|wxEXPAND, 5 ); + bSizerUpper->Add( m_leftGridLayers, 1, wxALL|wxEXPAND, 5 ); m_rightGridLayers = new wxGrid( this, ID_RIGHT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); // Grid - m_rightGridLayers->CreateGrid( 1, 4 ); + m_rightGridLayers->CreateGrid( 1, 3 ); m_rightGridLayers->EnableEditing( false ); m_rightGridLayers->EnableGridLines( true ); m_rightGridLayers->EnableDragGridSize( false ); @@ -72,7 +72,7 @@ DIALOG_LAYER_SELECTION_BASE::DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWi // Cell Defaults m_rightGridLayers->SetDefaultCellBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); m_rightGridLayers->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); - bSizerUpper->Add( m_rightGridLayers, 0, wxALL|wxEXPAND, 5 ); + bSizerUpper->Add( m_rightGridLayers, 1, wxALL|wxEXPAND, 5 ); bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); @@ -121,7 +121,7 @@ DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE m_leftGridLayers = new wxGrid( this, ID_LEFT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); // Grid - m_leftGridLayers->CreateGrid( 1, 4 ); + m_leftGridLayers->CreateGrid( 1, 3 ); m_leftGridLayers->EnableEditing( false ); m_leftGridLayers->EnableGridLines( true ); m_leftGridLayers->EnableDragGridSize( false ); @@ -159,7 +159,7 @@ DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE::DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE m_rightGridLayers = new wxGrid( this, ID_RIGHT_LIST, wxDefaultPosition, wxDefaultSize, 0 ); // Grid - m_rightGridLayers->CreateGrid( 1, 4 ); + m_rightGridLayers->CreateGrid( 1, 3 ); m_rightGridLayers->EnableEditing( false ); m_rightGridLayers->EnableGridLines( true ); m_rightGridLayers->EnableDragGridSize( false ); diff --git a/pcbnew/dialogs/dialog_layer_selection_base.fbp b/pcbnew/dialogs/dialog_layer_selection_base.fbp new file mode 100644 index 0000000000..2a702b9e3c --- /dev/null +++ b/pcbnew/dialogs/dialog_layer_selection_base.fbp @@ -0,0 +1,1143 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_layer_selection_base + 1000 + none + 1 + dialog_layer_selection_base + + . + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_LAYER_SELECTION_BASE + + 337,183 + wxDEFAULT_DIALOG_STYLE + + Select Layer: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizerMain + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + + bSizerUpper + wxHORIZONTAL + none + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + 0 + 0 + + + + 1 + wxSYS_COLOUR_MENU + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + 3 + + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 0 + 0 + 0 + 1 + + 1 + + + 1 + 0 + 0 + ID_LEFT_LIST + wxSYS_COLOUR_WINDOW + + + 3 + 0 + + 0 + + + 0 + + 1 + m_leftGridLayers + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + + 1 + 1 + + + 0 + + + + + + + + + OnLeftGridClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + 0 + 0 + + + + 1 + wxSYS_COLOUR_MENU + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + 3 + + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 0 + 0 + 0 + 1 + + 1 + + + 1 + 0 + 0 + ID_RIGHT_LIST + + + + 3 + 0 + + 0 + + + 0 + + 1 + m_rightGridLayers + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + + 1 + 1 + + + 0 + + + + + + + + + OnRightGridClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxALIGN_RIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Clear Selection + + 0 + + + 0 + + 1 + m_buttonClear + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnClearSelection + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE + + 400,175 + wxDEFAULT_DIALOG_STYLE + + Select Copper Layer Pair: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizerMain + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + + bSizerUpper + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + + bSizerLeft + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Top/Front Layer + + 0 + + + 0 + + 1 + m_staticTextTopLayer + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + 0 + 0 + + + + 1 + wxSYS_COLOUR_MENU + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + 3 + + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 0 + 0 + 0 + 1 + + 1 + + + 1 + 0 + 0 + ID_LEFT_LIST + wxSYS_COLOUR_WINDOW + + + 3 + 0 + + 0 + + + 0 + + 1 + m_leftGridLayers + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + + 1 + 1 + + + 0 + + + + + + + + + OnLeftGridClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSizerRight + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Bottom/Back Layer + + 0 + + + 0 + + 1 + m_staticTextBottomLayer + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + 0 + 0 + + + + 1 + wxSYS_COLOUR_MENU + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + 3 + + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 0 + 0 + 0 + 1 + + 1 + + + 1 + 0 + 0 + ID_RIGHT_LIST + + + + 3 + 0 + + 0 + + + 0 + + 1 + m_rightGridLayers + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTRE + 0 + + wxALIGN_CENTRE + + 1 + 1 + + + 0 + + + + + + + + + OnRightGridClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND | wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer + protected + + OnCancelClick + + + + OnOKClick + + + + + + + + diff --git a/pcbnew/dialogs/dialog_layer_selection_base.h b/pcbnew/dialogs/dialog_layer_selection_base.h index a124524afa..4a2b40f2ac 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.h +++ b/pcbnew/dialogs/dialog_layer_selection_base.h @@ -48,7 +48,7 @@ class DIALOG_LAYER_SELECTION_BASE : public wxDialog public: - DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Layer:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 452,183 ), long style = wxCAPTION|wxCLOSE_BOX ); + DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Layer:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 337,183 ), long style = wxDEFAULT_DIALOG_STYLE ); ~DIALOG_LAYER_SELECTION_BASE(); }; @@ -79,7 +79,7 @@ class DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE : public wxDialog public: - DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Cpper Layer Pair:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 332,175 ), long style = wxDEFAULT_DIALOG_STYLE ); + DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Copper Layer Pair:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 400,175 ), long style = wxDEFAULT_DIALOG_STYLE ); ~DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE(); }; diff --git a/pcbnew/hotkeys_module_editor.cpp b/pcbnew/hotkeys_module_editor.cpp index 0bff61af9e..2e2adcd11c 100644 --- a/pcbnew/hotkeys_module_editor.cpp +++ b/pcbnew/hotkeys_module_editor.cpp @@ -166,6 +166,12 @@ bool FOOTPRINT_EDIT_FRAME::OnHotkeyEditItem( int aIdCommand ) break; + case PCB_MODULE_EDGE_T: + if( aIdCommand == HK_EDIT_ITEM ) + evt_type = ID_POPUP_MODEDIT_EDIT_BODY_ITEM; + + break; + default: break; } diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index ca026f9f11..37fc32f77f 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -214,9 +214,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_STOP_CURRENT_DRAWING: case ID_POPUP_MODEDIT_EDIT_BODY_ITEM: - case ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE: case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: - case ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE: case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: case ID_POPUP_PCB_DELETE_EDGE: @@ -670,24 +668,12 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) m_canvas->Refresh(); break; - case ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE: - m_canvas->MoveCursorToCrossHair(); - Edit_Edge_Width( (EDGE_MODULE*) GetScreen()->GetCurItem() ); - m_canvas->Refresh(); - break; - case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Width( NULL ); m_canvas->Refresh(); break; - case ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE: - m_canvas->MoveCursorToCrossHair(); - Edit_Edge_Layer( (EDGE_MODULE*) GetScreen()->GetCurItem() ); - m_canvas->Refresh(); - break; - case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Layer( NULL ); diff --git a/pcbnew/modedit_onclick.cpp b/pcbnew/modedit_onclick.cpp index 145959aa6d..8418b01725 100644 --- a/pcbnew/modedit_onclick.cpp +++ b/pcbnew/modedit_onclick.cpp @@ -331,7 +331,7 @@ bool FOOTPRINT_EDIT_FRAME::OnRightClick( const wxPoint& MousePos, wxMenu* PopMen if( !flags ) { - msg = AddHotkeyName( _("Move edge" ), g_Module_Editor_Hokeys_Descr, HK_MOVE_ITEM ); + msg = AddHotkeyName( _("Move Edge" ), g_Module_Editor_Hokeys_Descr, HK_MOVE_ITEM ); AddMenuItem( PopMenu, ID_POPUP_PCB_MOVE_EDGE, msg, KiBitmap( move_line_xpm ) ); } @@ -339,21 +339,20 @@ bool FOOTPRINT_EDIT_FRAME::OnRightClick( const wxPoint& MousePos, wxMenu* PopMen AddMenuItem( PopMenu, ID_POPUP_PCB_PLACE_EDGE, _( "Place edge" ), KiBitmap( apply_xpm ) ); - wxMenu* edit_mnu = new wxMenu; - AddMenuItem( PopMenu, edit_mnu, ID_POPUP_MODEDIT_EDIT_EDGE, _( "Edit" ), KiBitmap( edit_xpm ) ); - AddMenuItem( edit_mnu, ID_POPUP_MODEDIT_EDIT_BODY_ITEM, - _( "Edit Body Item" ), KiBitmap( options_segment_xpm ) ); - AddMenuItem( edit_mnu, ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE, - _( "Change Body Item Width (Current)" ), KiBitmap( width_segment_xpm ) ); - AddMenuItem( edit_mnu, ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE, - _( "Change Body Items Width (All)" ), KiBitmap( width_segment_xpm ) ); - AddMenuItem( edit_mnu, ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE, - _( "Change Body Item Layer (Current)" ), KiBitmap( select_layer_pair_xpm ) ); - AddMenuItem( edit_mnu, ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE, - _( "Change Body Items Layer (All)" ), KiBitmap( select_layer_pair_xpm ) ); - msg = AddHotkeyName( _("Delete edge" ), g_Module_Editor_Hokeys_Descr, HK_DELETE ); + msg = AddHotkeyName( _("Edit" ), g_Module_Editor_Hokeys_Descr, HK_EDIT_ITEM ); + AddMenuItem( PopMenu, ID_POPUP_MODEDIT_EDIT_BODY_ITEM, + msg, KiBitmap( options_segment_xpm ) ); + msg = AddHotkeyName( _("Delete Edge" ), g_Module_Editor_Hokeys_Descr, HK_DELETE ); AddMenuItem( PopMenu, ID_POPUP_PCB_DELETE_EDGE, msg, KiBitmap( delete_xpm ) ); + + wxMenu* edit_global_mnu = new wxMenu; + AddMenuItem( PopMenu, edit_global_mnu, ID_POPUP_MODEDIT_GLOBAL_EDIT_EDGE, + _( "Global Changes" ), KiBitmap( edit_xpm ) ); + AddMenuItem( edit_global_mnu, ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE, + _( "Change Body Items Width" ), KiBitmap( width_segment_xpm ) ); + AddMenuItem( edit_global_mnu, ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE, + _( "Change Body Items Layer" ), KiBitmap( select_layer_pair_xpm ) ); } break; diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index 4e9834fb72..fed5c049e1 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -115,12 +115,8 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( ID_POPUP_MODEDIT_EDIT_BODY_ITEM, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) - EVT_MENU( ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE, - FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) - EVT_MENU( ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE, - FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index f4e5caa83b..8d89a6116a 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -312,9 +312,8 @@ enum pcbnew_ids ID_MODEDIT_PLACE_GRID_COORD, // ID used in module editor: - ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE, + ID_POPUP_MODEDIT_GLOBAL_EDIT_EDGE, ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE, - ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE, ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE, ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH, ID_POPUP_MODEDIT_EDIT_EDGE, diff --git a/pcbnew/sel_layer.cpp b/pcbnew/sel_layer.cpp index 0634c7fb28..fc8ebc10e1 100644 --- a/pcbnew/sel_layer.cpp +++ b/pcbnew/sel_layer.cpp @@ -83,6 +83,8 @@ class PCB_ONE_LAYER_SELECTOR : public PCB_LAYER_SELECTOR, LAYER_NUM m_layerSelected; LAYER_NUM m_minLayer; LAYER_NUM m_maxLayer; + std::vector m_layersIdLeftColumn; + std::vector m_layersIdRightColumn; public: PCB_ONE_LAYER_SELECTOR( wxWindow* aParent, BOARD * aBrd, @@ -122,25 +124,17 @@ private: #define SELECT_COLNUM 0 #define COLOR_COLNUM 1 #define LAYERNAME_COLNUM 2 -#define LAYERID_COLNUM 3 static DECLARE_LAYERS_ORDER_LIST( layertranscode ); void PCB_ONE_LAYER_SELECTOR::BuildList() { - m_leftGridLayers->SetColFormatNumber( LAYERID_COLNUM ); - m_rightGridLayers->SetColFormatNumber( LAYERID_COLNUM ); - m_leftGridLayers->HideCol( LAYERID_COLNUM ); - m_rightGridLayers->HideCol( LAYERID_COLNUM ); + // Hide layerid column which is used only to know the layer id + // not to be shown in dialogs m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 ); m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 ); - // Select a not show cell, to avoid a wrong cell selection for user - m_leftGridLayers->GoToCell( 0, LAYERID_COLNUM ); - m_rightGridLayers->GoToCell( 0, LAYERID_COLNUM ); - int left_row = 0; int right_row = 0; - wxString layernum; wxString layername; for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i ) { @@ -160,7 +154,6 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() wxColour color = MakeColour( GetLayerColor( layerid ) ); layername = GetLayerName( layerid ); - layernum.Printf( wxT("%d"), layerid ); if( layerid <= LAST_COPPER_LAYER ) { @@ -171,8 +164,6 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() color ); m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername ); - m_leftGridLayers->SetCellValue( left_row, LAYERID_COLNUM, - layernum ); if( m_layerSelected == layerid ) { @@ -180,8 +171,10 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() wxT("X") ); m_leftGridLayers->SetCellBackgroundColour ( left_row, SELECT_COLNUM, color ); + m_leftGridLayers->SetGridCursor( left_row, LAYERNAME_COLNUM ); } + m_layersIdLeftColumn.push_back( layerid ); left_row++; } else @@ -193,8 +186,6 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() color ); m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername ); - m_rightGridLayers->SetCellValue( right_row, LAYERID_COLNUM, - layernum ); if( m_layerSelected == layerid ) { @@ -202,8 +193,10 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() wxT("X") ); m_rightGridLayers->SetCellBackgroundColour ( right_row, SELECT_COLNUM, color ); + m_rightGridLayers->SetGridCursor( right_row, LAYERNAME_COLNUM ); } + m_layersIdRightColumn.push_back( layerid ); right_row++; } } @@ -223,19 +216,13 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() void PCB_ONE_LAYER_SELECTOR::OnLeftGridClick( wxGridEvent& event ) { - wxString text = m_leftGridLayers->GetCellValue(event.GetRow(), LAYERID_COLNUM); - long layer; - text.ToLong( &layer ); - m_layerSelected = layer; + m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ]; EndModal( 1 ); } void PCB_ONE_LAYER_SELECTOR::OnRightGridClick( wxGridEvent& event ) { - wxString text = m_rightGridLayers->GetCellValue(event.GetRow(), LAYERID_COLNUM); - long layer; - text.ToLong( &layer ); - m_layerSelected = layer; + m_layerSelected = m_layersIdRightColumn[ event.GetRow() ]; EndModal( 2 ); } @@ -283,6 +270,7 @@ private: LAYER_NUM m_backLayer; int m_leftRowSelected; int m_rightRowSelected; + std::vector m_layersId; public: SELECT_COPPER_LAYERS_PAIR_DIALOG( wxWindow* aParent, BOARD * aPcb, @@ -354,20 +342,14 @@ SELECT_COPPER_LAYERS_PAIR_DIALOG:: void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() { - m_leftGridLayers->SetColFormatNumber( LAYERID_COLNUM ); - m_rightGridLayers->SetColFormatNumber( LAYERID_COLNUM ); - m_leftGridLayers->HideCol( LAYERID_COLNUM ); - m_rightGridLayers->HideCol( LAYERID_COLNUM ); m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 ); m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 ); // Select a not show cell, to avoid a wrong cell selection for user - m_leftGridLayers->GoToCell( 0, LAYERID_COLNUM ); - m_rightGridLayers->GoToCell( 0, LAYERID_COLNUM ); int row = 0; - wxString layernum; wxString layername; + for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i ) { LAYER_NUM layerid = i; @@ -383,16 +365,15 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() wxColour color = MakeColour( GetLayerColor( layerid ) ); layername = GetLayerName( layerid ); - layernum.Printf( wxT("%d"), layerid ); if( row ) m_leftGridLayers->AppendRows( 1 ); + m_leftGridLayers->SetCellBackgroundColour ( row, COLOR_COLNUM, color ); m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername ); - m_leftGridLayers->SetCellValue( row, LAYERID_COLNUM, - layernum ); + m_layersId.push_back( layerid ); if( m_frontLayer == layerid ) { @@ -401,6 +382,7 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() m_leftGridLayers->SetCellBackgroundColour( row, SELECT_COLNUM, color ); m_leftRowSelected = row; + m_leftGridLayers->SetGridCursor( row, LAYERNAME_COLNUM ); } if( row ) @@ -409,8 +391,6 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() color ); m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername ); - m_rightGridLayers->SetCellValue( row, LAYERID_COLNUM, - layernum ); if( m_backLayer == layerid ) { @@ -419,6 +399,7 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() m_rightGridLayers->SetCellBackgroundColour ( row, SELECT_COLNUM, color ); m_rightRowSelected = row; + m_rightGridLayers->SetGridCursor( row, LAYERNAME_COLNUM ); } row++; @@ -433,9 +414,7 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridClick( wxGridEvent& event ) { int row = event.GetRow(); - wxString text = m_leftGridLayers->GetCellValue( row, LAYERID_COLNUM ); - long layer; - text.ToLong( &layer ); + LAYER_NUM layer = m_layersId[row]; if( m_frontLayer == layer ) return; @@ -452,14 +431,13 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridClick( wxGridEvent& event ) m_leftGridLayers->SetCellBackgroundColour( row, SELECT_COLNUM, MakeColour( GetLayerColor( layer ) ) ); + m_leftGridLayers->SetGridCursor( row, LAYERNAME_COLNUM ); } void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridClick( wxGridEvent& event ) { int row = event.GetRow(); - wxString text = m_rightGridLayers->GetCellValue( row, LAYERID_COLNUM ); - long layer; - text.ToLong( &layer ); + LAYER_NUM layer = m_layersId[row]; if( m_backLayer == layer ) return; @@ -475,4 +453,5 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridClick( wxGridEvent& event ) wxT("X") ); m_rightGridLayers->SetCellBackgroundColour ( row, SELECT_COLNUM, MakeColour( GetLayerColor( layer ) ) ); + m_rightGridLayers->SetGridCursor( row, LAYERNAME_COLNUM ); } From a7f31c59a86340f1c011f3ee70d466fe8a430a64 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Fri, 6 Sep 2013 08:17:33 -0400 Subject: [PATCH 15/29] Footprint library table ground work. * Remove defined CMAKE_INSTALL_PREFIX for Windows from main CMakeList.txt. * Move footprint library path detection code from pcbnew.cpp to EDA_APP object. * Add CMAKE_INSTALL_PREFIX to config.h.cmake. * Simplify and fix search path list code. * Add CMAKE_INSTALL_PREFIX to the list of search paths in case KiCad was installed using `make install`. * Add default global footprint library table to CMake install. * Add method to set footprint library table to PCB_BASE_FRAME object. * Remove unused function EDA_APP::GetLibraryFile(). * Minor FP_LIB_TABLE object improvements. --- CMakeLists.txt | 9 ++- CMakeModules/config.h.cmake | 6 ++ common/edaappl.cpp | 109 +++++++++++++++++++++++++----------- common/fp_lib_table.cpp | 53 +++++++++++++++--- cvpcb/cvpcb.cpp | 46 +++++++++++---- include/appl_wxstruct.h | 21 ++++++- include/fp_lib_table.h | 17 +++++- include/wxBasePcbFrame.h | 11 ++++ include/wxPcbStruct.h | 6 -- pcbnew/modview_frame.cpp | 2 - pcbnew/pcbframe.cpp | 20 ++++++- pcbnew/pcbnew.cpp | 27 +-------- pcbnew/pcbnew_config.cpp | 52 +++++++---------- template/CMakeLists.txt | 3 +- 14 files changed, 256 insertions(+), 126 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e5747a661..67b446d867 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,10 +197,14 @@ else() endif() endif() +#================================================ # Locations for install targets. set( KICAD_BIN bin CACHE PATH "Location of KiCad binaries." ) +set( KICAD_FP_LIB_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}" + CACHE PATH "Default path where footprint libraries are installed." ) + if( UNIX ) # Everything without leading / is relative to CMAKE_INSTALL_PREFIX. set( KICAD_PLUGINS lib/kicad/plugins @@ -209,12 +213,10 @@ if( UNIX ) CACHE PATH "Location of KiCad data files." ) set( KICAD_DOCS share/doc/kicad CACHE PATH "Location of KiCad documentation files." ) + set( KICAD_FP_LIB_INSTALL_PATH "${KICAD_FP_LIB_INSTALL_PATH}/share/kicad/modules" ) endif() if( MINGW ) - # Like all variables, CMAKE_INSTALL_PREFIX can be over-ridden on the command line. - set( CMAKE_INSTALL_PREFIX c:/kicad - CACHE PATH "" ) # Everything without leading / is relative to CMAKE_INSTALL_PREFIX. set( KICAD_PLUGINS ${KICAD_BIN}/plugins CACHE PATH "Location of KiCad plugins." ) @@ -222,6 +224,7 @@ if( MINGW ) CACHE PATH "Location of KiCad data files." ) set( KICAD_DOCS doc CACHE PATH "Location of KiCad documentation files." ) + set( KICAD_FP_LIB_INSTALL_PATH "${KICAD_FP_LIB_INSTALL_PATH}/modules" ) endif() set( KICAD_DEMOS ${KICAD_DATA}/demos diff --git a/CMakeModules/config.h.cmake b/CMakeModules/config.h.cmake index db9ba8ee84..7f8cd4cd19 100644 --- a/CMakeModules/config.h.cmake +++ b/CMakeModules/config.h.cmake @@ -81,6 +81,12 @@ /// Definition to compile with Pcbnew footprint library table implementation. #cmakedefine USE_FP_LIB_TABLE +/// The install prefix defined in CMAKE_INSTALL_PREFIX. +#define DEFAULT_INSTALL_PATH "@CMAKE_INSTALL_PREFIX" + +/// Default footprint library install path when installed with `make install`. +#define DEFAULT_FP_LIB_PATH "@KICAD_FP_LIB_INSTALL_PATH@" + /// When defined, build the GITHUB_PLUGIN for pcbnew. #cmakedefine BUILD_GITHUB_PLUGIN diff --git a/common/edaappl.cpp b/common/edaappl.cpp index 84a52c7606..706b6f70c9 100644 --- a/common/edaappl.cpp +++ b/common/edaappl.cpp @@ -64,18 +64,16 @@ static const wxChar* CommonConfigPath = wxT( "kicad_common" ); * the size of the array. */ #define LANGUAGE_DESCR_COUNT ( sizeof( s_Language_List ) / sizeof( struct LANGUAGE_DESCR ) ) -// Default font size -#define FONT_DEFAULT_SIZE 10 // Default font size. // some key strings used to store parameters in config static wxString backgroundColorKey( wxT( "BackgroundColor" ) ); static wxString showPageLimitsKey( wxT( "ShowPageLimits" ) ); static wxString workingDirKey( wxT( "WorkingDir" ) ) ; static wxString languageCfgKey( wxT( "LanguageID" ) ); +static wxString kicadFpLibPath( wxT( "KicadFootprintLibraryPath" ) ); /** - * The real font size will be computed at run time * A small class to handle the list on existing translations. * the locale translation is automatic. * the selection of languages is mainly for maintainer's convenience @@ -354,7 +352,7 @@ void EDA_APP::InitEDA_Appl( const wxString& aName, EDA_APP_T aId ) wxImage::AddHandler( new wxJPEGHandler ); wxFileSystem::AddHandler( new wxZipFSHandler ); - // Analise the command line & init binary path + // Analyze the command line & init binary path SetBinDir(); SetDefaultSearchPaths(); SetLanguagePath(); @@ -496,24 +494,20 @@ void EDA_APP::SetDefaultSearchPaths( void ) * if the user is savvy enough to set an environment variable they know * what they are doing. */ if( ::wxGetEnv( wxT( "KICAD" ), NULL ) ) - m_searchPaths.AddEnvList( wxT( "KICAD" ) ); + tmp.AddEnvList( wxT( "KICAD" ) ); // Add the user's home path. - m_searchPaths.Add( GetTraits()->GetStandardPaths().GetUserDataDir() ); + tmp.Add( GetTraits()->GetStandardPaths().GetUserDataDir() ); // Standard application data path if it is different from the binary path. if( fn.GetPath() != GetTraits()->GetStandardPaths().GetDataDir() ) { - m_searchPaths.Add( GetTraits()->GetStandardPaths().GetDataDir() ); + tmp.Add( GetTraits()->GetStandardPaths().GetDataDir() ); } // Up one level relative to binary path with "share" appended for Windows. fn.RemoveLastDir(); - m_searchPaths.Add( fn.GetPath() ); - fn.AppendDir( wxT( "share" ) ); - m_searchPaths.Add( fn.GetPath() ); - fn.AppendDir( wxT( "kicad" ) ); - m_searchPaths.Add( fn.GetPath() ); + tmp.Add( fn.GetPath() ); /* The normal OS program file install paths allow for binary to be * installed in a different path from the library files. This is @@ -524,13 +518,16 @@ void EDA_APP::SetDefaultSearchPaths( void ) #ifdef __WXMSW__ tmp.AddEnvList( wxT( "PROGRAMFILES" ) ); #elif __WXMAC__ - m_searchPaths.Add( wxT( "/Library/Application Support/kicad" ) ); - m_searchPaths.Add( wxString( wxGetenv( wxT( "HOME" ) ) ) + - wxT("/Library/Application Support/kicad") ); + tmp.Add( wxT( "/Library/Application Support" ) ); + tmp.Add( wxString( wxGetenv( wxT( "HOME" ) ) ) + wxT( "/Library/Application Support" ) ); #else tmp.AddEnvList( wxT( "PATH" ) ); #endif + // This is the equivalent of CMAKE_INSTALL_PREFIX. Useful when installed by `make install`. + tmp.Add( wxT( DEFAULT_INSTALL_PATH ) ); + + // Add kicad, kicad/share, share, and share/kicad to each possible base path. for( i = 0; i < tmp.GetCount(); i++ ) { fn = wxFileName( tmp[i], wxEmptyString ); @@ -621,6 +618,13 @@ void EDA_APP::SetDefaultSearchPaths( void ) fn.RemoveLastDir(); } } + +#if 1 && defined( DEBUG ) + wxLogDebug( wxT( "Library search paths:" ) ); + + for( unsigned i = 0; i < m_libSearchPaths.GetCount(); i++ ) + wxLogDebug( wxT( " %s" ), GetChars( m_libSearchPaths[i] ) ); +#endif } @@ -662,11 +666,14 @@ void EDA_APP::GetSettings( bool aReopenLastUsedDirectory ) } // FIXME OSX Mountain Lion (10.8) - // Seems that Read doesn't found anything and ColorFromInt Asserts - I'm unable to reproduce on 10.7 - // In general terms i think is better have a failsafe default than an uninit variable + // Seems that Read doesn't found anything and ColorFromInt Asserts - I'm unable to reproduce + // on 10.7 + // In general terms I think is better have a failsafe default than an uninit variable int draw_bg_color = (int)BLACK; // Default for all apps but Eeschema + if( m_Id == APP_EESCHEMA_T ) draw_bg_color = (int)WHITE; // Default for Eeschema + m_settings->Read( backgroundColorKey, &draw_bg_color ); g_DrawBgColor = ColorFromInt( draw_bg_color ); @@ -876,7 +883,7 @@ void EDA_APP::AddMenuLanguageList( wxMenu* MasterMenu ) wxString EDA_APP::FindFileInSearchPaths( const wxString& filename, - const wxArrayString* subdirs ) + const wxArrayString* subdirs ) { size_t i, j; wxFileName fn; @@ -979,21 +986,6 @@ wxString EDA_APP::GetHelpFile( void ) } -wxString EDA_APP::GetLibraryFile( const wxString& filename ) -{ - wxArrayString subdirs; - - subdirs.Add( wxT( "share" ) ); -#ifndef __WXMSW__ - - /* Up on level relative to binary path with "share/kicad" appended for - * all other platforms. */ - subdirs.Add( wxT( "kicad" ) ); -#endif - return FindFileInSearchPaths( filename, &subdirs ); -} - - wxString EDA_APP::ReturnLastVisitedLibraryPath( const wxString& aSubPathToSearch ) { if( !m_LastVisitedLibPath.IsEmpty() ) @@ -1164,3 +1156,54 @@ bool EDA_APP::LockFile( const wxString& fileName ) return true; } + + +bool EDA_APP::SetFootprintLibTablePath() +{ + wxString path; + + // Set the KISYSMOD environment variable for the current process if it is not already + // defined in the user's environment. This is required to expand the global footprint + // library table paths. + if( wxGetEnv( wxT( "KISYSMOD" ), &path ) && wxFileName::DirExists( path ) ) + return true; + + // Set the KISYSMOD environment variable to the path defined in the user's configuration + // if it is defined and the path exists. + if( m_commonSettings->Read( kicadFpLibPath, &path ) && wxFileName::DirExists( path ) ) + { + wxSetEnv( wxT( "KISYSMOD" ), path ); + wxLogDebug( wxT( "Setting $KISYSMOD=\"%s\"." ), GetChars( path ) ); + return true; + } + + // Attempt to determine where the footprint libraries were installed using the legacy + // library search paths. + if( !GetLibraryPathList().IsEmpty() ) + { + unsigned modFileCount = 0; + wxString bestPath; + wxArrayString tmp; + + for( unsigned i = 0; i < GetLibraryPathList().GetCount(); i++ ) + { + unsigned cnt = wxDir::GetAllFiles( GetLibraryPathList()[i], &tmp, wxT( "*.mod" ), + wxDIR_DEFAULT & ~wxDIR_HIDDEN ); + + if( cnt > modFileCount ) + { + modFileCount = cnt; + bestPath = GetLibraryPathList()[i]; + } + } + + if( modFileCount != 0 ) + { + wxLogDebug( wxT( "Setting $KISYSMOD=\"%s\"." ), GetChars( bestPath ) ); + wxSetEnv( wxT( "KISYSMOD" ), bestPath ); + return true; + } + } + + return false; +} diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index b03f8d3a2e..c90b0c586a 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -30,6 +30,7 @@ #include +#include #include #include @@ -319,23 +320,38 @@ bool FP_LIB_TABLE::IsEmpty() const } -void FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ) +bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ) { + bool tableExists = true; wxFileName fn = GetGlobalTableFileName(); wxLogDebug( wxT( "Loading global footprint table file: %s" ), GetChars( fn.GetFullPath() ) ); if( !fn.FileExists() ) { - /// @todo call some script to create initial global footprint table. - } - else - { - FILE_LINE_READER reader( fn.GetFullPath() ); - FP_LIB_TABLE_LEXER lexer( &reader ); + tableExists = false; - aTable.Parse( &lexer ); + // Attempt to copy the default global file table from the KiCad template folder to + // the users home configuration path. + wxString fileName( wxT( "fp_global_table" ) ); + fileName = wxGetApp().FindLibraryPath( fileName ); + + wxLogDebug( wxT( "Copying global footprint table from <%s>." ), GetChars( fileName ) ); + + // The fallback is to create an empty global footprint table for the user to populate. + if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) ) + { + FP_LIB_TABLE emptyTable; + FILE_OUTPUTFORMATTER sf( fn.GetFullPath() ); + emptyTable.Format( &sf, 0 ); + } } + + FILE_LINE_READER reader( fn.GetFullPath() ); + FP_LIB_TABLE_LEXER lexer( &reader ); + + aTable.Parse( &lexer ); + return tableExists; } @@ -357,7 +373,26 @@ wxString FP_LIB_TABLE::GetGlobalTableFileName() wxString FP_LIB_TABLE::GetFileName() { - return wxString( wxT( ".fp-lib-table" ) ); + return wxString( wxT( "fp-lib-table" ) ); +} + + +void FP_LIB_TABLE::Load( const wxFileName& aFileName, FP_LIB_TABLE* aFallBackTable ) + throw( IO_ERROR ) +{ + wxFileName fn = aFileName; + + fallBack = aFallBackTable; + + fn.SetName( FP_LIB_TABLE::GetFileName() ); + fn.SetExt( wxEmptyString ); + + if( fn.FileExists() ) + { + FILE_LINE_READER reader( fn.GetFullPath() ); + FP_LIB_TABLE_LEXER lexer( &reader ); + Parse( &lexer ); + } } diff --git a/cvpcb/cvpcb.cpp b/cvpcb/cvpcb.cpp index c3f758e8c4..2b78d7aca6 100644 --- a/cvpcb/cvpcb.cpp +++ b/cvpcb/cvpcb.cpp @@ -1,3 +1,27 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + /** * @file cvpcb.cpp */ @@ -22,7 +46,7 @@ // Colors for layers and items COLORS_DESIGN_SETTINGS g_ColorsSettings; -/* Constant string definitions for CvPcb */ +// Constant string definitions for CvPcb const wxString RetroFileExtension( wxT( "stf" ) ); const wxString FootprintAliasFileExtension( wxT( "equ" ) ); @@ -36,7 +60,7 @@ const wxString titleLibLoadError( _( "Library Load Error" ) ); * MacOSX: Needed for file association * http://wiki.wxwidgets.org/WxMac-specific_topics */ -void EDA_APP::MacOpenFile(const wxString &fileName) +void EDA_APP::MacOpenFile( const wxString &fileName ) { wxFileName filename = fileName; wxString oldPath; @@ -48,7 +72,7 @@ void EDA_APP::MacOpenFile(const wxString &fileName) if( frame->m_NetlistFileName.DirExists() ) oldPath = frame->m_NetlistFileName.GetPath(); - /* Update the library search path list. */ + // Update the library search path list. if( wxGetApp().GetLibraryPathList().Index( oldPath ) != wxNOT_FOUND ) wxGetApp().GetLibraryPathList().Remove( oldPath ); @@ -58,6 +82,7 @@ void EDA_APP::MacOpenFile(const wxString &fileName) frame->ReadNetListAndLinkFiles(); } + // Create a new application object IMPLEMENT_APP( EDA_APP ) @@ -74,6 +99,10 @@ bool EDA_APP::OnInit() InitEDA_Appl( wxT( "CvPcb" ), APP_CVPCB_T ); +#if defined( USE_FP_LIB_TABLE ) + SetFootprintLibTablePath(); +#endif + if( m_Checker && m_Checker->IsAnotherRunning() ) { if( !IsOK( NULL, _( "CvPcb is already running, Continue?" ) ) ) @@ -88,7 +117,7 @@ bool EDA_APP::OnInit() // read current setup and reopen last directory if no filename to open in command line bool reopenLastUsedDirectory = argc == 1; - GetSettings(reopenLastUsedDirectory); + GetSettings( reopenLastUsedDirectory ); g_DrawBgColor = BLACK; @@ -97,15 +126,13 @@ bool EDA_APP::OnInit() // Show the frame SetTopWindow( frame ); - - frame->LoadProjectFile( filename.GetFullPath() ); frame->Show( true ); - frame->BuildFOOTPRINTS_LISTBOX(); - frame->BuildLIBRARY_LISTBOX(); + frame->m_NetlistFileExtension = wxT( "net" ); if( filename.IsOk() && filename.FileExists() ) { frame->m_NetlistFileName = filename; + frame->LoadProjectFile( filename.GetFullPath() ); if( frame->ReadNetListAndLinkFiles() ) { @@ -114,9 +141,6 @@ bool EDA_APP::OnInit() } } - frame->LoadFootprintFiles(); - frame->m_NetlistFileExtension = wxT( "net" ); - frame->m_NetlistFileName.Clear(); frame->UpdateTitle(); return true; diff --git a/include/appl_wxstruct.h b/include/appl_wxstruct.h index 6ef675f6a1..a50c9b2241 100644 --- a/include/appl_wxstruct.h +++ b/include/appl_wxstruct.h @@ -344,8 +344,6 @@ public: */ wxString GetHelpFile( void ); - wxString GetLibraryFile( const wxString& filename ); - /** * Return the preferred editor name. */ @@ -414,6 +412,25 @@ public: * @return false if the file was already locked, true otherwise. */ bool LockFile( const wxString& fileName ); + + /** + * Function SetFootprintLibTableEnv + * attempts set the KISYSMOD environment variable to the best possible path. + * + * The path is determined by attempting to find the path with the most footprint library + * files. This may or may not be the best path but it provides the best solution for + * backwards compatibility with the previous library search path implementation. If the + * KISYSMOD environment variable is already set, then it left as is to respect the wishes + * of the user. + * + * @note This must be called after #SetDefaultSearchPaths() is called. Otherwise, the + * list of library search paths will be empty and KISYSMOD will be undefined making + * it impossible for the footprint libraries to be loaded from the footprint library + * table. + * + * @return false if the KISYSMOD path is not valid. + */ + bool SetFootprintLibTablePath(); }; diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 8c86d00aaa..f9f64fa9ff 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -379,8 +379,11 @@ public: * time being. * * @param aTable the #FP_LIB_TABLE object to load. + * @return true if the global library table exists and is loaded properly. + * @throw IO_ERROR if an error occurs attempting to load the footprint library + * table. */ - static void LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ); + static bool LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ); /** * Function GetGlobalTableFileName @@ -394,6 +397,18 @@ public: */ static wxString GetFileName(); + /** + * Function Load + * loads the footprint library table using the path defined in \a aFileName with + * \a aFallBackTable. + * + * @param aFileName contains the path and possible the file name and extension. + * @param aFallBackTable the fall back footprint library table which can be NULL. + * @throw IO_ERROR if an error occurs attempting to load the footprint library + * table. + */ + void Load( const wxFileName& aFileName, FP_LIB_TABLE* aFallBackTable ) throw( IO_ERROR ); + protected: /** diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 7118ff8867..12843befbe 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -173,6 +173,17 @@ public: return m_Pcb; } + /** + * Function SetFootprintLibTable + * set the footprint library table to \a aFootprintLibTable. + * + * @param aFootprintLibTable is a pointer to the #FP_LIB_TABLE object. + */ + void SetFootprintLibTable( FP_LIB_TABLE* aFootprintLibTable ) + { + m_footprintLibTable = aFootprintLibTable; + } + // General virtual void OnCloseWindow( wxCloseEvent& Event ) = 0; virtual void RedrawActiveWindow( wxDC* DC, bool EraseBg ) { } diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 7df4dfb73e..d7b2c09b5e 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -202,12 +202,6 @@ protected: */ void duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ); - /** - * Function loadFootprintLibTable - * deletes the existing #FP_LIB_TABLE and creates a new one when a new project is loaded. - */ - void loadFootprintLibTable(); - public: PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; // a combo box to display and select active layer wxComboBox* m_SelTrackWidthBox; // a combo box to display and select current track width diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index b8cf54629f..b002ea82d6 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -123,8 +123,6 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent, PCB_BASE_FRAME( aParent, MODULE_VIEWER_FRAME_TYPE, _( "Footprint Library Browser" ), wxDefaultPosition, wxDefaultSize, aStyle, GetFootprintViewerFrameName() ) { - wxASSERT( aTable != NULL ); - wxAcceleratorTable table( ACCEL_TABLE_CNT, accels ); m_footprintLibTable = aTable; diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index e45b22075b..b0e3e1c018 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -293,8 +293,11 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, m_RecordingMacros = -1; m_microWaveToolBar = NULL; m_useCmpFileForFpNames = true; + +#if defined( USE_FP_LIB_TABLE ) m_footprintLibTable = NULL; m_globalFootprintTable = NULL; +#endif #ifdef KICAD_SCRIPTING_WXPYTHON m_pythonPanel = NULL; @@ -443,12 +446,25 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, m_auimgr.Update(); +#if defined( USE_FP_LIB_TABLE ) if( m_globalFootprintTable == NULL ) { try { m_globalFootprintTable = new FP_LIB_TABLE(); - FP_LIB_TABLE::LoadGlobalTable( *m_globalFootprintTable ); + + if( !FP_LIB_TABLE::LoadGlobalTable( *m_globalFootprintTable ) ) + { + DisplayInfoMessage( this, wxT( "You have run Pcbnew for the first time using the " + "new footprint library table method for finding " + "footprints. Pcbnew has either copied the default " + "table or created an empty table in your home " + "folder. You must first configure the library " + "table to include all footprint libraries not " + "included with KiCad. See the \"Footprint Library " + "Table\" section of the CvPcb documentation for " + "more information." ) ); + } } catch( IO_ERROR ioe ) { @@ -458,6 +474,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, DisplayError( this, msg ); } } +#endif } @@ -470,6 +487,7 @@ PCB_EDIT_FRAME::~PCB_EDIT_FRAME() m_Macros[i].m_Record.clear(); delete m_drc; + delete m_footprintLibTable; delete m_globalFootprintTable; } diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index aa8887a2f1..4602111ee7 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -206,30 +206,9 @@ bool EDA_APP::OnInit() // Some will be overwritten after loading the board file frame->LoadProjectSettings( fn.GetFullPath() ); - // Set the KISYSMOD environment variable for the current process if it is not already - // defined in the user's environment. This is required to expand the global footprint - // library table paths. - if( !wxGetEnv( wxT( "KISYSMOD" ), &msg ) && !GetLibraryPathList().IsEmpty() ) - { - unsigned modFileCount = 0; - wxString bestPath; - wxArrayString tmp; - - for( unsigned i = 0; i < GetLibraryPathList().GetCount(); i++ ) - { - unsigned cnt = wxDir::GetAllFiles( GetLibraryPathList()[i], &tmp, - wxT( "*.mod" ), wxDIR_DEFAULT & ~wxDIR_HIDDEN ); - - if( cnt > modFileCount ) - { - modFileCount = cnt; - bestPath = GetLibraryPathList()[i]; - } - } - - wxLogDebug( wxT( "Setting $KISYSMOD=\"%s\"." ), GetChars( bestPath ) ); - wxSetEnv( wxT( "KISYSMOD" ), bestPath ); - } +#if defined( USE_FP_LIB_TABLE ) + SetFootprintLibTablePath(); +#endif /* Load file specified in the command line. */ if( fn.IsOk() ) diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index 8f3b4ecc18..1e6cd47581 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -222,13 +222,30 @@ bool PCB_EDIT_FRAME::LoadProjectSettings( const wxString& aProjectFileName ) SetElementVisibility( RATSNEST_VISIBLE, showRats ); #endif + fn = GetBoard()->GetFileName(); + + // Check if a project footprint table is defined and load it. If no project footprint + // table is defined, then the global library table is the footprint library table. +#if defined( USE_FP_LIB_TABLE ) + delete m_footprintLibTable; + + m_footprintLibTable = new FP_LIB_TABLE(); + + try + { + m_footprintLibTable->Load( fn, m_globalFootprintTable ); + } + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + } +#endif + // Load the page layout decr file, from the filename stored in // BASE_SCREEN::m_PageLayoutDescrFileName, read in config project file // If empty, the default descr is loaded WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); - pglayout.SetPageLayout(BASE_SCREEN::m_PageLayoutDescrFileName); - - loadFootprintLibTable(); + pglayout.SetPageLayout( BASE_SCREEN::m_PageLayoutDescrFileName ); return true; } @@ -550,32 +567,3 @@ void PCB_EDIT_FRAME::ReadMacros() macrosNode = (XNODE*) macrosNode->GetNext(); } } - - -void PCB_EDIT_FRAME::loadFootprintLibTable() -{ - delete m_footprintLibTable; - - wxFileName fn = GetBoard()->GetFileName(); - fn.SetName( FP_LIB_TABLE::GetFileName() ); - fn.SetExt( wxEmptyString ); - - // Check if a project footprint table is defined and load it. If no project footprint - // table is defined, then the global library table is the footprint library table. - - m_footprintLibTable = new FP_LIB_TABLE( m_globalFootprintTable ); - - if( fn.FileExists() ) - { - try - { - FILE_LINE_READER reader( fn.GetFullPath() ); - FP_LIB_TABLE_LEXER lexer( &reader ); - m_footprintLibTable->Parse( &lexer ); - } - catch( IO_ERROR ioe ) - { - DisplayError( this, ioe.errorText ); - } - } -} diff --git a/template/CMakeLists.txt b/template/CMakeLists.txt index 3461fe6934..c634135bb0 100644 --- a/template/CMakeLists.txt +++ b/template/CMakeLists.txt @@ -1,4 +1,3 @@ -install(FILES kicad.pro +install(FILES kicad.pro fp_global_table DESTINATION ${KICAD_TEMPLATE} COMPONENT resources) - From 24da541747a147f4e6a591f14e95d9ae3680babf Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Sun, 8 Sep 2013 14:31:21 -0400 Subject: [PATCH 16/29] Convert footprint definitions from wxString to FPID. * Use FPID instead of wxString in MODULE object. * Use FPID instead of wxString when loading and saving files. * Use FPID in COMPONENT object. * Add wxString helper functions and comparison operators to FPID. * Add fp_lib token to pcb and netlist file formats. * Add code to load and save FPIDs to pcb file format. * Fix segfault when deleting invalid footprint library tables in Pcbnew in non footprint library table build. * Fix bug when counting the number of mod files in EDA_APP::SetFootprintLibTablePath(); --- common/edaappl.cpp | 4 +- common/fpid.cpp | 30 +++++++++ common/netlist.keywords | 1 + common/pcb.keywords | 1 + cvpcb/autosel.cpp | 2 +- cvpcb/cvframe.cpp | 19 +++--- cvpcb/readwrite_dlgs.cpp | 10 +-- include/fpid.h | 8 +++ pcbnew/build_BOM_from_board.cpp | 11 ++-- pcbnew/class_board.cpp | 18 ++--- pcbnew/class_module.cpp | 6 +- pcbnew/class_module.h | 8 ++- .../dialog_edit_module_for_Modedit.cpp | 4 +- .../dialog_global_modules_fields_edition.cpp | 4 +- pcbnew/eagle_plugin.cpp | 2 +- pcbnew/export_gencad.cpp | 9 ++- pcbnew/gen_modules_placefile.cpp | 5 +- pcbnew/globaleditpad.cpp | 4 +- pcbnew/kicad_netlist_reader.cpp | 13 +++- pcbnew/kicad_plugin.cpp | 12 +++- pcbnew/legacy_netlist_reader.cpp | 5 +- pcbnew/legacy_plugin.cpp | 38 ++++++----- pcbnew/librairi.cpp | 12 ++-- pcbnew/modview.cpp | 3 +- pcbnew/modview_frame.cpp | 8 +-- pcbnew/muonde.cpp | 2 +- pcbnew/netlist.cpp | 65 +++++++++---------- pcbnew/netlist_reader.cpp | 24 +++---- pcbnew/netlist_reader.h | 37 ++++------- pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp | 2 +- pcbnew/pcb_parser.cpp | 9 ++- pcbnew/pcbframe.cpp | 3 + pcbnew/specctra_export.cpp | 2 +- pcbnew/xchgmod.cpp | 45 ++++++------- 34 files changed, 248 insertions(+), 178 deletions(-) diff --git a/common/edaappl.cpp b/common/edaappl.cpp index 706b6f70c9..cb3c15042c 100644 --- a/common/edaappl.cpp +++ b/common/edaappl.cpp @@ -619,7 +619,7 @@ void EDA_APP::SetDefaultSearchPaths( void ) } } -#if 1 && defined( DEBUG ) +#if 0 && defined( DEBUG ) wxLogDebug( wxT( "Library search paths:" ) ); for( unsigned i = 0; i < m_libSearchPaths.GetCount(); i++ ) @@ -1188,7 +1188,7 @@ bool EDA_APP::SetFootprintLibTablePath() for( unsigned i = 0; i < GetLibraryPathList().GetCount(); i++ ) { unsigned cnt = wxDir::GetAllFiles( GetLibraryPathList()[i], &tmp, wxT( "*.mod" ), - wxDIR_DEFAULT & ~wxDIR_HIDDEN ); + wxDIR_FILES ); if( cnt > modFileCount ) { diff --git a/common/fpid.cpp b/common/fpid.cpp index 984604d3cc..a07bf4707a 100644 --- a/common/fpid.cpp +++ b/common/fpid.cpp @@ -27,6 +27,7 @@ #include #include // _() +#include // TO_UTF8() #include @@ -185,6 +186,23 @@ FPID::FPID( const std::string& aId ) throw( PARSE_ERROR ) } +FPID::FPID( const wxString& aId ) throw( PARSE_ERROR ) +{ + std::string id = TO_UTF8( aId ); + + int offset = Parse( id ); + + if( offset != -1 ) + { + THROW_PARSE_ERROR( _( "Illegal character found in FPID string" ), + wxString::FromUTF8( id.c_str() ), + id.c_str(), + 0, + offset ); + } +} + + int FPID::SetLibNickname( const std::string& aLogical ) { int offset = okLogical( aLogical ); @@ -198,6 +216,12 @@ int FPID::SetLibNickname( const std::string& aLogical ) } +int FPID::SetLibNickname( const wxString& aLogical ) +{ + return SetLibNickname( std::string( TO_UTF8( aLogical ) ) ); +} + + int FPID::SetFootprintName( const std::string& aFootprintName ) { int separation = int( aFootprintName.find_first_of( "/" ) ); @@ -216,6 +240,12 @@ int FPID::SetFootprintName( const std::string& aFootprintName ) } +int FPID::SetFootprintName( const wxString& aFootprintName ) +{ + return SetFootprintName( std::string( TO_UTF8( aFootprintName ) ) ); +} + + int FPID::SetRevision( const std::string& aRevision ) { int offset = okRevision( aRevision ); diff --git a/common/netlist.keywords b/common/netlist.keywords index 2132e6b974..9f2932e190 100644 --- a/common/netlist.keywords +++ b/common/netlist.keywords @@ -12,6 +12,7 @@ fields footprint footprints fp +fp_lib lib libpart libparts diff --git a/common/pcb.keywords b/common/pcb.keywords index 0126f5602e..2e19147bdb 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -72,6 +72,7 @@ font fp_arc fp_circle fp_curve +fp_lib fp_line fp_poly fp_text diff --git a/cvpcb/autosel.cpp b/cvpcb/autosel.cpp index cddee0ba77..7079a280ba 100644 --- a/cvpcb/autosel.cpp +++ b/cvpcb/autosel.cpp @@ -165,7 +165,7 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) bool found = false; m_ListCmp->SetSelection( ii++, true ); - if( !component->GetFootprintName().IsEmpty() ) + if( !component->GetFPID().empty() ) continue; BOOST_FOREACH( FOOTPRINT_ALIAS& alias, aliases ) diff --git a/cvpcb/cvframe.cpp b/cvpcb/cvframe.cpp index 750e2d9924..6a17bdbc6b 100644 --- a/cvpcb/cvframe.cpp +++ b/cvpcb/cvframe.cpp @@ -342,7 +342,7 @@ void CVPCB_MAINFRAME::ToFirstNA( wxCommandEvent& event ) for( unsigned jj = selection+1; jj < m_netlist.GetCount(); jj++ ) { - if( m_netlist.GetComponent( jj )->GetFootprintName().IsEmpty() ) + if( m_netlist.GetComponent( jj )->GetFPID().empty() ) { m_ListCmp->SetSelection( wxNOT_FOUND, false ); // Remove all selections m_ListCmp->SetSelection( jj ); @@ -368,7 +368,7 @@ void CVPCB_MAINFRAME::ToPreviousNA( wxCommandEvent& event ) for( int kk = selection-1; kk >= 0; kk-- ) { - if( m_netlist.GetComponent( kk )->GetFootprintName().IsEmpty() ) + if( m_netlist.GetComponent( kk )->GetFPID().empty() ) { m_ListCmp->SetSelection( wxNOT_FOUND, false ); // Remove all selections m_ListCmp->SetSelection( kk ); @@ -405,7 +405,9 @@ void CVPCB_MAINFRAME::DelAssociations( wxCommandEvent& event ) for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { - m_netlist.GetComponent( i )->SetFootprintName( wxEmptyString ); + FPID fpid; + + m_netlist.GetComponent( i )->SetFPID( fpid ); SetNewPkg( wxEmptyString ); } @@ -521,7 +523,7 @@ void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event ) // selected footprint. if( FindFocus() == m_ListCmp || FindFocus() == m_LibraryList ) { - wxString module = component->GetFootprintName(); + wxString module = FROM_UTF8( component->GetFPID().GetFootprintName().c_str() ); bool found = false; @@ -781,8 +783,8 @@ int CVPCB_MAINFRAME::ReadSchematicNetlist() // not the actual name of the footprint. for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ ) { - if( m_netlist.GetComponent( ii )->GetFootprintName() == wxT( "$noname" ) ) - m_netlist.GetComponent( ii )->SetFootprintName( wxEmptyString ); + if( m_netlist.GetComponent( ii )->GetFPID().GetFootprintName() == std::string( "$noname" ) ) + m_netlist.GetComponent( ii )->SetFPID( FPID( wxEmptyString ) ); } // Sort components by reference: @@ -832,8 +834,7 @@ bool CVPCB_MAINFRAME::WriteComponentLinkFile( const wxString& aFullFileName ) retval |= fprintf( outputFile, "TimeStamp = %s;\n", TO_UTF8( component->GetTimeStamp() ) ); retval |= fprintf( outputFile, "Reference = %s;\n", TO_UTF8( component->GetReference() ) ); retval |= fprintf( outputFile, "ValeurCmp = %s;\n", TO_UTF8( component->GetValue() ) ); - retval |= fprintf( outputFile, "IdModule = %s;\n", - TO_UTF8( component->GetFootprintName() ) ); + retval |= fprintf( outputFile, "IdModule = %s;\n", component->GetFPID().Format().c_str() ); retval |= fprintf( outputFile, "EndCmp\n" ); } @@ -908,7 +909,7 @@ void CVPCB_MAINFRAME::BuildCmpListBox() msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_ListCmp->m_ComponentList.Add( msg ); } diff --git a/cvpcb/readwrite_dlgs.cpp b/cvpcb/readwrite_dlgs.cpp index 3780dfd46a..cb239ce3ff 100644 --- a/cvpcb/readwrite_dlgs.cpp +++ b/cvpcb/readwrite_dlgs.cpp @@ -71,16 +71,16 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) // Check to see if the component has already a footprint set. - hasFootprint = !(component->GetFootprintName().IsEmpty()); + hasFootprint = !component->GetFPID().empty(); - component->SetFootprintName( aFootprintName ); + component->SetFPID( FPID( aFootprintName ) ); // create the new component description description.Printf( CMP_FORMAT, componentIndex + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); // If the component hasn't had a footprint associated with it // it now has, so we decrement the count of components without @@ -136,10 +136,10 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_ListCmp->AppendLine( msg ); - if( component->GetFootprintName().IsEmpty() ) + if( component->GetFPID().empty() ) m_undefinedComponentCnt += 1; } diff --git a/include/fpid.h b/include/fpid.h index acb53df5b9..bd0be419a6 100644 --- a/include/fpid.h +++ b/include/fpid.h @@ -70,6 +70,8 @@ public: */ FPID( const std::string& aId ) throw( PARSE_ERROR ); + FPID( const wxString& aId ) throw( PARSE_ERROR ); + /** * Function Parse * [re-]stuffs this FPID with the information from @a aId. @@ -98,6 +100,8 @@ public: */ int SetLibNickname( const std::string& aNickname ); + int SetLibNickname( const wxString& aNickname ); + /** * Function GetFootprintName * returns the footprint name, i.e. footprintName. @@ -110,6 +114,8 @@ public: */ int SetFootprintName( const std::string& aFootprintName ); + int SetFootprintName( const wxString& aFootprintName ); + int SetRevision( const std::string& aRevision ); const std::string& GetRevision() const { return revision; } @@ -175,7 +181,9 @@ public: int compare( const FPID& aFPID ) const; bool operator <( const FPID& aFPID ) const { return this->compare( aFPID ) < 0; } + bool operator >( const FPID& aFPID ) const { return this->compare( aFPID ) > 0; } bool operator ==( const FPID& aFPID ) const { return this->compare( aFPID ) == 0; } + bool operator !=( const FPID& aFPID ) const { return !(*this == aFPID); } #if defined(DEBUG) static void Test(); diff --git a/pcbnew/build_BOM_from_board.cpp b/pcbnew/build_BOM_from_board.cpp index 66bbd9718d..65f1e57d2c 100644 --- a/pcbnew/build_BOM_from_board.cpp +++ b/pcbnew/build_BOM_from_board.cpp @@ -41,7 +41,7 @@ class cmp public: wxString m_Ref; wxString m_Val; - wxString m_Pkg; + FPID m_fpid; int m_Id; int m_CmpCount; }; @@ -99,7 +99,8 @@ void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent ) CmpList list; cmp* comp = NULL; CmpList::iterator iter; - int i = 1; + int i = 1; + while( Module != NULL ) { bool valExist = false; @@ -109,7 +110,7 @@ void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent ) { cmp* current = *iter; - if( (current->m_Val == Module->GetValue()) && (current->m_Pkg == Module->GetLibRef()) ) + if( (current->m_Val == Module->GetValue()) && (current->m_fpid == Module->GetFPID()) ) { current->m_Ref.Append( wxT( ", " ), 1 ); current->m_Ref.Append( Module->GetReference() ); @@ -127,7 +128,7 @@ void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent ) comp->m_Id = i++; comp->m_Val = Module->GetValue(); comp->m_Ref = Module->GetReference(); - comp->m_Pkg = Module->GetLibRef(); + comp->m_fpid = Module->GetFPID(); comp->m_CmpCount = 1; list.Append( comp ); } @@ -145,7 +146,7 @@ void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent ) msg << current->m_Id << wxT( ";\"" ); msg << current->m_Ref << wxT( "\";\"" ); - msg << current->m_Pkg << wxT( "\";" ); + msg << FROM_UTF8( current->m_fpid.Format().c_str() ) << wxT( "\";" ); msg << current->m_CmpCount << wxT( ";\"" ); msg << current->m_Val << wxT( "\";;;\n" ); fprintf( FichBom, "%s", TO_UTF8( msg ) ); diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 46ea086b93..a3f47416c3 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -2374,7 +2374,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, msg.Printf( _( "Checking netlist component footprint \"%s:%s:%s\".\n" ), GetChars( component->GetReference() ), GetChars( component->GetTimeStamp() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); aReporter->Report( msg ); } @@ -2392,7 +2392,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, msg.Printf( _( "Adding new component \"%s:%s\" footprint \"%s\".\n" ), GetChars( component->GetReference() ), GetChars( component->GetTimeStamp() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); if( aReporter->ReportWarnings() ) aReporter->Report( msg ); @@ -2403,7 +2403,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, "footprint \"%s\".\n" ), GetChars( component->GetReference() ), GetChars( component->GetTimeStamp() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); if( aReporter->ReportErrors() ) aReporter->Report( msg ); @@ -2423,8 +2423,8 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, else // An existing footprint. { // Test for footprint change. - if( !component->GetFootprintName().IsEmpty() && - footprint->GetLibRef() != component->GetFootprintName() ) + if( !component->GetFPID().empty() && + footprint->GetFPID() != component->GetFPID() ) { if( aNetlist.GetReplaceFootprints() ) { @@ -2436,8 +2436,8 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, "\"%s\".\n" ), GetChars( footprint->GetReference() ), GetChars( footprint->GetPath() ), - GetChars( footprint->GetLibRef() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( footprint->GetFPID().Format().c_str() ) ), + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); if( aReporter->ReportWarnings() ) aReporter->Report( msg ); @@ -2448,7 +2448,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, "footprint \"%s\".\n" ), GetChars( footprint->GetReference() ), GetChars( footprint->GetPath() ), - GetChars( component->GetFootprintName() ) ); + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); if( aReporter->ReportErrors() ) aReporter->Report( msg ); @@ -2679,7 +2679,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, msg.Printf( _( "** Error: Component \"%s\" pad <%s> not found in footprint \"%s\" **\n" ), GetChars( component->GetReference() ), GetChars( padname ), - GetChars( footprint->GetLibRef() ) ); + footprint->GetFPID().Format().c_str() ); aReporter->Report( msg ); } } diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index f5b29906a6..aef466c887 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -86,7 +86,7 @@ MODULE::MODULE( const MODULE& aModule ) : BOARD_ITEM( aModule ) { m_Pos = aModule.m_Pos; - m_LibRef = aModule.m_LibRef; + m_fpid = aModule.m_fpid; m_Layer = aModule.m_Layer; m_Attributs = aModule.m_Attributs; m_ModuleStatus = aModule.m_ModuleStatus; @@ -201,7 +201,7 @@ void MODULE::Copy( MODULE* aModule ) { m_Pos = aModule->m_Pos; m_Layer = aModule->m_Layer; - m_LibRef = aModule->m_LibRef; + m_fpid = aModule->m_fpid; m_Attributs = aModule->m_Attributs; m_ModuleStatus = aModule->m_ModuleStatus; m_Orient = aModule->m_Orient; @@ -524,7 +524,7 @@ void MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) } aList.push_back( MSG_PANEL_ITEM( _( "Attrib" ), msg, BROWN ) ); - aList.push_back( MSG_PANEL_ITEM( _( "Module" ), m_LibRef, BLUE ) ); + aList.push_back( MSG_PANEL_ITEM( _( "Module" ), FROM_UTF8( m_fpid.Format().c_str() ), BLUE ) ); msg = _( "No 3D shape" ); // Search the first active 3D shape in list diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 9730bd7caf..ad83e94f8c 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -35,11 +35,13 @@ #include #include // ALL_LAYERS definition. #include +#include #include #include #include "zones.h" + class LINE_READER; class EDA_3D_CANVAS; class S3D_MASTER; @@ -117,8 +119,8 @@ public: void SetOrientation( double newangle ); double GetOrientation() const { return m_Orient; } - const wxString& GetLibRef() const { return m_LibRef; } - void SetLibRef( const wxString& aLibRef ) { m_LibRef = aLibRef; } + const FPID& GetFPID() const { return m_fpid; } + void SetFPID( const FPID& aFPID ) { m_fpid = aFPID; } const wxString& GetDescription() const { return m_Doc; } void SetDescription( const wxString& aDoc ) { m_Doc = aDoc; } @@ -509,7 +511,7 @@ private: wxPoint m_Pos; ///< Position of module on the board in internal units. TEXTE_MODULE* m_Reference; ///< Component reference designator value (U34, R18..) TEXTE_MODULE* m_Value; ///< Component value (74LS00, 22K..) - wxString m_LibRef; ///< Name of the module in the library. + FPID m_fpid; ///< The #FPID of the MODULE. int m_Attributs; ///< Flag bits ( see Mod_Attribut ) int m_ModuleStatus; ///< For autoplace: flags (LOCKED, AUTOPLACED) EDA_RECT m_BoundaryBox; ///< Bounding box : coordinates on board, real orientation. diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp index f69176f329..364106624a 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp @@ -114,7 +114,7 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties() m_ReferenceCtrl->SetValue( m_referenceCopy->GetText() ); m_ValueCtrl->SetValue( m_valueCopy->GetText() ); m_ValueCtrl->SetValue( m_valueCopy->GetText() ); - m_FootprintNameCtrl->SetValue( m_currentModule->GetLibRef() ); + m_FootprintNameCtrl->SetValue( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ); m_AttributsCtrl->SetItemToolTip( 0, _( "Use this attribute for most non SMD components" ) ); m_AttributsCtrl->SetItemToolTip( 1, @@ -396,7 +396,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) // Init footprint name in library if( ! footprintName.IsEmpty() ) - m_currentModule->SetLibRef( footprintName ); + m_currentModule->SetFPID( FPID( footprintName ) ); // Init Fields: m_currentModule->Reference().Copy( m_referenceCopy ); diff --git a/pcbnew/dialogs/dialog_global_modules_fields_edition.cpp b/pcbnew/dialogs/dialog_global_modules_fields_edition.cpp index aa8f2c9186..63b4df2308 100644 --- a/pcbnew/dialogs/dialog_global_modules_fields_edition.cpp +++ b/pcbnew/dialogs/dialog_global_modules_fields_edition.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -156,7 +157,8 @@ void PCB_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef, if( ! aFilter.IsEmpty() ) { - if( ! WildCompareString( aFilter, module->GetLibRef(), false ) ) + if( ! WildCompareString( aFilter, FROM_UTF8( module->GetFPID().Format().c_str() ), + false ) ) continue; } diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index 00df1c0879..398967ea43 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -1866,7 +1866,7 @@ MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName { std::auto_ptr m( new MODULE( NULL ) ); - m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) ); + m->SetFPID( FPID( aPkgName ) ); opt_string description = aPackage.get_optional( "description" ); if( description ) diff --git a/pcbnew/export_gencad.cpp b/pcbnew/export_gencad.cpp index 59cecd1869..f04496ff7c 100644 --- a/pcbnew/export_gencad.cpp +++ b/pcbnew/export_gencad.cpp @@ -861,14 +861,17 @@ static void CreateDevicesSection( FILE* aFile, BOARD* aPcb ) { fprintf( aFile, "DEVICE \"%s\"\n", TO_UTF8( module->GetReference() ) ); fprintf( aFile, "PART \"%s\"\n", TO_UTF8( module->GetValue() ) ); - fprintf( aFile, "PACKAGE \"%s\"\n", TO_UTF8( module->GetLibRef() ) ); + fprintf( aFile, "PACKAGE \"%s\"\n", module->GetFPID().Format().c_str() ); // The TYPE attribute is almost freeform const char* ty = "TH"; + if( module->GetAttributes() & MOD_CMS ) ty = "SMD"; + if( module->GetAttributes() & MOD_VIRTUAL ) ty = "VIRTUAL"; + fprintf( aFile, "TYPE %s\n", ty ); } @@ -895,8 +898,8 @@ static void CreateBoardSection( FILE* aFile, BOARD* aPcb ) { // XXX GenCAD supports arc boundaries but I've seen nothing that reads them fprintf( aFile, "LINE %g %g %g %g\n", - MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ), - MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) ); + MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ), + MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) ); } } } diff --git a/pcbnew/gen_modules_placefile.cpp b/pcbnew/gen_modules_placefile.cpp index 32503e63a0..bc15b16140 100644 --- a/pcbnew/gen_modules_placefile.cpp +++ b/pcbnew/gen_modules_placefile.cpp @@ -472,7 +472,7 @@ int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName, wxPoint module_pos; const wxString& ref = list[ii].m_Reference; const wxString& val = list[ii].m_Value; - const wxString& pkg = list[ii].m_Module->GetLibRef(); + const wxString& pkg = FROM_UTF8( list[ii].m_Module->GetFPID().Format().c_str() ); sprintf( line, "%-8.8s %-16.16s %-16.16s", TO_UTF8( ref ), TO_UTF8( val ), TO_UTF8( pkg ) ); @@ -614,7 +614,8 @@ bool PCB_EDIT_FRAME::DoGenFootprintsReport( const wxString& aFullFilename, bool fputs( line, rptfile ); sprintf( line, "value %s\n", EscapedUTF8( Module->GetValue() ).c_str() ); fputs( line, rptfile ); - sprintf( line, "footprint %s\n", EscapedUTF8( Module->GetLibRef() ).c_str() ); + sprintf( line, "footprint %s\n", + EscapedUTF8( FROM_UTF8( Module->GetFPID().Format().c_str() ) ).c_str() ); fputs( line, rptfile ); msg = wxT( "attribut" ); diff --git a/pcbnew/globaleditpad.cpp b/pcbnew/globaleditpad.cpp index a3c9796363..01719f9ff4 100644 --- a/pcbnew/globaleditpad.cpp +++ b/pcbnew/globaleditpad.cpp @@ -241,7 +241,7 @@ void PCB_BASE_FRAME::GlobalChange_PadSettings( D_PAD* aPad, if( !aSameFootprints && (module != Module_Ref) ) continue; - if( module->GetLibRef() != Module_Ref->GetLibRef() ) + if( module->GetFPID() != Module_Ref->GetFPID() ) continue; bool saveMe = false; @@ -280,7 +280,7 @@ void PCB_BASE_FRAME::GlobalChange_PadSettings( D_PAD* aPad, if( !aSameFootprints && (module != Module_Ref) ) continue; - if( module->GetLibRef() != Module_Ref->GetLibRef() ) + if( module->GetFPID() != Module_Ref->GetFPID() ) continue; // Erase module on screen diff --git a/pcbnew/kicad_netlist_reader.cpp b/pcbnew/kicad_netlist_reader.cpp index 6cdd613810..912c13cba2 100644 --- a/pcbnew/kicad_netlist_reader.cpp +++ b/pcbnew/kicad_netlist_reader.cpp @@ -284,6 +284,7 @@ void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR ) wxString ref; wxString value; wxString footprintName; + wxString footprintLib; wxString library; wxString name; wxString pathtimestamp, timestamp; @@ -314,6 +315,12 @@ void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR ) NeedRIGHT(); break; + case T_fp_lib: + NeedSYMBOLorNUMBER(); + footprintLib = FROM_UTF8( CurText() ); + NeedRIGHT(); + break; + case T_libsource: // Read libsource while( (token = NextTok()) != T_RIGHT ) @@ -361,8 +368,12 @@ void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR ) } } + FPID fpid; + + fpid.SetFootprintName( footprintName ); + fpid.SetLibNickname( footprintName ); pathtimestamp += timestamp; - COMPONENT* component = new COMPONENT( footprintName, ref, value, pathtimestamp ); + COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp ); component->SetName( name ); component->SetLibrary( library ); m_netlist->AddComponent( component ); diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 847571940c..4e26452b3b 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -868,7 +868,8 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const } } - m_out->Print( aNestLevel, "(module %s", m_out->Quotew( aModule->GetLibRef() ).c_str() ); + m_out->Print( aNestLevel, "(module %s", + m_out->Quotes( aModule->GetFPID().GetFootprintName() ).c_str() ); if( aModule->IsLocked() ) m_out->Print( 0, " locked" ); @@ -876,6 +877,10 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const if( aModule->IsPlaced() ) m_out->Print( 0, " placed" ); + if( !aModule->GetFPID().IsLegacy() ) + m_out->Print( 0, " (fp_lib %s)", + m_out->Quotes( aModule->GetFPID().GetLibNickname() ).c_str() ); + formatLayer( aModule ); if( !( m_ctl & CTL_OMIT_TSTAMPS ) ) @@ -1664,12 +1669,13 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri aLibraryPath.GetData() ) ); } - std::string footprintName = TO_UTF8( aFootprint->GetLibRef() ); + std::string footprintName = aFootprint->GetFPID().GetFootprintName(); MODULE_MAP& mods = m_cache->GetModules(); // Quietly overwrite module and delete module file from path for any by same name. - wxFileName fn( aLibraryPath, aFootprint->GetLibRef(), KiCadFootprintFileExtension ); + wxFileName fn( aLibraryPath, FROM_UTF8( aFootprint->GetFPID().GetFootprintName().c_str() ), + KiCadFootprintFileExtension ); if( !fn.IsOk() ) { diff --git a/pcbnew/legacy_netlist_reader.cpp b/pcbnew/legacy_netlist_reader.cpp index 364959a904..6b415bcf82 100644 --- a/pcbnew/legacy_netlist_reader.cpp +++ b/pcbnew/legacy_netlist_reader.cpp @@ -165,7 +165,10 @@ COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText ) throw( PARSE_ERRO name = FROM_UTF8( text ).AfterFirst( wxChar( '=' ) ).BeforeLast( wxChar( '}' ) ); } - COMPONENT* component = new COMPONENT( footprintName, reference, value, timeStamp ); + FPID fpid; + + fpid.SetFootprintName( footprintName ); + COMPONENT* component = new COMPONENT( fpid, reference, value, timeStamp ); component->SetName( name ); m_netlist->AddComponent( component ); return component; diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index abe600d41b..c03dacbf76 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -278,7 +278,8 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) { auto_ptr module( new MODULE( m_board ) ); - module->SetLibRef( FROM_UTF8( StrPurge( line + SZ( "$MODULE" ) ) ) ); + std::string fpName = StrPurge( line + SZ( "$MODULE" ) ); + module->SetFPID( FPID( fpName ) ); LoadMODULE( module.get() ); m_board->Add( module.release(), ADD_APPEND ); @@ -1001,7 +1002,7 @@ void LEGACY_PLUGIN::LoadMODULE( MODULE* aModule ) { // There can be whitespace in the footprint name on some old libraries. // Grab everything after "Li" up to end of line: - //aModule->SetLibRef( FROM_UTF8( StrPurge( line + SZ( "Li" ) ) ) ); + //aModule->SetFPID( FROM_UTF8( StrPurge( line + SZ( "Li" ) ) ) ); } */ @@ -1130,9 +1131,8 @@ void LEGACY_PLUGIN::LoadMODULE( MODULE* aModule ) } } - wxString msg = wxString::Format( - wxT( "Missing '$EndMODULE' for MODULE '%s'" ), - GetChars( aModule->GetLibRef() ) ); + wxString msg = wxString::Format( wxT( "Missing '$EndMODULE' for MODULE '%s'" ), + aModule->GetFPID().GetFootprintName().c_str() ); THROW_IO_ERROR( msg ); } @@ -1183,10 +1183,10 @@ void LEGACY_PLUGIN::loadPAD( MODULE* aModule ) case 'T': padshape = PAD_TRAPEZOID; break; default: m_error.Printf( _( "Unknown padshape '%c=0x%02x' on line:%d of module:'%s'" ), - padchar, - padchar, - m_reader->LineNumber(), - GetChars( aModule->GetLibRef() ) + padchar, + padchar, + m_reader->LineNumber(), + aModule->GetFPID().GetFootprintName().c_str() ); THROW_IO_ERROR( m_error ); } @@ -1387,7 +1387,7 @@ void LEGACY_PLUGIN::loadMODULE_EDGE( MODULE* aModule ) (unsigned char) line[1], (unsigned char) line[1], m_reader->LineNumber(), - GetChars( aModule->GetLibRef() ) + aModule->GetFPID().GetFootprintName().c_str() ); THROW_IO_ERROR( m_error ); } @@ -3399,7 +3399,9 @@ void LEGACY_PLUGIN::SaveMODULE( const MODULE* me ) const char statusTxt[3]; double orient = me->GetOrientation(); - fprintf( m_fp, "$MODULE %s\n", TO_UTF8( me->GetLibRef() ) ); + // Do not save full FPID. Only the footprint name. The legacy file format should + // never support FPIDs. + fprintf( m_fp, "$MODULE %s\n", me->GetFPID().GetFootprintName().c_str() ); statusTxt[0] = me->IsLocked() ? 'F' : '~'; statusTxt[1] = me->IsPlaced() ? 'P' : '~'; @@ -3413,7 +3415,7 @@ void LEGACY_PLUGIN::SaveMODULE( const MODULE* me ) const me->GetTimeStamp(), statusTxt ); - fprintf( m_fp, "Li %s\n", TO_UTF8( me->GetLibRef() ) ); + fprintf( m_fp, "Li %s\n", me->GetFPID().GetFootprintName().c_str() ); if( !me->GetDescription().IsEmpty() ) { @@ -3490,7 +3492,7 @@ void LEGACY_PLUGIN::SaveMODULE( const MODULE* me ) const SaveModule3D( me ); - fprintf( m_fp, "$EndMODULE %s\n", TO_UTF8( me->GetLibRef() ) ); + fprintf( m_fp, "$EndMODULE %s\n", me->GetFPID().GetFootprintName().c_str() ); CHECK_WRITE_ERROR(); } @@ -4037,7 +4039,7 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader ) std::string footprintName = StrPurge( line + SZ( "$MODULE" ) ); // set the footprint name first thing, so exceptions can use name. - module->SetLibRef( FROM_UTF8( footprintName.c_str() ) ); + module->SetFPID( FPID( footprintName ) ); #if 0 && defined( DEBUG ) printf( "%s\n", footprintName.c_str() ); @@ -4052,7 +4054,9 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader ) MODULE* m = module.release(); // exceptions after this are not expected. - wxASSERT( footprintName == TO_UTF8( m->GetLibRef() ) ); + // Not sure why this is asserting on debug builds. The debugger shows the + // strings are the same. If it's not really needed maybe it can be removed. +// wxASSERT( footprintName == m->GetFPID().GetFootprintName() ); /* @@ -4099,7 +4103,7 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader ) { nameOK = true; - m->SetLibRef( FROM_UTF8( newName.c_str() ) ); + m->SetFPID( FPID( newName ) ); std::pair r = m_modules.insert( newName, m ); wxASSERT_MSG( r.second, wxT( "error doing cache insert using guaranteed unique name" ) ); @@ -4278,7 +4282,7 @@ void LEGACY_PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* a THROW_IO_ERROR( wxString::Format( _( "Library <%s> is read only" ), aLibraryPath.GetData() ) ); } - std::string footprintName = TO_UTF8( aFootprint->GetLibRef() ); + std::string footprintName = aFootprint->GetFPID().GetFootprintName(); MODULE_MAP& mods = m_cache->m_modules; diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index fb0752d45a..d7b5889e5a 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -284,7 +284,7 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule ) if( aModule == NULL ) return; - fn.SetName( aModule->GetLibRef() ); + fn.SetName( FROM_UTF8( aModule->GetFPID().GetFootprintName().c_str() ) ); wxString wildcard = wxGetTranslation( KiCadFootprintLibFileWildcard ); @@ -600,7 +600,7 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, SetMsgPanel( aModule ); // Ask what to use as the footprint name in the library - wxString footprintName = aModule->GetLibRef(); + wxString footprintName = FROM_UTF8( aModule->GetFPID().GetFootprintName().c_str() ); if( aDisplayDialog ) { @@ -624,17 +624,17 @@ bool PCB_BASE_FRAME::Save_Module_In_Library( const wxString& aLibPath, GetChars( footprintName ) ); DisplayError( NULL, msg ); - return false; + return false; } - aModule->SetLibRef( footprintName ); + aModule->SetFPID( FPID( footprintName ) ); } // Ensure this footprint has a libname if( footprintName.IsEmpty() ) { footprintName = wxT("noname"); - aModule->SetLibRef( footprintName ); + aModule->SetFPID( footprintName ); } IO_MGR::PCB_FILE_T pluginType = IO_MGR::GuessPluginTypeFromLibPath( aLibPath ); @@ -730,7 +730,7 @@ MODULE* PCB_BASE_FRAME::Create_1_Module( const wxString& aModuleName ) module->SetLastEditTime(); // Update its name in lib - module->SetLibRef( moduleName ); + module->SetFPID( FPID( moduleName ) ); // Update reference: module->SetReference( moduleName ); diff --git a/pcbnew/modview.cpp b/pcbnew/modview.cpp index 2fb378ef84..180148c123 100644 --- a/pcbnew/modview.cpp +++ b/pcbnew/modview.cpp @@ -33,6 +33,7 @@ #include #include <3d_viewer.h> #include +#include #include #include @@ -160,7 +161,7 @@ void FOOTPRINT_VIEWER_FRAME::SelectCurrentFootprint( wxCommandEvent& event ) delete oldmodule; } - m_footprintName = module->GetLibRef(); + m_footprintName = FROM_UTF8( module->GetFPID().GetFootprintName().c_str() ); module->ClearFlags(); SetCurItem( NULL ); diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index b002ea82d6..4014e1011d 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -209,8 +209,8 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent, GetBoard()->Add( footprint, ADD_APPEND ); #else FPID id; - id.SetLibNickname( TO_UTF8( m_libraryName ) ); - id.SetFootprintName( TO_UTF8( m_footprintName ) ); + id.SetLibNickname( m_libraryName ); + id.SetFootprintName( m_footprintName ); GetBoard()->Add( loadFootprint( id ) ); #endif } @@ -504,8 +504,8 @@ void FOOTPRINT_VIEWER_FRAME::ClickOnFootprintList( wxCommandEvent& event ) GetBoard()->Add( footprint, ADD_APPEND ); #else FPID id; - id.SetLibNickname( TO_UTF8( m_libraryName ) ); - id.SetFootprintName( TO_UTF8( m_footprintName ) ); + id.SetLibNickname( m_libraryName ); + id.SetFootprintName( m_footprintName ); try { diff --git a/pcbnew/muonde.cpp b/pcbnew/muonde.cpp index 6bf21028c7..39e9f6c90e 100644 --- a/pcbnew/muonde.cpp +++ b/pcbnew/muonde.cpp @@ -235,7 +235,7 @@ MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC ) return NULL; // here the module is already in the BOARD, Create_1_Module() does that. - module->SetLibRef( wxT( "MuSelf" ) ); + module->SetFPID( FPID( std::string( "MuSelf" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( Mself.m_End ); diff --git a/pcbnew/netlist.cpp b/pcbnew/netlist.cpp index d0a80154e5..1f8fe80b29 100644 --- a/pcbnew/netlist.cpp +++ b/pcbnew/netlist.cpp @@ -167,21 +167,20 @@ MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName() void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) throw( IO_ERROR, PARSE_ERROR ) { - wxString msg; - wxString lastFootprintLibName; - wxArrayString nofoundFootprints; // A list of footprints used in netlist - // but not found in any library - // to avoid a full search in all libs - // each time a non existent footprint is needed + wxString msg; + FPID lastFPID; + std::vector< FPID > nofoundFootprints; // A list of footprints used in netlist + // but not found in any library + // to avoid a full search in all libs + // each time a non existent footprint is needed COMPONENT* component; MODULE* module = 0; MODULE* fpOnBoard; - if( aNetlist.IsEmpty() ) return; - aNetlist.SortByFootprintName(); + aNetlist.SortByFPID(); wxString libPath; wxFileName fn; @@ -192,7 +191,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) { component = aNetlist.GetComponent( ii ); - if( component->GetFootprintName().IsEmpty() ) + if( component->GetFPID().empty() ) { if( aReporter ) { @@ -212,7 +211,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) fpOnBoard = m_Pcb->FindModule( aNetlist.GetComponent( ii )->GetReference() ); bool footprintMisMatch = fpOnBoard && - fpOnBoard->GetLibRef() != component->GetFootprintName(); + fpOnBoard->GetFPID() != component->GetFPID(); if( footprintMisMatch && !aNetlist.GetReplaceFootprints() ) { @@ -220,8 +219,8 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) { msg.Printf( _( "* Warning: component `%s` has footprint <%s> and should be <%s>\n" ), GetChars( component->GetReference() ), - GetChars( fpOnBoard->GetLibRef() ), - GetChars( component->GetFootprintName() ) ); + fpOnBoard->GetFPID().Format().c_str(), + component->GetFPID().GetFootprintName().c_str() ); aReporter->Report( msg ); } @@ -233,7 +232,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) bool loadFootprint = (fpOnBoard == NULL) || footprintMisMatch; - if( loadFootprint && (component->GetFootprintName() != lastFootprintLibName) ) + if( loadFootprint && (component->GetFPID() != lastFPID) ) { module = NULL; @@ -242,9 +241,10 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) // So it should be made only once. // Therefore search in not found list first: bool alreadySearched = false; - for( unsigned ii = 0; ii < nofoundFootprints.GetCount(); ii++ ) + + for( unsigned ii = 0; ii < nofoundFootprints.size(); ii++ ) { - if( component->GetFootprintName() == nofoundFootprints[ii] ) + if( component->GetFPID() == nofoundFootprints[ii] ) { alreadySearched = true; break; @@ -274,11 +274,12 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) continue; } - module = pi->FootprintLoad( libPath, component->GetFootprintName() ); + module = pi->FootprintLoad( libPath, + FROM_UTF8( component->GetFPID().GetFootprintName().c_str() ) ); if( module ) { - lastFootprintLibName = component->GetFootprintName(); + lastFPID = component->GetFPID(); break; } } @@ -290,11 +291,11 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) msg.Printf( _( "*** Warning: component `%s` footprint <%s> was not found in " "any libraries. ***\n" ), GetChars( component->GetReference() ), - GetChars( component->GetFootprintName() ) ); + component->GetFPID().GetFootprintName().c_str() ); aReporter->Report( msg ); } - nofoundFootprints.Add( component->GetFootprintName() ); + nofoundFootprints.push_back( component->GetFPID() ); continue; } @@ -319,7 +320,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) throw( IO_ERROR, PARSE_ERROR ) { wxString msg; - wxString lastFootprintLibName; + FPID lastFPID; COMPONENT* component; MODULE* module = 0; MODULE* fpOnBoard; @@ -327,13 +328,13 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) if( aNetlist.IsEmpty() || m_footprintLibTable->IsEmpty() ) return; - aNetlist.SortByFootprintName(); + aNetlist.SortByFPID(); for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ ) { component = aNetlist.GetComponent( ii ); - if( component->GetFootprintName().IsEmpty() ) + if( component->GetFPID().empty() ) { if( aReporter ) { @@ -353,7 +354,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) fpOnBoard = m_Pcb->FindModule( aNetlist.GetComponent( ii )->GetReference() ); bool footprintMisMatch = fpOnBoard && - fpOnBoard->GetLibRef() != component->GetFootprintName(); + fpOnBoard->GetFPID() != component->GetFPID(); if( footprintMisMatch && !aNetlist.GetReplaceFootprints() ) { @@ -361,8 +362,8 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) { msg.Printf( _( "* Warning: component `%s` has footprint <%s> and should be <%s>\n" ), GetChars( component->GetReference() ), - GetChars( fpOnBoard->GetLibRef() ), - GetChars( component->GetFootprintName() ) ); + fpOnBoard->GetFPID().GetFootprintName().c_str(), + component->GetFPID().GetFootprintName().c_str() ); aReporter->Report( msg ); } @@ -374,31 +375,29 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) bool loadFootprint = (fpOnBoard == NULL) || footprintMisMatch; - if( loadFootprint && (component->GetFootprintName() != lastFootprintLibName) ) + if( loadFootprint && (component->GetFPID() != lastFPID) ) { module = NULL; - FPID fpid; - - if( fpid.Parse( TO_UTF8( component->GetFootprintName() ) ) >= 0 ) + if( !component->GetFPID().IsValid() ) { if( aReporter ) { msg.Printf( _( "*** Warning: Component \"%s\" footprint ID <%s> is not " "valid. ***\n" ), GetChars( component->GetReference() ), - GetChars( component->GetFootprintName() ) ); + component->GetFPID().GetFootprintName().c_str() ); aReporter->Report( msg ); } continue; } - module = PCB_BASE_FRAME::loadFootprint( fpid ); + module = PCB_BASE_FRAME::loadFootprint( component->GetFPID() ); if( module ) { - lastFootprintLibName = component->GetFootprintName(); + lastFPID = component->GetFPID(); } if( module == NULL ) @@ -409,7 +408,7 @@ void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter ) msg.Printf( _( "*** Warning: component `%s` footprint <%s> was not found in " "any libraries in the footprint library table. ***\n" ), GetChars( component->GetReference() ), - GetChars( component->GetFootprintName() ) ); + component->GetFPID().GetFootprintName().c_str() ); aReporter->Report( msg ); } diff --git a/pcbnew/netlist_reader.cpp b/pcbnew/netlist_reader.cpp index 9f1888d798..c1b50fd79e 100644 --- a/pcbnew/netlist_reader.cpp +++ b/pcbnew/netlist_reader.cpp @@ -72,7 +72,7 @@ void COMPONENT::SetModule( MODULE* aModule ) aModule->SetReference( m_reference ); aModule->SetValue( m_value ); - aModule->SetLibRef( m_footprintName ); + aModule->SetFPID( m_fpid ); aModule->SetPath( m_timeStamp ); } @@ -116,11 +116,11 @@ void COMPONENT::Show( int aNestLevel, REPORTER& aReporter ) NestedSpace( aNestLevel, aReporter ); aReporter.Report( wxT( "\n" ) ); NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( wxString::Format( wxT( "\n" ), + aReporter.Report( wxString::Format( wxT( "\n" ), GetChars( m_reference ), GetChars( m_value ), GetChars( m_name ), GetChars( m_library ), - GetChars( m_footprintName ), GetChars( m_footprintLib ), + m_fpid.Format().c_str(), GetChars( m_timeStamp ) ) ); if( !m_footprintFilters.IsEmpty() ) @@ -198,18 +198,18 @@ COMPONENT* NETLIST::GetComponentByTimeStamp( const wxString& aTimeStamp ) /** - * Function ByFootprintName + * Function ByFPID * is a helper function used to sort the component list used by loadNewModules. */ -static bool ByFootprintName( const COMPONENT& ref, const COMPONENT& cmp ) +static bool ByFPID( const COMPONENT& ref, const COMPONENT& cmp ) { - return ref.GetFootprintName().CmpNoCase( cmp.GetFootprintName() ) > 0; + return ref.GetFPID() > cmp.GetFPID(); } -void NETLIST::SortByFootprintName() +void NETLIST::SortByFPID() { - m_components.sort( ByFootprintName ); + m_components.sort( ByFPID ); } @@ -233,7 +233,7 @@ bool NETLIST::AnyFootprintsLinked() const { for( unsigned i = 0; i < m_components.size(); i++ ) { - if( !m_components[i].GetFootprintName().IsEmpty() ) + if( !m_components[i].GetFPID().empty() ) return true; } @@ -245,7 +245,7 @@ bool NETLIST::AllFootprintsLinked() const { for( unsigned i = 0; i < m_components.size(); i++ ) { - if( m_components[i].GetFootprintName().IsEmpty() ) + if( m_components[i].GetFPID().empty() ) return false; } @@ -452,7 +452,7 @@ bool CMP_READER::Load( NETLIST* aNetlist ) throw( IO_ERROR, PARSE_ERROR ) // and still exists in footprint assignment list, before this list is updated // This is an usual case during the life of a design if( component ) - component->SetFootprintName( footprint ); + component->SetFPID( FPID( footprint ) ); else ok = false; // can be used to display a warning in Pcbnew. } diff --git a/pcbnew/netlist_reader.h b/pcbnew/netlist_reader.h index f1cbfa6632..ef8600de46 100644 --- a/pcbnew/netlist_reader.h +++ b/pcbnew/netlist_reader.h @@ -34,6 +34,7 @@ #include #include +#include #include // netlist_lexer is common to Eeschema and Pcbnew @@ -110,20 +111,12 @@ class COMPONENT wxString m_name; /** - * The name of the component library where #m_name was found. This will be set to - * wxEmptyString for legacy netlist files. + * The name of the component library where #m_name was found. */ wxString m_library; - /// The name of the footprint in the footprint library assigned to the component. - wxString m_footprintName; - - /** - * The name of the footprint library that #m_footprintName is located. This will be - * set to wxEmptyString for legacy netlist formats indicating that all libraries need - * to be searched. - */ - wxString m_footprintLib; + /// The #FPID of the footprint assigned to the component. + FPID m_fpid; /// The #MODULE loaded for #m_footprintName found in #m_footprintLib. std::auto_ptr< MODULE > m_footprint; @@ -135,12 +128,12 @@ class COMPONENT static COMPONENT_NET m_emptyNet; public: - COMPONENT( const wxString& aFootprintName, + COMPONENT( const FPID& aFPID, const wxString& aReference, const wxString& aValue, const wxString& aTimeStamp ) { - m_footprintName = aFootprintName; + m_fpid = aFPID; m_reference = aReference; m_value = aValue; m_timeStamp = aTimeStamp; @@ -172,21 +165,13 @@ public: const wxString& GetValue() const { return m_value; } - void SetFootprintName( const wxString& aFootprintName ) + void SetFPID( const FPID& aFPID ) { - m_footprintChanged = !m_footprintName.IsEmpty() && (m_footprintName != aFootprintName); - m_footprintName = aFootprintName; + m_footprintChanged = !m_fpid.empty() && (m_fpid != aFPID); + m_fpid = aFPID; } - const wxString& GetFootprintName() const { return m_footprintName; } - - void SetFootprintLib( const wxString& aFootprintLib ) - { - m_footprintChanged = !m_footprintLib.IsEmpty() && (m_footprintLib != aFootprintLib); - m_footprintLib = aFootprintLib; - } - - const wxString& GetFootprintLib() const { return m_footprintLib; } + const FPID& GetFPID() const { return m_fpid; } const wxString& GetTimeStamp() const { return m_timeStamp; } @@ -324,7 +309,7 @@ public: */ COMPONENT* GetComponentByTimeStamp( const wxString& aTimeStamp ); - void SortByFootprintName(); + void SortByFPID(); void SortByReference(); diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp index 45c8853590..a04155d5a2 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp @@ -511,7 +511,7 @@ void PCB_MODULE::AddToBoard() module->SetTimeStamp( 0 ); module->SetLastEditTime( 0 ); - module->SetLibRef( m_compRef ); + module->SetFPID( FPID( m_compRef ) ); module->SetAttributes( MOD_DEFAULT | MOD_CMS ); diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 0c4c77358e..16f2d5b6da 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1542,13 +1542,14 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR wxPoint pt; T token; + FPID fpid; auto_ptr< MODULE > module( new MODULE( m_board ) ); module->SetInitialComments( aInitialComments ); NeedSYMBOLorNUMBER(); - module->SetLibRef( FromUTF8() ); + fpid.SetFootprintName( FromUTF8() ); for( token = NextTok(); token != T_RIGHT; token = NextTok() ) { @@ -1565,6 +1566,11 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR module->SetIsPlaced( true ); break; + case T_fp_lib: + fpid.SetLibNickname( FromUTF8() ); + NeedRIGHT(); + break; + case T_layer: module->SetLayer( parseBoardItemLayer() ); NeedRIGHT(); @@ -1747,6 +1753,7 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR } } + module->SetFPID( fpid ); module->CalculateBoundingBox(); return module.release(); diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index b0e3e1c018..9bce32510e 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -487,8 +487,11 @@ PCB_EDIT_FRAME::~PCB_EDIT_FRAME() m_Macros[i].m_Record.clear(); delete m_drc; + +#if defined( USE_FP_LIB_TABLE ) delete m_footprintLibTable; delete m_globalFootprintTable; +#endif } diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index 57f063cd8d..016776698f 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -627,7 +627,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) IMAGE* image = new IMAGE(0); - image->image_id = TO_UTF8( aModule->GetLibRef() ); + image->image_id = aModule->GetFPID().Format().c_str(); // from the pads, and make an IMAGE using collated padstacks. for( int p=0; pAppendText( m_CurrentModule->GetLibRef() ); - m_NewModule->AppendText( m_CurrentModule->GetLibRef() ); + m_OldModule->AppendText( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ); + m_NewModule->AppendText( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ); m_OldValue->AppendText( m_CurrentModule->GetValue() ); m_Selection->SetSelection( s_SelectionMode ); @@ -168,8 +168,8 @@ void DIALOG_EXCHANGE_MODULE::OnSelectionClicked( wxCommandEvent& event ) * Return 1 if error */ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference, - const wxString& old_name, - const wxString& new_name, + const FPID& old_name, + const FPID& new_name, bool ShowError ) { wxFileName fn; @@ -241,7 +241,7 @@ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference, if( start_descr && strnicmp( line, "IdModule", 8 ) == 0 ) { - sprintf( line + 8, " = %s;\n", TO_UTF8( new_name ) ); + sprintf( line + 8, " = %s;\n", new_name.Format().c_str() ); msg = wxT( " * in <" ) + fn.GetFullPath() + wxT( ">.\n" ); m_WinMessages->AppendText( msg ); @@ -306,7 +306,8 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) MODULE* Module, * PtBack; bool change = false; wxString newmodulename = m_NewModule->GetValue(); - wxString value, lib_reference; + wxString value; + FPID lib_reference; bool check_module_value = false; int ShowErr = 3; // Post 3 error messages max. @@ -316,21 +317,21 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) if( newmodulename == wxEmptyString ) return; - lib_reference = m_CurrentModule->GetLibRef(); + lib_reference = m_CurrentModule->GetFPID(); if( aUseValue ) { check_module_value = true; value = m_CurrentModule->GetValue(); msg.Printf( _( "Change modules %s -> %s (for value = %s)?" ), - GetChars( m_CurrentModule->GetLibRef() ), + m_CurrentModule->GetFPID().Format().c_str(), GetChars( newmodulename ), GetChars( m_CurrentModule->GetValue() ) ); } else { msg.Printf( _( "Change modules %s -> %s ?" ), - GetChars( lib_reference ), GetChars( newmodulename ) ); + lib_reference.GetFootprintName().c_str(), GetChars( newmodulename ) ); } if( !IsOK( this, msg ) ) @@ -350,7 +351,7 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) { PtBack = Module->Back(); - if( lib_reference.CmpNoCase( Module->GetLibRef() ) != 0 ) + if( lib_reference != Module->GetFPID() ) continue; if( check_module_value ) @@ -412,7 +413,7 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleAll() { PtBack = Module->Back(); - if( Change_1_Module( Module, Module->GetLibRef(), &pickList, ShowErr ) ) + if( Change_1_Module( Module, Module->GetFPID(), &pickList, ShowErr ) ) change = true; else if( ShowErr ) ShowErr--; @@ -443,11 +444,11 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleAll() * Ratsnest must be recalculated after module exchange */ bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE* Module, - const wxString& new_module, + const FPID& new_module, PICKED_ITEMS_LIST* aUndoPickList, bool ShowError ) { - wxString namecmp, oldnamecmp; + FPID namecmp, oldnamecmp; MODULE* NewModule; wxString line; @@ -457,18 +458,18 @@ bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE* Module, wxBusyCursor dummy; // Copy parameters from the old module. - oldnamecmp = Module->GetLibRef(); + oldnamecmp = Module->GetFPID(); namecmp = new_module; // Load module. line.Printf( _( "Change module %s (from %s) " ), GetChars( Module->GetReference() ), - GetChars( oldnamecmp ) ); + oldnamecmp.Format().c_str() ); m_WinMessages->AppendText( line ); - namecmp.Trim( true ); - namecmp.Trim( false ); - NewModule = m_Parent->GetModuleLibrary( wxEmptyString, namecmp, ShowError ); + NewModule = m_Parent->GetModuleLibrary( FROM_UTF8( namecmp.GetLibNickname().c_str() ), + FROM_UTF8( namecmp.GetFootprintName().c_str() ), + ShowError ); if( NewModule == NULL ) // New module not found, redraw the old one. { @@ -641,7 +642,7 @@ void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent ) fprintf( FichCmp, "ValeurCmp = %s;\n", !Module->GetValue().IsEmpty() ? TO_UTF8( Module->GetValue() ) : "[NoVal]" ); - fprintf( FichCmp, "IdModule = %s;\n", TO_UTF8( Module->GetLibRef() ) ); + fprintf( FichCmp, "IdModule = %s;\n", Module->GetFPID().Format().c_str() ); fprintf( FichCmp, "EndCmp\n" ); } From 8ea015aaab1df0e9c03e64dc90179dbf1d7d2ea3 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 11 Sep 2013 17:30:21 +0200 Subject: [PATCH 17/29] Eeschema: fix compatibility with old schematic files, which can contain markers. Pcbnew: better test for allowed layers when creating/editing Dimensions and some other Graphic items Drc: fix comments and messages for some drc tests. To do: fix issues in active layer selection when creating a track and layer pair selection dialog --- eeschema/load_one_schematic_file.cpp | 4 + include/layers_id_colors_and_visibility.h | 39 ++++++-- include/wxBasePcbFrame.h | 18 +++- pcbnew/class_drc_item.cpp | 6 +- .../dialog_graphic_item_properties.cpp | 1 + .../dialogs/dialog_layer_selection_base.cpp | 17 ++-- .../dialogs/dialog_layer_selection_base.fbp | 96 +------------------ pcbnew/dialogs/dialog_layer_selection_base.h | 9 +- pcbnew/dimension.cpp | 8 +- pcbnew/drc_clearance_test_functions.cpp | 16 +++- pcbnew/drc_stuff.h | 10 +- pcbnew/edgemod.cpp | 41 +++++--- pcbnew/edit.cpp | 10 +- pcbnew/onleftclick.cpp | 5 +- pcbnew/sel_layer.cpp | 71 +++++--------- pcbnew/swap_layers.cpp | 31 ++---- 16 files changed, 159 insertions(+), 223 deletions(-) diff --git a/eeschema/load_one_schematic_file.cpp b/eeschema/load_one_schematic_file.cpp index 9ca2183bba..8aa9243d79 100644 --- a/eeschema/load_one_schematic_file.cpp +++ b/eeschema/load_one_schematic_file.cpp @@ -194,6 +194,7 @@ again." ); case 'K': // It is a Marker item. // Markers are no more read from file. they are only created on // demand in schematic + itemLoaded = true; // Just skip descr and disable err message break; case 'N': // It is a NoConnect item. @@ -242,6 +243,9 @@ again." ); if( !itemLoaded ) { + msgDiag.Printf( _( "Eeschema file object not loaded at line %d, aborted" ), + reader.LineNumber() ); + msgDiag << wxT( "\n" ) << FROM_UTF8( line ); DisplayError( this, msgDiag ); break; } diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index 1dd41130f0..dc8185896a 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -139,14 +139,35 @@ typedef unsigned LAYER_MSK; #define NO_LAYERS 0x00000000 -/** return a one bit layer mask from a layer number - * aLayerNumber = the layer number to convert (0 .. LAYERS-1) +/** + * @return a one bit layer mask from a layer number + * @param aLayerNumber = the layer number to convert (0 .. LAYERS-1) */ inline LAYER_MSK GetLayerMask( LAYER_NUM aLayerNumber ) { return 1 << aLayerNumber; } +/** + * @return bool if aLayerNumber is a layer contained in aMask + * @param aMask = a layer mask + * @param aLayerNumber is the layer id to test + */ +inline bool IsLayerInList( LAYER_MSK aMask, LAYER_NUM aLayerNumber ) +{ + return (aMask & GetLayerMask( aLayerNumber )) != 0; +} + +/** + * @return bool if 2 layer masks have a comman layer + * @param aMask1 = a layer mask + * @param aMask2 = an other layer mask + */ +inline bool IsLayerMasksIntersect( LAYER_MSK aMask1, LAYER_MSK aMask2 ) +{ + return (aMask1 & aMask2) != 0; +} + /** * Count the number of set layers in the mask */ @@ -244,11 +265,11 @@ inline bool IsPcbLayer( LAYER_NUM aLayer ) * Function IsCopperLayer * tests whether a layer is a copper layer * @param aLayer = Layer to test - * @return true if aLayer is a valid copper layer + * @return true if aLayer is a valid copper layer */ inline bool IsCopperLayer( LAYER_NUM aLayer ) { - return aLayer >= FIRST_COPPER_LAYER + return aLayer >= FIRST_COPPER_LAYER && aLayer <= LAST_COPPER_LAYER; } @@ -269,12 +290,12 @@ inline bool IsNonCopperLayer( LAYER_NUM aLayer ) So a layer can be: - Front - Back - - Neither (internal or auxiliary) - + - Neither (internal or auxiliary) + The check most frequent is for back layers, since it involves flips */ -/** +/** * Layer classification: check if it's a front layer */ inline bool IsFrontLayer( LAYER_NUM aLayer ) @@ -286,7 +307,7 @@ inline bool IsFrontLayer( LAYER_NUM aLayer ) aLayer == SOLDERPASTE_N_FRONT ); } -/** +/** * Layer classification: check if it's a back layer */ inline bool IsBackLayer( LAYER_NUM aLayer ) @@ -314,7 +335,7 @@ LAYER_MSK FlipLayerMask( LAYER_MSK aMask ); /** * Extract the set layer from a mask. Returns UNDEFINED_LAYER if more - * than one is set or UNSELECTED_LAYER if none is + * than one is set or UNSELECTED_LAYER if none is */ LAYER_NUM ExtractLayer( LAYER_MSK aMask ); diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 12843befbe..b74c6165e5 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -639,11 +639,19 @@ public: const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) = 0; - // layerhandling: - // (See pcbnew/sel_layer.cpp for description of why null_layer parameter - // is provided) - LAYER_NUM SelectLayer( LAYER_NUM default_layer, LAYER_NUM min_layer, LAYER_NUM max_layer, bool null_layer = false ); - void SelectLayerPair(); + /** Install the dialog box for layer selection + * @param aDefaultLayer = Preselection (NB_PCB_LAYERS for "(Deselect)" layer) + * @param aNotAllowedLayersMask = a layer mask for not allowed layers + * (= 0 to show all layers in use) + * @return the selected layer id + */ + LAYER_NUM SelectLayer( LAYER_NUM aDefaultLayer, LAYER_MSK aNotAllowedLayersMask = 0 ); + + /* Display a list of two copper layers to choose a pair of copper layers + * the layer pair is used to fast switch between copper layers when placing vias + */ + void SelectCopperLayerPair(); + virtual void SwitchLayer( wxDC* DC, LAYER_NUM layer ); /** diff --git a/pcbnew/class_drc_item.cpp b/pcbnew/class_drc_item.cpp index edbdf94308..b70d98d3c2 100644 --- a/pcbnew/class_drc_item.cpp +++ b/pcbnew/class_drc_item.cpp @@ -60,9 +60,9 @@ wxString DRC_ITEM::GetErrorText() const case DRCE_ENDS_PROBLEM3: case DRCE_ENDS_PROBLEM4: case DRCE_ENDS_PROBLEM5: - return wxString( _("Two track ends") ); - case DRCE_TRACK_UNKNOWN1: - return wxString( _("This looks bad") ); ///< @todo check source code and change this comment + return wxString( _("Two track ends too close") ); + case DRCE_TRACK_SEGMENTS_TOO_CLOSE: + return wxString( _("Two parallel track segments too close") ); case DRCE_TRACKS_CROSSING: return wxString( _("Tracks crossing") ); case DRCE_PAD_NEAR_PAD1: diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index c4271c7b1c..561c29fa2a 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -165,6 +165,7 @@ void DIALOG_GRAPHIC_ITEM_PROPERTIES::initDlg( ) m_LayerSelectionCtrl->SetLayerMask( ALL_CU_LAYERS ); m_LayerSelectionCtrl->SetBoardFrame( m_parent ); m_LayerSelectionCtrl->Resync(); + if( m_LayerSelectionCtrl->SetLayerSelection( m_Item->GetLayer() ) < 0 ) { wxMessageBox( _("This item has an illegal layer id.\n" diff --git a/pcbnew/dialogs/dialog_layer_selection_base.cpp b/pcbnew/dialogs/dialog_layer_selection_base.cpp index 37e90f562b..363bcac26a 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.cpp +++ b/pcbnew/dialogs/dialog_layer_selection_base.cpp @@ -77,9 +77,6 @@ DIALOG_LAYER_SELECTION_BASE::DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWi bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); - m_buttonClear = new wxButton( this, wxID_ANY, _("Clear Selection"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerMain->Add( m_buttonClear, 0, wxALL|wxALIGN_RIGHT, 5 ); - this->SetSizer( bSizerMain ); this->Layout(); @@ -87,17 +84,19 @@ DIALOG_LAYER_SELECTION_BASE::DIALOG_LAYER_SELECTION_BASE( wxWindow* parent, wxWi this->Centre( wxBOTH ); // Connect Events - m_leftGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftGridClick ), NULL, this ); - m_rightGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnRightGridClick ), NULL, this ); - m_buttonClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LAYER_SELECTION_BASE::OnClearSelection ), NULL, this ); + m_leftGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftGridCellClick ), NULL, this ); + m_leftGridLayers->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftButtonReleased ), NULL, this ); + m_rightGridLayers->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnRightGridCellClick ), NULL, this ); + m_rightGridLayers->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftButtonReleased ), NULL, this ); } DIALOG_LAYER_SELECTION_BASE::~DIALOG_LAYER_SELECTION_BASE() { // Disconnect Events - m_leftGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftGridClick ), NULL, this ); - m_rightGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnRightGridClick ), NULL, this ); - m_buttonClear->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LAYER_SELECTION_BASE::OnClearSelection ), NULL, this ); + m_leftGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftGridCellClick ), NULL, this ); + m_leftGridLayers->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftButtonReleased ), NULL, this ); + m_rightGridLayers->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LAYER_SELECTION_BASE::OnRightGridCellClick ), NULL, this ); + m_rightGridLayers->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( DIALOG_LAYER_SELECTION_BASE::OnLeftButtonReleased ), NULL, this ); } diff --git a/pcbnew/dialogs/dialog_layer_selection_base.fbp b/pcbnew/dialogs/dialog_layer_selection_base.fbp index 2a702b9e3c..5b93df5788 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.fbp +++ b/pcbnew/dialogs/dialog_layer_selection_base.fbp @@ -190,7 +190,7 @@ - OnLeftGridClick + OnLeftGridCellClick @@ -227,7 +227,7 @@ - + OnLeftButtonReleased @@ -333,7 +333,7 @@ - OnRightGridClick + OnRightGridCellClick @@ -370,7 +370,7 @@ - + OnLeftButtonReleased @@ -388,94 +388,6 @@
- - 5 - wxALL|wxALIGN_RIGHT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Clear Selection - - 0 - - - 0 - - 1 - m_buttonClear - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnClearSelection - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pcbnew/dialogs/dialog_layer_selection_base.h b/pcbnew/dialogs/dialog_layer_selection_base.h index 4a2b40f2ac..af475aa160 100644 --- a/pcbnew/dialogs/dialog_layer_selection_base.h +++ b/pcbnew/dialogs/dialog_layer_selection_base.h @@ -18,10 +18,10 @@ #include #include #include -#include #include #include #include +#include /////////////////////////////////////////////////////////////////////////// @@ -38,12 +38,11 @@ class DIALOG_LAYER_SELECTION_BASE : public wxDialog protected: wxGrid* m_leftGridLayers; wxGrid* m_rightGridLayers; - wxButton* m_buttonClear; // Virtual event handlers, overide them in your derived class - virtual void OnLeftGridClick( wxGridEvent& event ) { event.Skip(); } - virtual void OnRightGridClick( wxGridEvent& event ) { event.Skip(); } - virtual void OnClearSelection( wxCommandEvent& event ) { event.Skip(); } + virtual void OnLeftGridCellClick( wxGridEvent& event ) { event.Skip(); } + virtual void OnLeftButtonReleased( wxMouseEvent& event ) { event.Skip(); } + virtual void OnRightGridCellClick( wxGridEvent& event ) { event.Skip(); } public: diff --git a/pcbnew/dimension.cpp b/pcbnew/dimension.cpp index ab07b66fdb..819c1a3110 100644 --- a/pcbnew/dimension.cpp +++ b/pcbnew/dimension.cpp @@ -138,7 +138,13 @@ DIALOG_DIMENSION_EDITOR::DIALOG_DIMENSION_EDITOR( PCB_EDIT_FRAME* aParent, m_SelLayerBox->SetLayerMask( ALL_CU_LAYERS | EDGE_LAYER ); m_SelLayerBox->SetBoardFrame( m_Parent ); m_SelLayerBox->Resync(); - m_SelLayerBox->SetLayerSelection( aDimension->GetLayer() ); + + if( m_SelLayerBox->SetLayerSelection( aDimension->GetLayer() ) < 0 ) + { + wxMessageBox( _("This item has an illegal layer id.\n" + "Now, forced on the drawings layer. Please, fix it") ); + m_SelLayerBox->SetLayerSelection( DRAW_N ); + } GetSizer()->Fit( this ); GetSizer()->SetSizeHints( this ); diff --git a/pcbnew/drc_clearance_test_functions.cpp b/pcbnew/drc_clearance_test_functions.cpp index b0d1d01a56..43d96d11d1 100644 --- a/pcbnew/drc_clearance_test_functions.cpp +++ b/pcbnew/drc_clearance_test_functions.cpp @@ -420,6 +420,10 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) if( segStartPoint.x > (-w_dist) && segStartPoint.x < (m_segmLength + w_dist) ) /* possible error drc */ { + // the start point is inside the reference range + // X........ + // O--REF--+ + // Fine test : we consider the rounded shape of each end of the track segment: if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength ) { @@ -438,7 +442,10 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) if( segEndPoint.x > (-w_dist) && segEndPoint.x < (m_segmLength + w_dist) ) { - /* Fine test : we consider the rounded shape of the ends */ + // the end point is inside the reference range + // .....X + // O--REF--+ + // Fine test : we consider the rounded shape of the ends if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength ) { m_currentMarker = fillMarker( aRefSeg, track, @@ -456,8 +463,13 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) if( segStartPoint.x <=0 && segEndPoint.x >= 0 ) { + // the segment straddles the reference range (this actually only + // checks if it straddles the origin, because the other cases where already + // handled) + // X.............X + // O--REF--+ m_currentMarker = fillMarker( aRefSeg, track, - DRCE_TRACK_UNKNOWN1, m_currentMarker ); + DRCE_TRACK_SEGMENTS_TOO_CLOSE, m_currentMarker ); return false; } } diff --git a/pcbnew/drc_stuff.h b/pcbnew/drc_stuff.h index e031cdc20a..f2daee5b95 100644 --- a/pcbnew/drc_stuff.h +++ b/pcbnew/drc_stuff.h @@ -44,11 +44,11 @@ #define DRCE_TRACK_NEAR_VIA 5 ///< track too close to via #define DRCE_VIA_NEAR_VIA 6 ///< via too close to via #define DRCE_VIA_NEAR_TRACK 7 ///< via too close to track -#define DRCE_TRACK_ENDS1 8 ///< @todo say what this problem is -#define DRCE_TRACK_ENDS2 9 ///< @todo say what this problem is -#define DRCE_TRACK_ENDS3 10 ///< @todo say what this problem is -#define DRCE_TRACK_ENDS4 11 ///< @todo say what this problem is -#define DRCE_TRACK_UNKNOWN1 12 ///< @todo check source code and change this comment +#define DRCE_TRACK_ENDS1 8 ///< 2 parallel track segments too close: fine start point test +#define DRCE_TRACK_ENDS2 9 ///< 2 parallel track segments too close: fine start point test +#define DRCE_TRACK_ENDS3 10 ///< 2 parallel track segments too close: fine end point test +#define DRCE_TRACK_ENDS4 11 ///< 2 parallel track segments too close: fine end point test +#define DRCE_TRACK_SEGMENTS_TOO_CLOSE 12 ///< 2 parallel track segments too close: segm ends between segref ends #define DRCE_TRACKS_CROSSING 13 ///< tracks are crossing #define DRCE_ENDS_PROBLEM1 14 ///< track ends are too close #define DRCE_ENDS_PROBLEM2 15 ///< track ends are too close diff --git a/pcbnew/edgemod.cpp b/pcbnew/edgemod.cpp index 870e9e710a..14843623a1 100644 --- a/pcbnew/edgemod.cpp +++ b/pcbnew/edgemod.cpp @@ -1,10 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr - * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2012 Wayne Stambaugh - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2013 Wayne Stambaugh + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -190,16 +190,19 @@ void FOOTPRINT_EDIT_FRAME::Edit_Edge_Width( EDGE_MODULE* aEdge ) void FOOTPRINT_EDIT_FRAME::Edit_Edge_Layer( EDGE_MODULE* aEdge ) { + // note: if aEdge == NULL, all outline segments will be modified + MODULE* module = GetBoard()->m_Modules; - LAYER_NUM new_layer = SILKSCREEN_N_FRONT; + LAYER_NUM layer = SILKSCREEN_N_FRONT; + bool modified = false; if( aEdge ) - new_layer = aEdge->GetLayer(); + layer = aEdge->GetLayer(); // Ask for the new layer - new_layer = SelectLayer( new_layer, FIRST_COPPER_LAYER, ECO2_N ); + LAYER_NUM new_layer = SelectLayer(layer, EDGE_LAYER ); - if( new_layer < 0 ) + if( layer < 0 ) return; if( IsCopperLayer( new_layer ) ) @@ -211,8 +214,6 @@ void FOOTPRINT_EDIT_FRAME::Edit_Edge_Layer( EDGE_MODULE* aEdge ) return; } - SaveCopyInUndoList( module, UR_MODEDIT ); - if( aEdge == NULL ) { aEdge = (EDGE_MODULE*) (BOARD_ITEM*) module->GraphicalItems(); @@ -222,17 +223,27 @@ void FOOTPRINT_EDIT_FRAME::Edit_Edge_Layer( EDGE_MODULE* aEdge ) if( aEdge->Type() != PCB_MODULE_EDGE_T ) continue; - aEdge->SetLayer( new_layer ); + if( aEdge->GetLayer() != new_layer ) + { + if( ! modified ) // save only once + SaveCopyInUndoList( module, UR_MODEDIT ); + aEdge->SetLayer( new_layer ); + modified = true; + } } } - else + else if( aEdge->GetLayer() != new_layer ) { + SaveCopyInUndoList( module, UR_MODEDIT ); aEdge->SetLayer( new_layer ); + modified = true; } - OnModify(); - module->CalculateBoundingBox(); - module->SetLastEditTime(); + if( modified ) + { + module->CalculateBoundingBox(); + module->SetLastEditTime(); + } } diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index ae445f1d8b..3524e584f3 100755 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -922,7 +922,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_SELECT_LAYER: - itmp = SelectLayer( getActiveLayer(), UNDEFINED_LAYER, UNDEFINED_LAYER ); + itmp = SelectLayer( getActiveLayer() ); if( itmp >= 0 ) { @@ -939,11 +939,11 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR: - SelectLayerPair(); + SelectCopperLayerPair(); break; case ID_POPUP_PCB_SELECT_NO_CU_LAYER: - itmp = SelectLayer( getActiveLayer(), FIRST_NON_COPPER_LAYER, UNDEFINED_LAYER ); + itmp = SelectLayer( getActiveLayer(), ALL_CU_LAYERS ); if( itmp >= 0 ) setActiveLayer( itmp ); @@ -952,7 +952,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_SELECT_CU_LAYER: - itmp = SelectLayer( getActiveLayer(), UNDEFINED_LAYER, LAST_COPPER_LAYER ); + itmp = SelectLayer( getActiveLayer(), ALL_NO_CU_LAYERS ); if( itmp >= 0 ) setActiveLayer( itmp ); @@ -960,7 +960,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_SELECT_LAYER_PAIR: - SelectLayerPair(); + SelectCopperLayerPair(); m_canvas->MoveCursorToCrossHair(); break; diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 53703e3166..5c79ce4962 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -367,9 +367,10 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) break; case ID_PCB_DIMENSION_BUTT: - if( IsCopperLayer( getActiveLayer() ) ) + if( IsLayerInList( EDGE_LAYER|ALL_CU_LAYERS ,getActiveLayer() ) ) { - DisplayError( this, _( "Dimension not allowed on Copper layers" ) ); + DisplayError( this, + _( "Dimension not allowed on Copper or Edge Cut layers" ) ); break; } diff --git a/pcbnew/sel_layer.cpp b/pcbnew/sel_layer.cpp index fc8ebc10e1..28a9e3f327 100644 --- a/pcbnew/sel_layer.cpp +++ b/pcbnew/sel_layer.cpp @@ -74,30 +74,25 @@ protected: }; /* - * This class display a pcb layers list in adialog, + * This class display a pcb layers list in a dialog, * to select one layer from this list */ class PCB_ONE_LAYER_SELECTOR : public PCB_LAYER_SELECTOR, public DIALOG_LAYER_SELECTION_BASE { LAYER_NUM m_layerSelected; - LAYER_NUM m_minLayer; - LAYER_NUM m_maxLayer; + LAYER_MSK m_notAllowedLayersMask; std::vector m_layersIdLeftColumn; std::vector m_layersIdRightColumn; public: PCB_ONE_LAYER_SELECTOR( wxWindow* aParent, BOARD * aBrd, LAYER_NUM aDefaultLayer, - LAYER_NUM aMinLayer = -1, LAYER_NUM aMaxLayer = -1, - bool aClearTool = false ) + LAYER_MSK aNotAllowedLayersMask ) :PCB_LAYER_SELECTOR( aBrd ), DIALOG_LAYER_SELECTION_BASE( aParent ) { m_layerSelected = (int) aDefaultLayer; - // When not needed, remove the "Clear" button - m_buttonClear->Show( aClearTool ); - m_minLayer = aMinLayer; - m_maxLayer = aMaxLayer; + m_notAllowedLayersMask = aNotAllowedLayersMask; BuildList(); Layout(); GetSizer()->SetSizeHints(this); @@ -108,13 +103,8 @@ public: private: // Event handlers - void OnLeftGridClick( wxGridEvent& event ); - void OnRightGridClick( wxGridEvent& event ); - void OnClearSelection( wxCommandEvent& event ) - { - m_layerSelected = NB_PCB_LAYERS; - EndModal( NB_PCB_LAYERS ); - } + void OnLeftGridCellClick( wxGridEvent& event ); + void OnRightGridCellClick( wxGridEvent& event ); void BuildList(); }; @@ -146,10 +136,7 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() if( ! IsLayerEnabled( layerid ) ) continue; - if( m_minLayer >= 0 && layerid < m_minLayer ) - continue; - - if( m_maxLayer >= 0 && layerid > m_maxLayer ) + if( (m_notAllowedLayersMask & GetLayerMask( layerid )) != 0 ) continue; wxColour color = MakeColour( GetLayerColor( layerid ) ); @@ -214,43 +201,31 @@ void PCB_ONE_LAYER_SELECTOR::BuildList() m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM); } -void PCB_ONE_LAYER_SELECTOR::OnLeftGridClick( wxGridEvent& event ) +void PCB_ONE_LAYER_SELECTOR::OnLeftGridCellClick( wxGridEvent& event ) { m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ]; + m_leftGridLayers->SetGridCursor( event.GetRow(), LAYERNAME_COLNUM ); EndModal( 1 ); } -void PCB_ONE_LAYER_SELECTOR::OnRightGridClick( wxGridEvent& event ) +void PCB_ONE_LAYER_SELECTOR::OnRightGridCellClick( wxGridEvent& event ) { m_layerSelected = m_layersIdRightColumn[ event.GetRow() ]; + m_rightGridLayers->SetGridCursor( event.GetRow(), LAYERNAME_COLNUM ); EndModal( 2 ); } /** Install the dialog box for layer selection * @param aDefaultLayer = Preselection (NB_PCB_LAYERS for "(Deselect)" layer) - * @param aMinlayer = min layer id value (-1 if no min value) - * @param aMaxLayer = max layer id value (-1 if no max value) - * @param aDeselectTool = display a "Clear" button when true - * @return new layer value (NB_PCB_LAYERS when "(Deselect)" radiobutton selected), - * or -1 if canceled - * - * Providing the option to also display a "Clear" button makes the - * "Swap Layers" command more "user friendly", - * by permitting any layer to be "deselected" immediately after its - * corresponding radiobutton has been clicked on. (It would otherwise be - * necessary to first cancel the "Select Layer:" dialog box (invoked after a - * different radiobutton is clicked on) prior to then clicking on the - * "Clear" button provided within the "Swap Layers:" - * or "Layer selection:" dialog box). + * @param aNotAllowedLayers = a layer mask for not allowed layers + * (= 0 to show all layers in use) + * @return the selected layer id */ LAYER_NUM PCB_BASE_FRAME::SelectLayer( LAYER_NUM aDefaultLayer, - LAYER_NUM aMinlayer, - LAYER_NUM aMaxLayer, - bool aDeselectTool ) + LAYER_MSK aNotAllowedLayersMask ) { PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), - aDefaultLayer, aMinlayer, aMaxLayer, - aDeselectTool ); + aDefaultLayer, aNotAllowedLayersMask ); dlg.ShowModal(); LAYER_NUM layer = dlg.GetLayerSelection(); return layer; @@ -283,8 +258,8 @@ public: } private: - void OnLeftGridClick( wxGridEvent& event ); - void OnRightGridClick( wxGridEvent& event ); + void OnLeftGridCellClick( wxGridEvent& event ); + void OnRightGridCellClick( wxGridEvent& event ); void OnOkClick( wxCommandEvent& event ) { @@ -300,10 +275,10 @@ private: }; -/* Display a list of two copper layers to choose a pair of layers - * for auto-routing, vias ... +/* Display a list of two copper layers to choose a pair of copper layers + * the layer pair is used to fast switch between copper layers when placing vias */ -void PCB_BASE_FRAME::SelectLayerPair() +void PCB_BASE_FRAME::SelectCopperLayerPair() { PCB_SCREEN* screen = GetScreen(); SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( this, GetBoard(), @@ -411,7 +386,7 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::BuildList() m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM); } -void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridClick( wxGridEvent& event ) +void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridCellClick( wxGridEvent& event ) { int row = event.GetRow(); LAYER_NUM layer = m_layersId[row]; @@ -434,7 +409,7 @@ void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridClick( wxGridEvent& event ) m_leftGridLayers->SetGridCursor( row, LAYERNAME_COLNUM ); } -void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridClick( wxGridEvent& event ) +void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridCellClick( wxGridEvent& event ) { int row = event.GetRow(); LAYER_NUM layer = m_layersId[row]; diff --git a/pcbnew/swap_layers.cpp b/pcbnew/swap_layers.cpp index 545c063770..10847c99c5 100644 --- a/pcbnew/swap_layers.cpp +++ b/pcbnew/swap_layers.cpp @@ -195,12 +195,11 @@ WinEDA_SwapLayerFrame::WinEDA_SwapLayerFrame( PCB_BASE_FRAME* parent ) : item_ID = ID_TEXT_0 + ii; /* When the first of these text strings is being added, determine - * what size is necessary to to be able to display any possible - * string without it being truncated. Then specify that size as the - * minimum size for all of these text strings. (If this minimum - * size is not determined in this fashion, then it is possible for - * the display of one or more of these strings to be truncated after - * different layers are selected.) + * what size is necessary to to be able to display the longest + * string without truncation. Then use that size as the + * minimum size for all text strings. (If the minimum + * size is not this size, strings can be truncated after + * some other layer is selected.) */ if( ii == 0 ) { @@ -235,8 +234,8 @@ WinEDA_SwapLayerFrame::WinEDA_SwapLayerFrame( PCB_BASE_FRAME* parent ) : } /* Provide spacers to occupy otherwise blank cells within the second - * FlexGrid sizer. (As it incorporates three columns, three spacers - * are thus required for each otherwise unused row.) + * FlexGrid sizer. (Becuse there are three columns, three spacers + * are thus required for each unused row.) */ for( int ii = 3 * NB_PCB_LAYERS; ii < 96; ii++ ) { @@ -289,28 +288,16 @@ void WinEDA_SwapLayerFrame::Sel_Layer( wxCommandEvent& event ) if( (jj < 0) || (jj > NB_PCB_LAYERS) ) jj = LAYER_NO_CHANGE; // (Defaults to "No Change".) - jj = m_Parent->SelectLayer( jj, UNDEFINED_LAYER, UNDEFINED_LAYER, true ); + jj = m_Parent->SelectLayer( jj ); if( !IsValidLayer( jj ) ) return; - // No change if the selected layer matches the layer being edited. - // (Hence the only way to restore a layer to the "No Change" - // state is by specifically deselecting it; any attempt - // to select the same layer (instead) will be ignored.) - if( jj == ii ) - { - wxString msg; - msg = _( "Deselect this layer to select the No Change state" ); - DisplayInfoMessage( this, msg ); - return; - } - if( jj != New_Layer[ii] ) { New_Layer[ii] = jj; - if( jj >= LAYER_NO_CHANGE ) + if( jj >= LAYER_NO_CHANGE || jj == ii ) { layer_list[ii]->SetLabel( _( "No Change" ) ); From a06134cd6c9156472c32a5eb768db49db1c6f031 Mon Sep 17 00:00:00 2001 From: "Lorenzo Marcantonio l.marcantonio@logossrl.com" Date: Fri, 13 Sep 2013 11:49:55 +0200 Subject: [PATCH 18/29] Add export netlist IPC-D-356 from Lorenzo Marcantonio, with very minor fixes. --- include/wxPcbStruct.h | 1 + pcbnew/CMakeLists.txt | 1 + pcbnew/menubar_pcbframe.cpp | 5 +++++ pcbnew/pcbframe.cpp | 1 + pcbnew/pcbnew_id.h | 1 + 5 files changed, 9 insertions(+) diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index d7b2c09b5e..43971a89de 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -810,6 +810,7 @@ public: bool DoGenFootprintsReport( const wxString& aFullFilename, bool aUnitsMM ); void InstallDrillFrame( wxCommandEvent& event ); + void GenD356File( wxCommandEvent& event ); void ToPostProcess( wxCommandEvent& event ); void OnFileHistory( wxCommandEvent& event ); diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 59fcb0209c..37a671744b 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -155,6 +155,7 @@ set( PCBNEW_CLASS_SRCS edit_track_width.cpp edtxtmod.cpp event_handlers_tracks_vias_sizes.cpp + export_d356.cpp export_gencad.cpp export_vrml.cpp files.cpp diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index a63c652b5a..b4ef6f6407 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -141,6 +141,11 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() _( "Create a report of all modules on the current board" ), KiBitmap( tools_xpm ) ); + AddMenuItem( fabricationOutputsMenu, ID_PCB_GEN_D356_FILE, + _( "IPC-D-356 Netlist File" ), + _( "Generate IPC-D-356 netlist file" ), + KiBitmap( netlist_xpm ) ); + // Component File AddMenuItem( fabricationOutputsMenu, ID_PCB_GEN_CMP_FILE, _( "&Component (.cmp) File" ), diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 9bce32510e..ed6795639b 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -136,6 +136,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) // menu Postprocess EVT_MENU( ID_PCB_GEN_POS_MODULES_FILE, PCB_EDIT_FRAME::GenFootprintsPositionFile ) EVT_MENU( ID_PCB_GEN_DRILL_FILE, PCB_EDIT_FRAME::InstallDrillFrame ) + EVT_MENU( ID_PCB_GEN_D356_FILE, PCB_EDIT_FRAME::GenD356File ) EVT_MENU( ID_PCB_GEN_CMP_FILE, PCB_EDIT_FRAME::RecreateCmpFileFromBoard ) EVT_MENU( ID_PCB_GEN_BOM_FILE_FROM_BOARD, PCB_EDIT_FRAME::RecreateBOMFileFromBoard ) diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index 8d89a6116a..7ca2e561d6 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -260,6 +260,7 @@ enum pcbnew_ids ID_PCB_GEN_POS_MODULES_FILE, ID_PCB_GEN_DRILL_FILE, + ID_PCB_GEN_D356_FILE, ID_PCB_PAD_SETUP, From eedd673d4c350d0570e65ab2856fbe6adc3f4e2a Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 13 Sep 2013 11:58:51 +0200 Subject: [PATCH 19/29] Pcbnew: Fix Bug #1224656 --- pcbnew/pcb_parser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 16f2d5b6da..58208e320b 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1567,6 +1567,7 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR break; case T_fp_lib: + NeedSYMBOLorNUMBER(); fpid.SetLibNickname( FromUTF8() ); NeedRIGHT(); break; From 2cab94f56ca8e84125b6e4b7b8737dc9a71a2657 Mon Sep 17 00:00:00 2001 From: Lorenzo Marcantonio Date: Fri, 13 Sep 2013 12:59:47 +0200 Subject: [PATCH 20/29] Add missing file --- pcbnew/export_d356.cpp | 394 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 pcbnew/export_d356.cpp diff --git a/pcbnew/export_d356.cpp b/pcbnew/export_d356.cpp new file mode 100644 index 0000000000..e8ef8f3fbf --- /dev/null +++ b/pcbnew/export_d356.cpp @@ -0,0 +1,394 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011-2013 Lorenzo Marcantonio + * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file export_d356.cpp + * @brief Export IPC-D-356 test format + */ + +#include "fctsys.h" +#include "class_drawpanel.h" +#include "confirm.h" +#include "gestfich.h" +#include "appl_wxstruct.h" +#include "wxPcbStruct.h" +#include "trigo.h" +#include "build_version.h" +#include "macros.h" + +#include "pcbnew.h" + +#include "class_board.h" +#include "class_module.h" +#include "class_track.h" +#include "class_edge_mod.h" +#include +#include + +/* Structure for holding the D-356 record fields. + * Useful because 356A (when implemented) must be sorted before outputting it */ +struct D356_RECORD +{ + bool smd; + bool hole; + wxString netname; + wxString refdes; + wxString pin; + bool midpoint; + int drill; + bool mechanical; + int access; // Access 0 is 'both sides' + int soldermask; + // All these in PCB units, will be output in decimils + int x_location; + int y_location; + int x_size; + int y_size; + int rotation; +}; + +// Compute the access code for a pad. Returns -1 if there is no copper +static int compute_pad_access_code( BOARD *aPcb, LAYER_MSK aLayerMask ) +{ + // Non-copper is not interesting here + aLayerMask &= ALL_CU_LAYERS; + if( aLayerMask == 0 ) + return -1; + + // Traditional TH pad + if( (aLayerMask & LAYER_FRONT) && (aLayerMask & LAYER_BACK) ) + return 0; + + // Front SMD pad + if( (aLayerMask & LAYER_FRONT) ) + return 1; + + // Back SMD pad + if( (aLayerMask & LAYER_BACK) ) + return aPcb->GetCopperLayerCount(); + + // OK, we have an inner-layer only pad (and I have no idea about + // what could be used for); anyway, find the first copper layer + // it's on + for (LAYER_NUM scan_layer = LAYER_N_2; + scan_layer < LAYER_N_BACK; + ++scan_layer) + { + if( GetLayerMask( scan_layer ) & aLayerMask ) + return scan_layer + 1; + } + + // This shouldn't happen + return -1; +} + +/* Convert and clamp a size from IU to decimils */ +static int iu_to_d356(int iu, int clamp) +{ + int val = KiROUND( iu / IU_PER_DECIMILS ); + if( val > clamp ) return clamp; + if( val < -clamp ) return -clamp; + return val; +} + +/* Extract the D356 record from the modules (pads) */ +static void build_pad_testpoints( BOARD *aPcb, + std::vector & aRecords ) +{ + wxPoint origin = aPcb->GetAuxOrigin(); + + for( MODULE *module = aPcb->m_Modules; + module != NULL; module = module->Next() ) + { + for( D_PAD *pad = module->Pads(); pad != NULL; pad = pad->Next() ) + { + D356_RECORD rk; + rk.access = compute_pad_access_code( aPcb, pad->GetLayerMask() ); + + // It could be a mask only pad, we only handle pads with copper here + if( rk.access != -1 ) + { + rk.netname = pad->GetNetname(); + rk.refdes = module->GetReference(); + pad->ReturnStringPadName( rk.pin ); + rk.midpoint = false; // XXX MAYBE need to be computed (how?) + const wxSize& drill = pad->GetDrillSize(); + rk.drill = std::min( drill.x, drill.y ); + rk.hole = (rk.drill != 0); + rk.smd = pad->GetAttribute() == PAD_SMD; + rk.mechanical = (pad->GetAttribute() == PAD_HOLE_NOT_PLATED); + rk.x_location = pad->GetPosition().x - origin.x; + rk.y_location = origin.y - pad->GetPosition().y; + rk.x_size = pad->GetSize().x; + + // Rule: round pads have y = 0 + if( pad->GetShape() == PAD_CIRCLE ) + rk.y_size = 0; + else + rk.y_size = pad->GetSize().y; + + rk.rotation = -KiROUND( pad->GetOrientation() ) / 10; + if( rk.rotation < 0 ) rk.rotation += 360; + + // the value indicates which sides are *not* accessible + rk.soldermask = 3; + if( pad->GetLayerMask() & SOLDERMASK_LAYER_FRONT) + rk.soldermask &= ~1; + if( pad->GetLayerMask() & SOLDERMASK_LAYER_BACK) + rk.soldermask &= ~2; + + aRecords.push_back( rk ); + } + } + } +} + +/* Compute the access code for a via. In D-356 layers are numbered from 1 up, + where '1' is the 'primary side' (usually the component side); + '0' means 'both sides', and other layers follows in an unspecified order */ +static int via_access_code( BOARD *aPcb, int top_layer, int bottom_layer ) +{ + // Easy case for through vias: top_layer is component, bottom_layer is + // solder, access code is 0 + if( (top_layer == LAYER_N_FRONT) && (bottom_layer == LAYER_N_BACK) ) + return 0; + + // Blind via, reachable from front + if( top_layer == LAYER_N_FRONT ) + return 1; + + // Blind via, reachable from bottom + if( bottom_layer == LAYER_N_BACK ) + return aPcb->GetCopperLayerCount(); + + // It's a buried via, accessible from some inner layer + // (maybe could be used for testing before laminating? no idea) + return bottom_layer + 1; // XXX is this correct? +} + +/* Extract the D356 record from the vias */ +static void build_via_testpoints( BOARD *aPcb, + std::vector & aRecords ) +{ + wxPoint origin = aPcb->GetAuxOrigin(); + + // Enumerate all the track segments and keep the vias + for( TRACK *track = aPcb->m_Track; track != NULL; track = track->Next() ) + { + if( track->Type() == PCB_VIA_T ) + { + SEGVIA *via = (SEGVIA*) track; + NETINFO_ITEM *net = aPcb->FindNet( track->GetNet() ); + + D356_RECORD rk; + rk.smd = false; + rk.hole = true; + if( net ) + rk.netname = net->GetNetname(); + else + rk.netname = wxEmptyString; + rk.refdes = wxT("VIA"); + rk.pin = wxT(""); + rk.midpoint = true; // Vias are always midpoints + rk.drill = via->GetDrillValue(); + rk.mechanical = false; + LAYER_NUM top_layer, bottom_layer; + via->ReturnLayerPair( &top_layer, &bottom_layer ); + rk.access = via_access_code( aPcb, top_layer, bottom_layer ); + rk.x_location = via->GetPosition().x - origin.x; + rk.y_location = origin.y - via->GetPosition().y; + rk.x_size = via->GetWidth(); + rk.y_size = 0; // Round so height = 0 + rk.rotation = 0; + rk.soldermask = 3; // XXX always tented? + + aRecords.push_back( rk ); + } + } +} + +/* Add a new netname to the d356 canonicalized list */ +static const wxString intern_new_d356_netname( const wxString &aNetname, + std::map &aMap, std::set &aSet ) +{ + wxString canon; + for (wxString::const_iterator i = aNetname.begin(); + i != aNetname.end(); ++i) + { + // Rule: we can only use the standard ASCII, control excluded + char ch = *i; + if( ch > 126 || !std::isgraph( ch ) ) + ch = '?'; + canon += ch; + } + + // Rule: only uppercase (unofficial, but known to give problems + // otherwise) + canon.MakeUpper(); + + // Rule: maximum length is 14 characters, otherwise we keep the tail + if( canon.size() > 14 ) + { + canon = canon.Right( 14 ); + } + + // Check if it's still unique + if( aSet.count( canon ) ) + { + // Nope, need to uniquify it, trim it more and add a number + wxString base( canon ); + if( base.size() > 10 ) + { + base = base.Right( 10 ); + } + + int ctr = 0; + do + { + ++ctr; + canon = base; + canon << '#' << ctr; + } while ( aSet.count( canon ) ); + } + + // Register it + aMap[aNetname] = canon; + aSet.insert( canon ); + return canon; +} + +/* Write all the accumuled data to the file in D356 format */ +static void write_D356_records( std::vector &aRecords, + FILE *fout ) +{ + // Sanified and shorted network names and set of short names + std::map d356_net_map; + std::set d356_net_set; + + for (unsigned i = 0; i < aRecords.size(); i++) + { + D356_RECORD &rk = aRecords[i]; + + // Try to sanify the network name (there are limits on this), if + // not already done. Also 'empty' net are marked as N/C, as + // specified. + wxString d356_net( wxT("N/C") ); + if( !rk.netname.empty() ) + { + d356_net = d356_net_map[rk.netname]; + + if( d356_net.empty() ) + d356_net = intern_new_d356_netname( rk.netname, d356_net_map, + d356_net_set ); + } + + // Choose the best record type + int rktype; + if( rk.smd ) + rktype = 327; + else + { + if( rk.mechanical ) + rktype = 367; + else + rktype = 317; + } + + // Operation code, signal and component + fprintf( fout, "%03d%-14.14s %-6.6s%c%-4.4s%c", + rktype, TO_UTF8(d356_net), + TO_UTF8(rk.refdes), + rk.pin.empty()?' ':'-', + TO_UTF8(rk.pin), + rk.midpoint?'M':' ' ); + + // Hole definition + if( rk.hole ) + { + fprintf( fout, "D%04d%c", + iu_to_d356( rk.drill, 9999 ), + rk.mechanical ? 'U':'P' ); + } + else + fprintf( fout, " " ); + + // Test point access + fprintf( fout, "A%02dX%+07dY%+07dX%04dY%04dR%03d", + rk.access, + iu_to_d356( rk.x_location, 999999 ), + iu_to_d356( rk.y_location, 999999 ), + iu_to_d356( rk.x_size, 9999 ), + iu_to_d356( rk.y_size, 9999 ), + rk.rotation ); + + // Soldermask + fprintf( fout, "S%d\n", rk.soldermask ); + } +} + +/* Driver function: processing starts here */ +void PCB_EDIT_FRAME::GenD356File( wxCommandEvent& aEvent ) +{ + wxFileName fn = GetBoard()->GetFileName(); + wxString msg, ext, wildcard; + FILE *file; + + ext = wxT( "d356" ); + wildcard = _( "IPC-D-356 Test Files (.d356)|*.d356" ); + fn.SetExt( ext ); + + wxFileDialog dlg( this, _( "Export D-356 Test File" ), wxGetCwd(), + fn.GetFullName(), wildcard, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + if( ( file = wxFopen( dlg.GetPath(), wxT( "wt" ) ) ) == NULL ) + { + msg = _( "Unable to create " ) + dlg.GetPath(); + DisplayError( this, msg ); return; + } + + LOCALE_IO toggle; // Switch the locale to standard C + + // This will contain everything needed for the 356 file + std::vector d356_records; + BOARD* pcb = GetBoard(); + + build_via_testpoints( pcb, d356_records ); + + build_pad_testpoints( pcb, d356_records ); + + // Code 00 AFAIK is ASCII, CUST 0 is decimils/degrees + // CUST 1 would be metric but gerbtool simply ignores it! + fprintf( file, "P CODE 00\n" ); + fprintf( file, "P UNITS CUST 0\n" ); + fprintf( file, "P DIM N\n" ); + write_D356_records( d356_records, file ); + fprintf( file, "999\n" ); + + fclose( file ); +} + From cecd75063e20dae9ae0c518a4e5c6475caca738b Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Sat, 14 Sep 2013 16:33:22 -0400 Subject: [PATCH 21/29] CvPcb footprint library table implementation. * Add code to CvPcb to handle assigning component footprints from the footprint library table instead of the search path method. * Add code to CvPcb to allow editing of the footprint library table. * CvPcb footprint and component panes display fully qualified FPID names. * Make CvPcb library pane display footprint library table nicknames instead of library file names. * Add code to FP_LIB_TABLE object to test the paths in the table against the list of libraries loaded from the project file. * Add code to FP_LIB_TABLE to convert assigned footprints in a NETLIST from legacy format to footprint library table format. * Split out COMPONENT_NET, COMPONENT, and NETLIST objects from netlist_reader files and create new pcb_netlist files. * Fix minor wxListView scroll bar sizing issues. * Add new token and code to save and load FPID nickname in board file. * Add new token and code to save and load FPID nickname in s-expression net list file. * Add WX_STRING_REPORT object to dump strings to a wxString object. --- common/CMakeLists.txt | 1 + common/footprint_info.cpp | 26 ++ common/fp_lib_table.cpp | 218 ++++++++++++++- common/reporter.cpp | 12 +- cvpcb/CMakeLists.txt | 3 + cvpcb/cfg.cpp | 50 +++- cvpcb/class_DisplayFootprintsFrame.cpp | 74 ++++- cvpcb/class_footprints_listbox.cpp | 33 ++- cvpcb/class_library_listbox.cpp | 16 +- cvpcb/cvframe.cpp | 132 ++++++++- cvpcb/cvpcb.h | 11 +- cvpcb/cvpcb_id.h | 3 +- cvpcb/cvpcb_mainframe.h | 30 +- cvpcb/cvstruct.h | 1 - cvpcb/menubar.cpp | 6 + cvpcb/readwrite_dlgs.cpp | 109 +++++++- include/footprint_info.h | 17 +- include/fp_lib_table.h | 43 ++- include/reporter.h | 19 ++ pcbnew/class_board.cpp | 2 +- pcbnew/dialogs/dialog_netlist.cpp | 2 + pcbnew/kicad_netlist_reader.cpp | 2 + pcbnew/legacy_netlist_reader.cpp | 1 + pcbnew/netlist.cpp | 1 + pcbnew/netlist_reader.cpp | 268 +----------------- pcbnew/netlist_reader.h | 331 +--------------------- pcbnew/pcb_netlist.cpp | 278 +++++++++++++++++++ pcbnew/pcb_netlist.h | 367 +++++++++++++++++++++++++ 28 files changed, 1408 insertions(+), 648 deletions(-) create mode 100644 pcbnew/pcb_netlist.cpp create mode 100644 pcbnew/pcb_netlist.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 45a7662fc1..9909a8d54c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -137,6 +137,7 @@ set(PCB_COMMON_SRCS ../pcbnew/legacy_plugin.cpp ../pcbnew/kicad_plugin.cpp ../pcbnew/gpcb_plugin.cpp + ../pcbnew/pcb_netlist.cpp pcb_plot_params_keywords.cpp pcb_keywords.cpp ../pcbnew/pcb_parser.cpp diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index a82f809d7a..5a4ce2970a 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -182,6 +183,31 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE& aTable ) } +FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString & aFootprintName ) +{ + BOOST_FOREACH( FOOTPRINT_INFO& footprint, m_List ) + { +#if defined( USE_FP_LIB_TABLE ) + FPID fpid; + + wxCHECK_MSG( fpid.Parse( TO_UTF8( aFootprintName ) ) < 0, NULL, + wxString::Format( wxT( "<%s> is not a valid FPID." ), + GetChars( aFootprintName ) ) ); + + wxString libNickname = FROM_UTF8( fpid.GetLibNickname().c_str() ); + wxString footprintName = FROM_UTF8( fpid.GetFootprintName().c_str() ); + + if( libNickname == footprint.m_libName && footprintName == footprint.m_Module ) + return &footprint; +#else + if( aFootprintName.CmpNoCase( footprint.m_Module ) == 0 ) + return &footprint; +#endif + } + return NULL; +} + + bool FOOTPRINT_INFO::InLibrary( const wxString& aLibrary ) const { if( aLibrary.IsEmpty() ) diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index c90b0c586a..2ab1ad8290 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -31,10 +31,14 @@ #include #include +#include +#include +#include +#include +#include #include #include - using namespace FP_LIB_TABLE_T; @@ -251,6 +255,35 @@ const FP_LIB_TABLE::ROW* FP_LIB_TABLE::findRow( const wxString& aNickName ) } +const FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRowByURI( const wxString& aURI ) +{ + FP_LIB_TABLE* cur = this; + + do + { + cur->ensureIndex(); + + for( unsigned i = 0; i < cur->rows.size(); i++ ) + { + wxString uri = ExpandSubstitutions( cur->rows[i].GetFullURI() ); + + if( wxFileName::GetPathSeparator() == wxChar( '\\' ) && uri.Find( wxChar( '/' ) ) >= 0 ) + uri.Replace( wxT( "/" ), wxT( "\\" ) ); + + if( (wxFileName::IsCaseSensitive() && uri == aURI) + || (!wxFileName::IsCaseSensitive() && uri.Upper() == aURI.Upper() ) ) + { + return &cur->rows[i]; // found + } + } + + // not found, search fall back table(s), if any + } while( ( cur = cur->fallBack ) != 0 ); + + return 0; // not found +} + + bool FP_LIB_TABLE::InsertRow( const ROW& aRow, bool doReplace ) { ensureIndex(); @@ -281,8 +314,8 @@ const FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRow( const wxString& aLibraryNickName if( !row ) { - wxString msg = wxString::Format( _("lib table contains no logical lib '%s'" ), - GetChars( aLibraryNickName ) ); + wxString msg = wxString::Format( _( "lib table contains no logical lib '%s'" ), + GetChars( aLibraryNickName ) ); THROW_IO_ERROR( msg ); } @@ -320,6 +353,185 @@ bool FP_LIB_TABLE::IsEmpty() const } +bool FP_LIB_TABLE::MissingLegacyLibs( const wxArrayString& aLibNames, wxString* aErrorMsg ) +{ + bool retv = false; + + for( unsigned i = 0; i < aLibNames.GetCount(); i++ ) + { + wxFileName fn = wxFileName( wxEmptyString, aLibNames[i], LegacyFootprintLibPathExtension ); + wxString legacyLibPath = wxGetApp().FindLibraryPath( fn ); + + if( legacyLibPath.IsEmpty() ) + continue; + + if( FindRowByURI( legacyLibPath ) == 0 ) + { + retv = true; + + if( aErrorMsg ) + *aErrorMsg += wxT( "\"" ) + legacyLibPath + wxT( "\"\n" ); + } + } + + return retv; +} + + +bool FP_LIB_TABLE::ConvertFromLegacy( NETLIST& aNetList, const wxArrayString& aLibNames, + REPORTER* aReporter ) throw( IO_ERROR ) +{ + wxString msg; + FPID lastFPID; + COMPONENT* component; + MODULE* module = 0; + bool retv = true; + + if( aNetList.IsEmpty() ) + return true; + + aNetList.SortByFPID(); + + wxString libPath; + wxFileName fn; + + PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) ); + + for( unsigned ii = 0; ii < aNetList.GetCount(); ii++ ) + { + component = aNetList.GetComponent( ii ); + + // The footprint hasn't been assigned yet so ignore it. + if( component->GetFPID().empty() ) + continue; + + if( component->GetFPID() != lastFPID ) + { + module = NULL; + + for( unsigned ii = 0; ii < aLibNames.GetCount(); ii++ ) + { + fn = wxFileName( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension ); + + libPath = wxGetApp().FindLibraryPath( fn ); + + if( !libPath ) + { + if( aReporter ) + { + msg.Printf( _( "Cannot find footprint library file \"%s\" in any of the " + "KiCad legacy library search paths.\n" ), + GetChars( fn.GetFullPath() ) ); + aReporter->Report( msg ); + } + + retv = false; + continue; + } + + module = pi->FootprintLoad( libPath, + FROM_UTF8( component->GetFPID().GetFootprintName().c_str() ) ); + + if( module ) + { + lastFPID = component->GetFPID(); + break; + } + } + } + + if( module == NULL ) + { + if( aReporter ) + { + msg.Printf( _( "Component `%s` footprint <%s> was not found in any legacy " + "library.\n" ), + GetChars( component->GetReference() ), + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); + aReporter->Report( msg ); + } + + // Clear the footprint assignment since the old library lookup method is no + // longer valid. + FPID emptyFPID; + component->SetFPID( emptyFPID ); + retv = false; + continue; + } + else + { + wxLogDebug( wxT( "Found component %s footprint %s in legacy library <%s>." ), + GetChars( component->GetReference() ), + GetChars( GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ), + GetChars( libPath ) ); + + wxString libNickname; + + FP_LIB_TABLE* cur = this; + + do + { + cur->ensureIndex(); + + for( unsigned i = 0; i < cur->rows.size(); i++ ) + { + wxString uri = ExpandSubstitutions( cur->rows[i].GetFullURI() ); + + if( wxFileName::GetPathSeparator() == wxChar( '\\' ) + && uri.Find( wxChar( '/' ) ) >= 0 ) + uri.Replace( wxT( "/"), wxT( "\\" ) ); + + wxLogDebug( wxT( "Comparing legacy path <%s> to lib table path <%s>." ), + GetChars( libPath ), GetChars( uri ) ); + + if( uri == libPath ) + { + libNickname = cur->rows[i].GetNickName(); + break; + } + } + } while( ( cur = cur->fallBack ) != 0 && libNickname.IsEmpty() ); + + if( libNickname.IsEmpty() ) + { + if( aReporter ) + { + msg.Printf( _( "Component `%s` footprint <%s> legacy library path <%s > " + "was not found in the footprint library table.\n" ), + GetChars( component->GetReference() ), + GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); + aReporter->Report( msg ); + } + + retv = false; + } + else + { + FPID newFPID = lastFPID; + + newFPID.SetLibNickname( libNickname ); + + if( !newFPID.IsValid() ) + { + msg.Printf( _( "Component `%s` FPID <%s> is not valid.\n" ), + GetChars( component->GetReference() ), + GetChars( FROM_UTF8( newFPID.Format().c_str() ) ) ); + aReporter->Report( msg ); + retv = false; + } + else + { + // The footprint name should already be set. + component->SetFPID( newFPID ); + } + } + } + } + + return retv; +} + + bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ) { bool tableExists = true; diff --git a/common/reporter.cpp b/common/reporter.cpp index d3297fe4a9..be4372a3b9 100644 --- a/common/reporter.cpp +++ b/common/reporter.cpp @@ -1,5 +1,5 @@ /** - * @file reporter.h + * @file reporter.cpp */ /* * This program source code file is part of KiCad, a free EDA CAD application. @@ -43,3 +43,13 @@ REPORTER& WX_TEXT_CTRL_REPORTER::Report( const wxString& aText ) m_textCtrl->AppendText( aText ); return *this; } + + +REPORTER& WX_STRING_REPORTER::Report( const wxString& aText ) +{ + wxCHECK_MSG( m_string != NULL, *this, + wxT( "No wxString object defined in WX_STRING_REPORTER." ) ); + + *m_string << aText; + return *this; +} diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt index 2447f4cd3e..3e4d8e3f47 100644 --- a/cvpcb/CMakeLists.txt +++ b/cvpcb/CMakeLists.txt @@ -9,6 +9,7 @@ include_directories( ./dialogs ../3d-viewer ../pcbnew + ../pcbnew/dialogs ../polygon ../common ${INC_AFTER} @@ -22,6 +23,8 @@ set( CVPCB_DIALOGS dialogs/dialog_cvpcb_config_fbp.cpp dialogs/dialog_display_options.cpp dialogs/dialog_display_options_base.cpp + ../pcbnew/dialogs/dialog_fp_lib_table.cpp + ../pcbnew/dialogs/dialog_fp_lib_table_base.cpp ) set( CVPCB_SRCS diff --git a/cvpcb/cfg.cpp b/cvpcb/cfg.cpp index f6648a3b67..6d1bb55596 100644 --- a/cvpcb/cfg.cpp +++ b/cvpcb/cfg.cpp @@ -1,6 +1,30 @@ -/*************/ -/** cfg.cpp **/ -/*************/ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007 Jean-Pierre Charras, jean-pierre.charras + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file cfg.cpp + */ #include #include @@ -9,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -59,8 +85,24 @@ void CVPCB_MAINFRAME::LoadProjectFile( const wxString& aFileName ) if( m_NetlistFileExtension.IsEmpty() ) m_NetlistFileExtension = wxT( "net" ); - /* User library path takes precedent over default library search paths. */ + // User library path takes precedent over default library search paths. wxGetApp().InsertLibraryPath( m_UserLibraryPath, 1 ); + +#if defined( USE_FP_LIB_TABLE ) + delete m_footprintLibTable; + + // Attempt to load the project footprint library table if it exists. + m_footprintLibTable = new FP_LIB_TABLE(); + + try + { + m_footprintLibTable->Load( fn, m_globalFootprintTable ); + } + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + } +#endif } diff --git a/cvpcb/class_DisplayFootprintsFrame.cpp b/cvpcb/class_DisplayFootprintsFrame.cpp index b868985389..44810b1abc 100644 --- a/cvpcb/class_DisplayFootprintsFrame.cpp +++ b/cvpcb/class_DisplayFootprintsFrame.cpp @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include #include @@ -473,10 +476,59 @@ EDA_COLOR_T DISPLAY_FOOTPRINTS_FRAME::GetGridColor() const MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) { - CVPCB_MAINFRAME* parent = ( CVPCB_MAINFRAME* ) GetParent(); + MODULE* footprint; try { +#if defined( USE_FP_LIB_TABLE ) + FPID fpid; + + if( fpid.Parse( TO_UTF8( aFootprintName ) ) >= 0 ) + { + DisplayInfoMessage( this, wxString::Format( wxT( "Footprint ID <%s> is not valid." ), + GetChars( aFootprintName ) ) ); + return NULL; + } + + wxString libName = FROM_UTF8( fpid.GetLibNickname().c_str() ); + + wxLogDebug( wxT( "Load footprint <%s> from library <%s>." ), + fpid.GetFootprintName().c_str(), fpid.GetLibNickname().c_str() ); + + const FP_LIB_TABLE::ROW* row; + + try + { + row = m_footprintLibTable->FindRow( libName ); + + if( row == NULL ) + { + wxString msg; + msg.Printf( _( "No library named <%s> was found in the footprint library table." ), + fpid.GetLibNickname().c_str() ); + DisplayInfoMessage( this, msg ); + return NULL; + } + } + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + } + + wxString footprintName = FROM_UTF8( fpid.GetFootprintName().c_str() ); + wxString libPath = row->GetFullURI(); + + libPath = FP_LIB_TABLE::ExpandSubstitutions( libPath ); + + wxLogDebug( wxT( "Loading footprint <%s> from library <%s>." ), + GetChars( footprintName ), GetChars( libPath ) ); + + PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::EnumFromStr( row->GetType() ) ) ); + + footprint = pi->FootprintLoad( libPath, footprintName ); +#else + CVPCB_MAINFRAME* parent = ( CVPCB_MAINFRAME* ) GetParent(); + PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) ); for( unsigned i = 0; i < parent->m_ModuleLibNames.GetCount(); ++i ) @@ -493,19 +545,13 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) fn.GetFullName().GetData() ); // @todo we should not be using wxMessageBox directly. - wxMessageBox( msg, titleLibLoadError, wxOK | wxICON_ERROR, this ); + wxMessageBox( msg, wxEmptyString, wxOK | wxICON_ERROR, this ); continue; } - MODULE* footprint = pi->FootprintLoad( libPath, aFootprintName ); - - if( footprint ) - { - footprint->SetParent( (EDA_ITEM*) GetBoard() ); - footprint->SetPosition( wxPoint( 0, 0 ) ); - return footprint; - } + footprint = pi->FootprintLoad( libPath, aFootprintName ); } +#endif } catch( IO_ERROR ioe ) { @@ -513,6 +559,13 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) return NULL; } + if( footprint ) + { + footprint->SetParent( (EDA_ITEM*) GetBoard() ); + footprint->SetPosition( wxPoint( 0, 0 ) ); + return footprint; + } + wxString msg = wxString::Format( _( "Footprint '%s' not found" ), aFootprintName.GetData() ); DisplayError( this, msg ); return NULL; @@ -532,6 +585,7 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay() FOOTPRINT_INFO* module_info = parentframe->m_footprints.GetModuleInfo( footprintName ); const wxChar *libname; + if( module_info ) libname = GetChars( module_info->GetLibraryPath() ); else diff --git a/cvpcb/class_footprints_listbox.cpp b/cvpcb/class_footprints_listbox.cpp index 22e0c94477..e50a61fd10 100644 --- a/cvpcb/class_footprints_listbox.cpp +++ b/cvpcb/class_footprints_listbox.cpp @@ -135,8 +135,14 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a { if( aFilterType == UNFILTERED ) { +#if !defined( USE_FP_LIB_TABLE ) msg.Printf( wxT( "%3zu %s" ), newList.GetCount() + 1, GetChars( aList.GetItem( ii ).m_Module ) ); +#else + msg.Printf( wxT( "%3zu %s:%s" ), newList.GetCount() + 1, + GetChars( aList.GetItem( ii ).GetLibraryName() ), + GetChars( aList.GetItem( ii ).m_Module ) ); +#endif newList.Add( msg ); continue; } @@ -153,8 +159,14 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a && (aComponent->GetNetCount() != aList.GetItem( ii ).m_padCount) ) continue; +#if !defined( USE_FP_LIB_TABLE ) msg.Printf( wxT( "%3zu %s" ), newList.GetCount() + 1, aList.GetItem( ii ).m_Module.GetData() ); +#else + msg.Printf( wxT( "%3zu %s:%s" ), newList.GetCount() + 1, + GetChars( aList.GetItem( ii ).GetLibraryName() ), + GetChars( aList.GetItem( ii ).m_Module ) ); +#endif newList.Add( msg ); } @@ -169,9 +181,24 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a selection = 0; DeleteAllItems(); - SetItemCount( m_footprintList.GetCount() ); - SetSelection( selection, true ); - Refresh(); + + if( m_footprintList.GetCount() ) + { + SetItemCount( m_footprintList.GetCount() ); + SetSelection( selection, true ); + RefreshItems( 0L, m_footprintList.GetCount()-1 ); + +#if defined (__WXGTK__ ) + // @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the + // column parameter is -1. This was the only way to prevent GTK3 from + // ellipsizing long strings down to a few characters. It still doesn't set + // the scroll bars correctly (too short) but it's better than any of the + // other alternatives. If someone knows how to fix this, please do. + SetColumnWidth( -1, wxLIST_AUTOSIZE ); +#else + SetColumnWidth( 0, wxLIST_AUTOSIZE ); +#endif + } } diff --git a/cvpcb/class_library_listbox.cpp b/cvpcb/class_library_listbox.cpp index 9c3e6cd0dd..5c7f76256f 100644 --- a/cvpcb/class_library_listbox.cpp +++ b/cvpcb/class_library_listbox.cpp @@ -124,7 +124,21 @@ void LIBRARY_LISTBOX::SetLibraryList( const wxArrayString& aList ) if( GetCount() == 0 || oldSelection < 0 || oldSelection >= GetCount() ) SetSelection( 0, true ); - Refresh(); + if( m_libraryList.Count() ) + { + RefreshItems( 0L, m_libraryList.Count()-1 ); + +#if defined (__WXGTK__ ) + // @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the + // column parameter is -1. This was the only way to prevent GTK3 from + // ellipsizing long strings down to a few characters. It still doesn't set + // the scroll bars correctly (too short) but it's better than any of the + // other alternatives. If someone knows how to fix this, please do. + SetColumnWidth( -1, wxLIST_AUTOSIZE ); +#else + SetColumnWidth( 0, wxLIST_AUTOSIZE ); +#endif + } } diff --git a/cvpcb/cvframe.cpp b/cvpcb/cvframe.cpp index 6a17bdbc6b..08e669e7d8 100644 --- a/cvpcb/cvframe.cpp +++ b/cvpcb/cvframe.cpp @@ -28,22 +28,25 @@ */ #include +#include #include #include #include #include #include #include +#include +#include +#include +#include #include +#include #include #include #include #include -#include -#include -#include #define FRAME_MIN_SIZE_X 450 #define FRAME_MIN_SIZE_Y 300 @@ -54,6 +57,16 @@ static const wxString KeepCvpcbOpenEntry( wxT( "KeepCvpcbOpen" ) ); static const wxString FootprintDocFileEntry( wxT( "footprints_doc_file" ) ); +/** + * Function InvokePcbLibTableEditor + * shows the modal DIALOG_FP_LIB_TABLE for purposes of editing two lib tables. + * + * @return int - bits 0 and 1 tell whether a change was made to the @a aGlobal + * and/or the @a aProject table, respectively. If set, table was modified. + */ +int InvokePcbLibTableEditor( wxFrame* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TABLE* aProject ); + + BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME ) EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, CVPCB_MAINFRAME::LoadNetList ) @@ -69,6 +82,10 @@ BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME ) EVT_MENU( ID_SAVE_PROJECT_AS, CVPCB_MAINFRAME::SaveProjectFile ) EVT_MENU( ID_CVPCB_CONFIG_KEEP_OPEN_ON_SAVE, CVPCB_MAINFRAME::OnKeepOpenOnSave ) +#if defined( USE_FP_LIB_TABLE ) + EVT_MENU( ID_CVPCB_LIB_TABLE_EDIT, CVPCB_MAINFRAME::OnEditFootprintLibraryTable ) +#endif + EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, CVPCB_MAINFRAME::SetLanguage ) // Toolbar events @@ -114,6 +131,11 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( const wxString& title, long style ) : m_undefinedComponentCnt = 0; m_skipComponentSelect = false; +#if defined( USE_FP_LIB_TABLE ) + m_globalFootprintTable = NULL; + m_footprintLibTable = NULL; +#endif + /* Name of the document footprint list * usually located in share/modules/footprints_doc * this is of the responsibility to users to create this file @@ -185,6 +207,39 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( const wxString& title, long style ) : Right().BestSize( (int) ( m_FrameSize.x * 0.30 ), m_FrameSize.y ) ); m_auimgr.Update(); + +#if defined( USE_FP_LIB_TABLE ) + if( m_globalFootprintTable == NULL ) + { + try + { + m_globalFootprintTable = new FP_LIB_TABLE(); + + if( !FP_LIB_TABLE::LoadGlobalTable( *m_globalFootprintTable ) ) + { + DisplayInfoMessage( this, wxT( "You have run CvPcb for the first time using the " + "new footprint library table method of finding " + "footprints. CvPcb has either copied the default " + "table or created an empty table in your home " + "folder. You must first configure the library " + "table to include all footprint libraries not " + "included with KiCad. See the \"Footprint Library " + "Table\" section of the CvPcb documentation for " + "more information." ) ); + } + } + catch( IO_ERROR ioe ) + { + wxString msg; + msg.Printf( _( "An error occurred attempting to load the global footprint library " + "table:\n\n%s" ), GetChars( ioe.errorText ) ); + DisplayError( this, msg ); + } + + m_footprintLibTable = new FP_LIB_TABLE( m_globalFootprintTable ); + } +#endif + } @@ -466,6 +521,30 @@ void CVPCB_MAINFRAME::ConfigCvpcb( wxCommandEvent& event ) } +#if defined( USE_FP_LIB_TABLE ) +void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent ) +{ + int r = InvokePcbLibTableEditor( this, m_globalFootprintTable, m_footprintLibTable ); + + if( r & 1 ) + { + FILE_OUTPUTFORMATTER sf( FP_LIB_TABLE::GetGlobalTableFileName() ); + m_globalFootprintTable->Format( &sf, 0 ); + } + + if( r & 2 ) + { + wxFileName fn = m_NetlistFileName; + fn.SetName( FP_LIB_TABLE::GetFileName() ); + fn.SetExt( wxEmptyString ); + + FILE_OUTPUTFORMATTER sf( fn.GetFullPath() ); + m_footprintLibTable->Format( &sf, 0 ); + } +} +#endif + + void CVPCB_MAINFRAME::OnKeepOpenOnSave( wxCommandEvent& event ) { m_KeepCvpcbOpen = event.IsChecked(); @@ -523,7 +602,7 @@ void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event ) // selected footprint. if( FindFocus() == m_ListCmp || FindFocus() == m_LibraryList ) { - wxString module = FROM_UTF8( component->GetFPID().GetFootprintName().c_str() ); + wxString module = FROM_UTF8( component->GetFPID().Format().c_str() ); bool found = false; @@ -667,7 +746,12 @@ bool CVPCB_MAINFRAME::LoadFootprintFiles() return false; } +#if !defined( USE_FP_LIB_TABLE ) m_footprints.ReadFootprintFiles( m_ModuleLibNames ); +#else + if( m_footprintLibTable != NULL ) + m_footprints.ReadFootprintFiles( *m_footprintLibTable ); +#endif // Display error messages, if any. if( !m_footprints.m_filesNotFound.IsEmpty() || !m_footprints.m_filesInvalid.IsEmpty() ) @@ -770,7 +854,7 @@ int CVPCB_MAINFRAME::ReadSchematicNetlist() netlistReader->LoadNetlist(); } else - wxMessageBox( _( "Unknown netlist format" ), wxEmptyString, wxOK | wxICON_ERROR ); + wxMessageBox( _( "Unknown netlist format." ), wxEmptyString, wxOK | wxICON_ERROR ); } catch( IO_ERROR& ioe ) { @@ -852,6 +936,11 @@ void CVPCB_MAINFRAME::CreateScreenCmp() wxPoint( 0, 0 ), wxSize( 600, 400 ), KICAD_DEFAULT_DRAWFRAME_STYLE ); + +#if defined( USE_FP_LIB_TABLE ) + m_DisplayFootprintFrame->SetFootprintLibTable( m_footprintLibTable ); +#endif + m_DisplayFootprintFrame->Show( true ); } else @@ -913,8 +1002,23 @@ void CVPCB_MAINFRAME::BuildCmpListBox() m_ListCmp->m_ComponentList.Add( msg ); } - m_ListCmp->SetItemCount( m_ListCmp->m_ComponentList.Count() ); - m_ListCmp->SetSelection( 0, true ); + if( m_ListCmp->m_ComponentList.Count() ) + { + m_ListCmp->SetItemCount( m_ListCmp->m_ComponentList.Count() ); + m_ListCmp->SetSelection( 0, true ); + m_ListCmp->RefreshItems( 0L, m_ListCmp->m_ComponentList.Count()-1 ); + +#if defined (__WXGTK__ ) + // @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the + // column parameter is -1. This was the only way to prevent GTK3 from + // ellipsizing long strings down to a few characters. It still doesn't set + // the scroll bars correctly (too short) but it's better than any of the + // other alternatives. If someone knows how to fix this, please do. + m_ListCmp->SetColumnWidth( -1, wxLIST_AUTOSIZE ); +#else + m_ListCmp->SetColumnWidth( 0, wxLIST_AUTOSIZE ); +#endif + } } @@ -932,7 +1036,21 @@ void CVPCB_MAINFRAME::BuildLIBRARY_LISTBOX() wxFONTWEIGHT_NORMAL ) ); } +#if defined( USE_FP_LIB_TABLE ) + if( m_footprintLibTable ) + { + wxArrayString libNames; + + std::vector< wxString > libNickNames = m_footprintLibTable->GetLogicalLibs(); + + for( unsigned ii = 0; ii < libNickNames.size(); ii++ ) + libNames.Add( libNickNames[ii] ); + + m_LibraryList->SetLibraryList( libNames ); + } +#else m_LibraryList->SetLibraryList( m_ModuleLibNames ); +#endif } diff --git a/cvpcb/cvpcb.h b/cvpcb/cvpcb.h index c506ea41df..5b91f21640 100644 --- a/cvpcb/cvpcb.h +++ b/cvpcb/cvpcb.h @@ -5,21 +5,16 @@ #ifndef __CVPCB_H__ #define __CVPCB_H__ -#include - -#include -#include - - // config for footprints doc file access #define DEFAULT_FOOTPRINTS_LIST_FILENAME wxT( "footprints_doc/footprints.pdf" ) // Define print format to display a schematic component line -#define CMP_FORMAT wxT( "%3d %8s - %16s : %-.32s" ) +#define CMP_FORMAT wxT( "%3d %8s - %16s : %s" ) #define FILTERFOOTPRINTKEY "FilterFootprint" -#define LISTB_STYLE (wxSUNKEN_BORDER | wxLC_NO_HEADER | wxLC_REPORT | wxLC_VIRTUAL) +#define LISTB_STYLE ( wxSUNKEN_BORDER | wxLC_NO_HEADER | wxLC_REPORT | wxLC_VIRTUAL | \ + wxLC_SINGLE_SEL | wxVSCROLL | wxHSCROLL ) extern const wxString FootprintAliasFileExtension; extern const wxString RetroFileExtension; diff --git a/cvpcb/cvpcb_id.h b/cvpcb/cvpcb_id.h index 7ac8ce95ad..6229f87947 100644 --- a/cvpcb/cvpcb_id.h +++ b/cvpcb/cvpcb_id.h @@ -32,5 +32,6 @@ enum id_cvpcb_frm ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST, ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST, ID_CVPCB_CONFIG_KEEP_OPEN_ON_SAVE, - ID_CVPCB_LIBRARY_LIST + ID_CVPCB_LIBRARY_LIST, + ID_CVPCB_LIB_TABLE_EDIT }; diff --git a/cvpcb/cvpcb_mainframe.h b/cvpcb/cvpcb_mainframe.h index 69fe7a03bc..7fea960ec2 100644 --- a/cvpcb/cvpcb_mainframe.h +++ b/cvpcb/cvpcb_mainframe.h @@ -31,12 +31,11 @@ #include #include -#include +#include #include #include #include -#include /* Forward declarations of all top-level window classes. */ @@ -46,6 +45,7 @@ class COMPONENTS_LISTBOX; class LIBRARY_LISTBOX; class DISPLAY_FOOTPRINTS_FRAME; class COMPONENT; +class FP_LIB_TABLE; /** @@ -55,6 +55,16 @@ class CVPCB_MAINFRAME : public EDA_BASE_FRAME { wxArrayString m_footprintListEntries; +#if defined( USE_FP_LIB_TABLE ) + /// The global footprint library table. + FP_LIB_TABLE* m_globalFootprintTable; + + /// The project footprint library table. This is a combination of the project + /// footprint library table and the global footprint table. This is the one to + /// use when finding a #MODULE. + FP_LIB_TABLE* m_footprintLibTable; +#endif + public: bool m_KeepCvpcbOpen; FOOTPRINTS_LISTBOX* m_FootprintList; @@ -92,6 +102,13 @@ public: */ void OnSelectComponent( wxListEvent& event ); + /** + * Function OnEditFootrprintLibraryTable + * displays the footprint library table editing dialog and updates the global and local + * footprint tables accordingly. + */ + void OnEditFootrprintLibraryTable( wxCommandEvent& event ); + void OnQuit( wxCommandEvent& event ); void OnCloseWindow( wxCloseEvent& Event ); void OnSize( wxSizeEvent& SizeEvent ); @@ -126,6 +143,15 @@ public: void LoadNetList( wxCommandEvent& event ); void ConfigCvpcb( wxCommandEvent& event ); + + /** + * Function OnEditLibraryTable + * envokes the footpirnt library table edit dialog. + */ +#if defined( USE_FP_LIB_TABLE ) + void OnEditFootprintLibraryTable( wxCommandEvent& aEvent ); +#endif + void OnKeepOpenOnSave( wxCommandEvent& event ); void DisplayModule( wxCommandEvent& event ); diff --git a/cvpcb/cvstruct.h b/cvpcb/cvstruct.h index a2d2eb7701..579aa44dc6 100644 --- a/cvpcb/cvstruct.h +++ b/cvpcb/cvstruct.h @@ -30,7 +30,6 @@ #include -#include /* Forward declarations of all top-level window classes. */ class CVPCB_MAINFRAME; diff --git a/cvpcb/menubar.cpp b/cvpcb/menubar.cpp index f7c188d4aa..bceb5170bf 100644 --- a/cvpcb/menubar.cpp +++ b/cvpcb/menubar.cpp @@ -110,11 +110,17 @@ void CVPCB_MAINFRAME::ReCreateMenuBar() // Menu Preferences: wxMenu* preferencesMenu = new wxMenu; +#if !defined( USE_FP_LIB_TABLE ) // Libraries to load AddMenuItem( preferencesMenu, wxID_PREFERENCES, _( "&Libraries" ), _( "Set footprint libraries to load and library search paths" ), KiBitmap( config_xpm ) ); +#else + AddMenuItem( preferencesMenu, ID_CVPCB_LIB_TABLE_EDIT, + _( "Li&brary Tables" ), _( "Setup footprint libraries" ), + KiBitmap( library_table_xpm ) ); +#endif // Language submenu wxGetApp().AddMenuLanguageList( preferencesMenu ); diff --git a/cvpcb/readwrite_dlgs.cpp b/cvpcb/readwrite_dlgs.cpp index cb239ce3ff..4eb58bf9b5 100644 --- a/cvpcb/readwrite_dlgs.cpp +++ b/cvpcb/readwrite_dlgs.cpp @@ -31,6 +31,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -50,7 +55,6 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) return; // If no component is selected, select the first one - if( m_ListCmp->GetFirstSelected() < 0 ) { componentIndex = 0; @@ -58,11 +62,9 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) } // iterate over the selection - - while( m_ListCmp->GetFirstSelected() != -1) + while( m_ListCmp->GetFirstSelected() != -1 ) { // Get the component for the current iteration - componentIndex = m_ListCmp->GetFirstSelected(); component = m_netlist.GetComponent( componentIndex ); @@ -70,13 +72,21 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) return; // Check to see if the component has already a footprint set. - hasFootprint = !component->GetFPID().empty(); +#if defined( USE_FP_LIB_TABLE ) + FPID fpid; + + wxCHECK_RET( fpid.Parse( TO_UTF8( aFootprintName ) ) < 0, + wxString::Format( wxT( "<%s> is not a valid FPID." ), + GetChars( aFootprintName ) ) ); + + component->SetFPID( fpid ); +#else component->SetFPID( FPID( aFootprintName ) ); +#endif // create the new component description - description.Printf( CMP_FORMAT, componentIndex + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), @@ -85,7 +95,6 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) // If the component hasn't had a footprint associated with it // it now has, so we decrement the count of components without // a footprint assigned. - if( !hasFootprint ) { hasFootprint = true; @@ -115,6 +124,7 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() { COMPONENT* component; wxString msg; + bool isLegacy = true; ReadSchematicNetlist(); @@ -129,6 +139,87 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() m_ListCmp->Clear(); m_undefinedComponentCnt = 0; + if( m_netlist.AnyFootprintsLinked() ) + { + for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) + { + component = m_netlist.GetComponent( i ); + + if( component->GetFPID().empty() ) + continue; + + if( isLegacy ) + { + if( !component->GetFPID().IsLegacy() ) + isLegacy = false; + } + } + } + else + { + isLegacy = false; // None of the components have footprints assigned. + } + + +#if defined( USE_FP_LIB_TABLE ) + wxString missingLibs; + + // Check if footprint links were generated before the footprint library table was implemented. + if( isLegacy ) + { + if( m_footprintLibTable->MissingLegacyLibs( m_ModuleLibNames, &missingLibs ) ) + { + msg = wxT( "The following legacy libraries are defined in the project file " + "were not found in the footprint library table:\n\n" ) + missingLibs; + msg += wxT( "\nDo you want to update the footprint library table before " + "attempting to update the assigned footprints?" ); + + if( IsOK( this, msg ) ) + { + wxCommandEvent cmd; + + OnEditFootprintLibraryTable( cmd ); + } + } + + msg = wxT( "Some or all of the assigned footprints contain legacy entries. Would you " + "like CvPcb to attempt to convert them to the new footprint library table " + "format?" ); + + if( IsOK( this, msg ) ) + { + msg.Clear(); + WX_STRING_REPORTER reporter( &msg ); + + if( !m_footprintLibTable->ConvertFromLegacy( m_netlist, m_ModuleLibNames, &reporter ) ) + { + HTML_MESSAGE_BOX dlg( this, wxEmptyString ); + + dlg.MessageSet( wxT( "The following errors occurred attempt to convert the " + "footprint assignments:\n\n" ) ); + dlg.ListSet( msg ); + dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them " + "to be updated correctly the next time you import the " + "netlist in Pcbnew." ) ); + dlg.ShowModal(); + } + + m_modified = true; + } + else + { + // Clear the legacy footprint assignments. + for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) + { + FPID emptyFPID; + component = m_netlist.GetComponent( i ); + component->SetFPID( emptyFPID ); + m_modified = true; + } + } + } +#endif + for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); @@ -137,10 +228,14 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); + m_ListCmp->AppendLine( msg ); if( component->GetFPID().empty() ) + { m_undefinedComponentCnt += 1; + continue; + } } if( !m_netlist.IsEmpty() ) diff --git a/include/footprint_info.h b/include/footprint_info.h index ccdba621db..0035938cfa 100644 --- a/include/footprint_info.h +++ b/include/footprint_info.h @@ -102,15 +102,7 @@ public: * @return the item stored in list if found * @param aFootprintName = the name of item */ - FOOTPRINT_INFO * GetModuleInfo( const wxString & aFootprintName ) - { - BOOST_FOREACH( FOOTPRINT_INFO& footprint, m_List ) - { - if( aFootprintName.CmpNoCase( footprint.m_Module ) == 0 ) - return &footprint; - } - return NULL; - } + FOOTPRINT_INFO* GetModuleInfo( const wxString & aFootprintName ); /** * Function GetItem @@ -159,6 +151,13 @@ public: /// FOOTPRINT object list sort function. inline bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2 ) { +#if defined( USE_FP_LIB_TABLE ) + int retv = StrNumCmp( item1.m_libName, item2.m_libName, INT_MAX, true ); + + if( retv != 0 ) + return retv < 0; +#endif + return StrNumCmp( item1.m_Module, item2.m_Module, INT_MAX, true ) < 0; } diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index f9f64fa9ff..98796040fc 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -31,13 +31,16 @@ #include #include -//#include #include +class wxFileName; class OUTPUTFORMATTER; class MODULE; class FP_LIB_TABLE_LEXER; +class NETLIST; +class REPORTER; + /** * Class FP_LIB_TABLE @@ -355,12 +358,50 @@ public: */ const ROW* FindRow( const wxString& aNickName ) throw( IO_ERROR ); + /** + * Function FindRowByURI + * returns a #ROW if aURE is found in this table or in any chained + * fallBack table fragments, else NULL. + */ + const ROW* FindRowByURI( const wxString& aURI ); + /** * Function IsEmpty * @return true if the footprint library table is empty. */ bool IsEmpty() const; + /** + * Function MissingLegacyLibs + * tests the list of \a aLibNames by URI to determine if any of them are missing from + * the #FP_LIB_TABLE. + * + * @note The missing legacy footprint library test is performed by using old library + * file path lookup method. If the library is found, it is compared against all + * of the URIs in the table rather than the nickname. This was done because the + * user could change the nicknames from the default table. Using the full path + * is more reliable. + * + * @param aLibNames is the list of legacy library names. + * @param aErrorMsg is a pointer to a wxString object to store the URIs of any missing + * legacy library paths. Can be NULL. + * @return true if there are missing legacy libraries. Otherwise false. + */ + bool MissingLegacyLibs( const wxArrayString& aLibNames, wxString* aErrorMsg = NULL ); + + /** + * Function ConvertFromLegacy + * converts the footprint names in \a aNetList from the legacy fromat to the #FPID format. + * + * @param aNetList is the #NETLIST object to convert. + * @param aLibNames is the list of legacy footprint library names from the currently loaded + * project. + * @param aReporter is the #REPORTER object to dump messages into. + * @return true if all footprint names were successfully converted to a valid FPID. + */ + bool ConvertFromLegacy( NETLIST& aNetList, const wxArrayString& aLibNames, + REPORTER* aReporter = NULL ) throw( IO_ERROR ); + /** * Function ExpandEnvSubsitutions * replaces any environment variable references with their values and is diff --git a/include/reporter.h b/include/reporter.h index 0fcbb7eec7..42d4c1fa34 100644 --- a/include/reporter.h +++ b/include/reporter.h @@ -136,4 +136,23 @@ public: REPORTER& Report( const wxString& aText ); }; + +/** + * Class WX_STRING_REPROTER + * is a wrapper for reporting to a wxString object. + */ +class WX_STRING_REPORTER : public REPORTER +{ + wxString* m_string; + +public: + WX_STRING_REPORTER( wxString* aString ) : + REPORTER(), + m_string( aString ) + { + } + + REPORTER& Report( const wxString& aText ); +}; + #endif // _REPORTER_H_ diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index a3f47416c3..d7e8dcb6cd 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include diff --git a/pcbnew/dialogs/dialog_netlist.cpp b/pcbnew/dialogs/dialog_netlist.cpp index 2137cf886c..6315e63a00 100644 --- a/pcbnew/dialogs/dialog_netlist.cpp +++ b/pcbnew/dialogs/dialog_netlist.cpp @@ -29,11 +29,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include diff --git a/pcbnew/kicad_netlist_reader.cpp b/pcbnew/kicad_netlist_reader.cpp index 912c13cba2..fb40685ee8 100644 --- a/pcbnew/kicad_netlist_reader.cpp +++ b/pcbnew/kicad_netlist_reader.cpp @@ -28,6 +28,8 @@ #include #include // netlist_lexer is common to Eeschema and Pcbnew #include + +#include #include using namespace NL_T; diff --git a/pcbnew/legacy_netlist_reader.cpp b/pcbnew/legacy_netlist_reader.cpp index 6b415bcf82..e215a67720 100644 --- a/pcbnew/legacy_netlist_reader.cpp +++ b/pcbnew/legacy_netlist_reader.cpp @@ -31,6 +31,7 @@ #include #include +#include #include diff --git a/pcbnew/netlist.cpp b/pcbnew/netlist.cpp index 1f8fe80b29..c1ecf930f1 100644 --- a/pcbnew/netlist.cpp +++ b/pcbnew/netlist.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/pcbnew/netlist_reader.cpp b/pcbnew/netlist_reader.cpp index c1b50fd79e..a970d53940 100644 --- a/pcbnew/netlist_reader.cpp +++ b/pcbnew/netlist_reader.cpp @@ -31,267 +31,13 @@ #include #include +#include #include #include #include -#if defined(DEBUG) -/** - * Function NestedSpace - * outputs nested space for pretty indenting. - * @param aNestLevel The nest count - * @param aReporter A reference to a #REPORTER object where to output. - * @return REPORTER& for continuation. - **/ -static REPORTER& NestedSpace( int aNestLevel, REPORTER& aReporter ) -{ - for( int i = 0; i < aNestLevel; ++i ) - aReporter.Report( wxT( " " ) ); - - return aReporter; -} - - -void COMPONENT_NET::Show( int aNestLevel, REPORTER& aReporter ) -{ - NestedSpace( aNestLevel, aReporter ); - aReporter.Report( wxString::Format( wxT( "\n" ), - GetChars( m_pinName ), GetChars( m_netName ) ) ); -} -#endif - - -void COMPONENT::SetModule( MODULE* aModule ) -{ - m_footprint.reset( aModule ); - - if( aModule == NULL ) - return; - - aModule->SetReference( m_reference ); - aModule->SetValue( m_value ); - aModule->SetFPID( m_fpid ); - aModule->SetPath( m_timeStamp ); -} - - -COMPONENT_NET COMPONENT::m_emptyNet; - - -const COMPONENT_NET& COMPONENT::GetNet( const wxString& aPinName ) -{ - for( unsigned i = 0; i < m_nets.size(); i++ ) - { - if( m_nets[i].GetPinName() == aPinName ) - return m_nets[i]; - } - - return m_emptyNet; -} - - -bool COMPONENT::MatchesFootprintFilters( const wxString& aFootprintName ) const -{ - if( m_footprintFilters.GetCount() == 0 ) - return true; - - // The matching is case insensitive - wxString name = aFootprintName.Upper(); - - for( unsigned ii = 0; ii < m_footprintFilters.GetCount(); ii++ ) - { - if( name.Matches( m_footprintFilters[ii].Upper() ) ) - return true; - } - - return false; -} - - -#if defined(DEBUG) -void COMPONENT::Show( int aNestLevel, REPORTER& aReporter ) -{ - NestedSpace( aNestLevel, aReporter ); - aReporter.Report( wxT( "\n" ) ); - NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( wxString::Format( wxT( "\n" ), - GetChars( m_reference ), GetChars( m_value ), - GetChars( m_name ), GetChars( m_library ), - m_fpid.Format().c_str(), - GetChars( m_timeStamp ) ) ); - - if( !m_footprintFilters.IsEmpty() ) - { - NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( wxT( "\n" ) ); - - for( unsigned i = 0; i < m_footprintFilters.GetCount(); i++ ) - { - NestedSpace( aNestLevel+2, aReporter ); - aReporter.Report( wxString::Format( wxT( "<%s>\n" ), - GetChars( m_footprintFilters[i] ) ) ); - } - - NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( wxT( "\n" ) ); - } - - if( !m_nets.empty() ) - { - NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( wxT( "\n" ) ); - - for( unsigned i = 0; i < m_nets.size(); i++ ) - m_nets[i].Show( aNestLevel+3, aReporter ); - - NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( "\n" ); - } - - NestedSpace( aNestLevel, aReporter ); - aReporter.Report( "\n" ); -} -#endif - - -void NETLIST::AddComponent( COMPONENT* aComponent ) -{ - m_components.push_back( aComponent ); -} - - -COMPONENT* NETLIST::GetComponentByReference( const wxString& aReference ) -{ - COMPONENT* component = NULL; - - for( unsigned i = 0; i < m_components.size(); i++ ) - { - if( m_components[i].GetReference() == aReference ) - { - component = &m_components[i]; - break; - } - } - - return component; -} - - -COMPONENT* NETLIST::GetComponentByTimeStamp( const wxString& aTimeStamp ) -{ - COMPONENT* component = NULL; - - for( unsigned i = 0; i < m_components.size(); i++ ) - { - if( m_components[i].GetTimeStamp() == aTimeStamp ) - { - component = &m_components[i]; - break; - } - } - - return component; -} - - -/** - * Function ByFPID - * is a helper function used to sort the component list used by loadNewModules. - */ -static bool ByFPID( const COMPONENT& ref, const COMPONENT& cmp ) -{ - return ref.GetFPID() > cmp.GetFPID(); -} - - -void NETLIST::SortByFPID() -{ - m_components.sort( ByFPID ); -} - - -/** - * Operator < - * compares two #COMPONENT objects by reference designator. - */ -bool operator < ( const COMPONENT& item1, const COMPONENT& item2 ) -{ - return StrNumCmp( item1.GetReference(), item2.GetReference(), INT_MAX, true ) < 0; -} - - -void NETLIST::SortByReference() -{ - m_components.sort(); -} - - -bool NETLIST::AnyFootprintsLinked() const -{ - for( unsigned i = 0; i < m_components.size(); i++ ) - { - if( !m_components[i].GetFPID().empty() ) - return true; - } - - return false; -} - - -bool NETLIST::AllFootprintsLinked() const -{ - for( unsigned i = 0; i < m_components.size(); i++ ) - { - if( m_components[i].GetFPID().empty() ) - return false; - } - - return true; -} - - -bool NETLIST::AnyFootprintsChanged() const -{ - for( unsigned i = 0; i < m_components.size(); i++ ) - { - if( m_components[i].FootprintChanged() ) - return true; - } - - return false; -} - - -#if defined( DEBUG ) -void NETLIST::Show( int aNestLevel, REPORTER& aReporter ) -{ - NestedSpace( aNestLevel, aReporter ); - aReporter.Report( "\n" ); - - if( !m_components.empty() ) - { - NestedSpace( aNestLevel+1, aReporter ); - aReporter.Report( "\n" ); - - for( unsigned i = 0; i < m_components.size(); i++ ) - { - m_components[i].Show( aNestLevel+2, aReporter ); - } - - NestedSpace( aNestLevel+1, aReporter ); - - aReporter.Report( "\n" ); - } - - NestedSpace( aNestLevel, aReporter ); - aReporter.Report( "\n" ); -} -#endif - - NETLIST_READER::~NETLIST_READER() { if( m_lineReader ) @@ -308,7 +54,6 @@ NETLIST_READER::~NETLIST_READER() } - NETLIST_READER::NETLIST_FILE_T NETLIST_READER::GuessNetlistFileType( LINE_READER* aLineReader ) { // Orcad Pcb2 netlist format starts by "( {", followed by an unknown comment, @@ -447,14 +192,17 @@ bool CMP_READER::Load( NETLIST* aNetlist ) throw( IO_ERROR, PARSE_ERROR ) // Find the corresponding item in component list: COMPONENT* component = aNetlist->GetComponentByReference( reference ); - // the corresponding component could be no more existing in netlist: - // this is the case when it is just removed from schematic, - // and still exists in footprint assignment list, before this list is updated - // This is an usual case during the life of a design + // The corresponding component could no longer existing in the netlist. This + // can happed when it is removed from schematic and still exists in footprint + // assignment list. This is an usual case during the life of a design. if( component ) + { component->SetFPID( FPID( footprint ) ); + } else + { ok = false; // can be used to display a warning in Pcbnew. + } } return ok; diff --git a/pcbnew/netlist_reader.h b/pcbnew/netlist_reader.h index ef8600de46..3db2236003 100644 --- a/pcbnew/netlist_reader.h +++ b/pcbnew/netlist_reader.h @@ -42,335 +42,8 @@ using namespace NL_T; -class MODULE; -class LINE_READER; -class REPORTER; - - -/** - * Class COMPONENT_NET - * is used to store the component pin name to net name associations stored in a netlist. - */ -class COMPONENT_NET -{ - wxString m_pinName; - wxString m_netNumber; - wxString m_netName; - -public: - COMPONENT_NET() {} - - COMPONENT_NET( const wxString& aPinName, const wxString& aNetName ) - { - m_pinName = aPinName; - m_netName = aNetName; - } - - const wxString& GetPinName() const { return m_pinName; } - - const wxString& GetNetName() const { return m_netName; } - - bool IsValid() const { return !m_pinName.IsEmpty(); } - - bool operator <( const COMPONENT_NET& aNet ) const - { - return m_pinName < aNet.m_pinName; - } - -#if defined(DEBUG) - /** - * Function Show - * is used to output the object tree, currently for debugging only. - * @param aNestLevel An aid to prettier tree indenting, and is the level - * of nesting of this object within the overall tree. - * @param aReporter A reference to a #REPORTER object to output to. - */ - virtual void Show( int aNestLevel, REPORTER& aReporter ); -#endif -}; - - -typedef std::vector< COMPONENT_NET > COMPONENT_NETS; - - -/** - * Class COMPONENT - * is used to store components and all of their related information found in a netlist. - */ -class COMPONENT -{ - COMPONENT_NETS m_nets; - wxArrayString m_footprintFilters; ///< Footprint filters found in netlist. - wxString m_reference; ///< The component reference designator found in netlist. - wxString m_value; ///< The component value found in netlist. - - // ZZZ This timestamp is string, not time_t - wxString m_timeStamp; ///< The component full time stamp found in netlist. - - /// The name of the component in #m_library used when it was placed on the schematic.. - wxString m_name; - - /** - * The name of the component library where #m_name was found. - */ - wxString m_library; - - /// The #FPID of the footprint assigned to the component. - FPID m_fpid; - - /// The #MODULE loaded for #m_footprintName found in #m_footprintLib. - std::auto_ptr< MODULE > m_footprint; - - /// Set to true if #m_footprintName or #m_footprintLib was changed when the footprint - /// link file was read. - bool m_footprintChanged; - - static COMPONENT_NET m_emptyNet; - -public: - COMPONENT( const FPID& aFPID, - const wxString& aReference, - const wxString& aValue, - const wxString& aTimeStamp ) - { - m_fpid = aFPID; - m_reference = aReference; - m_value = aValue; - m_timeStamp = aTimeStamp; - m_footprintChanged = false; - } - - virtual ~COMPONENT() { }; - - void AddNet( const wxString& aPinName, const wxString& aNetName ) - { - m_nets.push_back( COMPONENT_NET( aPinName, aNetName ) ); - } - - unsigned GetNetCount() const { return m_nets.size(); } - - const COMPONENT_NET& GetNet( unsigned aIndex ) const { return m_nets[aIndex]; } - - const COMPONENT_NET& GetNet( const wxString& aPinName ); - - void SortPins() { sort( m_nets.begin(), m_nets.end() ); } - - void SetName( const wxString& aName ) { m_name = aName;} - const wxString& GetName() const { return m_name; } - - void SetLibrary( const wxString& aLibrary ) { m_library = aLibrary; } - const wxString& GetLibrary() const { return m_library; } - - const wxString& GetReference() const { return m_reference; } - - const wxString& GetValue() const { return m_value; } - - void SetFPID( const FPID& aFPID ) - { - m_footprintChanged = !m_fpid.empty() && (m_fpid != aFPID); - m_fpid = aFPID; - } - - const FPID& GetFPID() const { return m_fpid; } - - const wxString& GetTimeStamp() const { return m_timeStamp; } - - void SetFootprintFilters( const wxArrayString& aFilterList ) - { - m_footprintFilters = aFilterList; - } - - const wxArrayString& GetFootprintFilters() const { return m_footprintFilters; } - - /** - * Function MatchesFootprintFilters - * - * @return true if \a aFootprintName matches any of the footprint filters or no footprint - * filters are defined. - */ - bool MatchesFootprintFilters( const wxString& aFootprintName ) const; - - MODULE* GetModule( bool aRelease = false ) - { - return ( aRelease ) ? m_footprint.release() : m_footprint.get(); - } - - void SetModule( MODULE* aModule ); - - bool IsLibSource( const wxString& aLibrary, const wxString& aName ) const - { - return aLibrary == m_library && aName == m_name; - } - - bool FootprintChanged() const { return m_footprintChanged; } - -#if defined(DEBUG) - /** - * Function Show - * is used to output the object tree, currently for debugging only. - * @param aNestLevel An aid to prettier tree indenting, and is the level - * of nesting of this object within the overall tree. - * @param aReporter A reference to a #REPORTER object to output to. - */ - virtual void Show( int aNestLevel, REPORTER& aReporter ); -#endif -}; - - -typedef boost::ptr_vector< COMPONENT > COMPONENTS; -typedef COMPONENTS::iterator COMPONENTS_ITER; -typedef COMPONENTS::const_iterator COMPONENTS_CITER; - - -/** - * Class NETLIST - * stores all of information read from a netlist along with the flags used to update - * the NETLIST in the #BOARD. - */ -class NETLIST -{ - COMPONENTS m_components; ///< Components found in the netlist. - - /// Remove footprints from #BOARD not found in netlist when true. - bool m_deleteExtraFootprints; - - /// Do not actually make any changes. Only report changes to #BOARD from netlist - /// when true. - bool m_isDryRun; - - /// Find component by time stamp if true or reference designator if false. - bool m_findByTimeStamp; - - /// Replace component footprints when they differ from the netlist if true. - bool m_replaceFootprints; - -public: - NETLIST() : - m_deleteExtraFootprints( false ), - m_isDryRun( false ), - m_findByTimeStamp( false ), - m_replaceFootprints( false ) - { - } - - /** - * Function IsEmpty() - * @return true if there are no components in the netlist. - */ - bool IsEmpty() const { return m_components.empty(); } - - /** - * Function Clear - * removes all components from the netlist. - */ - void Clear() { m_components.clear(); } - - /** - * Function GetCount - * @return the number of components in the netlist. - */ - unsigned GetCount() const { return m_components.size(); } - - /** - * Function GetComponent - * returns the #COMPONENT at \a aIndex. - * - * @param aIndex the index in #m_components to fetch. - * @return a pointer to the #COMPONENT at \a Index. - */ - COMPONENT* GetComponent( unsigned aIndex ) { return &m_components[ aIndex ]; } - - /** - * Function AddComponent - * adds \a aComponent to the NETLIST. - * - * @note If \a aComponent already exists in the NETLIST, \a aComponent is deleted - * to prevent memory leaks. An assertion is raised in debug builds. - * - * @param aComponent is the COMPONENT to save to the NETLIST. - */ - void AddComponent( COMPONENT* aComponent ); - - /* - * Function GetComponentByReference - * returns a #COMPONENT by \a aReference. - * - * @param aReference is the reference designator the #COMPONENT. - * @return a pointer to the #COMPONENT that matches \a aReference if found. Otherwise NULL. - */ - COMPONENT* GetComponentByReference( const wxString& aReference ); - - /* - * Function GetComponentByTimeStamp - * returns a #COMPONENT by \a aTimeStamp. - * - * @param aTimeStamp is the time stamp the #COMPONENT. - * @return a pointer to the #COMPONENT that matches \a aTimeStamp if found. Otherwise NULL. - */ - COMPONENT* GetComponentByTimeStamp( const wxString& aTimeStamp ); - - void SortByFPID(); - - void SortByReference(); - - void SetDeleteExtraFootprints( bool aDeleteExtraFootprints ) - { - m_deleteExtraFootprints = aDeleteExtraFootprints; - } - - bool GetDeleteExtraFootprints() const { return m_deleteExtraFootprints; } - - void SetIsDryRun( bool aIsDryRun ) { m_isDryRun = aIsDryRun; } - - bool IsDryRun() const { return m_isDryRun; } - - void SetFindByTimeStamp( bool aFindByTimeStamp ) { m_findByTimeStamp = aFindByTimeStamp; } - - bool IsFindByTimeStamp() const { return m_findByTimeStamp; } - - void SetReplaceFootprints( bool aReplaceFootprints ) - { - m_replaceFootprints = aReplaceFootprints; - } - - bool GetReplaceFootprints() const { return m_replaceFootprints; } - - /** - * Function AnyFootprintsLinked - * @return true if any component with a footprint link is found. - */ - bool AnyFootprintsLinked() const; - - /** - * Function AllFootprintsLinked - * @return true if all components have a footprint link. - */ - bool AllFootprintsLinked() const; - - /** - * Function NoFootprintsLinked - * @return true if none of the components have a footprint link. - */ - bool NoFootprintsLinked() const { return !AnyFootprintsLinked(); } - - /** - * Function AnyFootprintsChanged - * @return true if any components footprints were changed when the footprint link file - * (*.cmp) was loaded. - */ - bool AnyFootprintsChanged() const; - -#if defined(DEBUG) - /** - * Function Show - * is used to output the object tree, currently for debugging only. - * @param aNestLevel An aid to prettier tree indenting, and is the level - * of nesting of this object within the overall tree. - * @param aReporter A reference to a #REPORTER object to output to. - */ - virtual void Show( int aNestLevel, REPORTER& aReporter ); -#endif -}; +class NETLIST; +class COMPONENT; /** diff --git a/pcbnew/pcb_netlist.cpp b/pcbnew/pcb_netlist.cpp new file mode 100644 index 0000000000..7e1ee53aa1 --- /dev/null +++ b/pcbnew/pcb_netlist.cpp @@ -0,0 +1,278 @@ +/** + * @file pcb_netlist.cpp + */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2011 Jean-Pierre Charras. + * Copyright (C) 2013 Wayne Stambaugh . + * Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +#include +#include +#include + +#include +#include + + +#if defined(DEBUG) +/** + * Function NestedSpace + * outputs nested space for pretty indenting. + * @param aNestLevel The nest count + * @param aReporter A reference to a #REPORTER object where to output. + * @return REPORTER& for continuation. + **/ +static REPORTER& NestedSpace( int aNestLevel, REPORTER& aReporter ) +{ + for( int i = 0; i < aNestLevel; ++i ) + aReporter.Report( wxT( " " ) ); + + return aReporter; +} + + +void COMPONENT_NET::Show( int aNestLevel, REPORTER& aReporter ) +{ + NestedSpace( aNestLevel, aReporter ); + aReporter.Report( wxString::Format( wxT( "\n" ), + GetChars( m_pinName ), GetChars( m_netName ) ) ); +} +#endif + + +void COMPONENT::SetModule( MODULE* aModule ) +{ + m_footprint.reset( aModule ); + + if( aModule == NULL ) + return; + + aModule->SetReference( m_reference ); + aModule->SetValue( m_value ); + aModule->SetFPID( m_fpid ); + aModule->SetPath( m_timeStamp ); +} + + +COMPONENT_NET COMPONENT::m_emptyNet; + + +const COMPONENT_NET& COMPONENT::GetNet( const wxString& aPinName ) +{ + for( unsigned i = 0; i < m_nets.size(); i++ ) + { + if( m_nets[i].GetPinName() == aPinName ) + return m_nets[i]; + } + + return m_emptyNet; +} + + +bool COMPONENT::MatchesFootprintFilters( const wxString& aFootprintName ) const +{ + if( m_footprintFilters.GetCount() == 0 ) + return true; + + // The matching is case insensitive + wxString name = aFootprintName.Upper(); + + for( unsigned ii = 0; ii < m_footprintFilters.GetCount(); ii++ ) + { + if( name.Matches( m_footprintFilters[ii].Upper() ) ) + return true; + } + + return false; +} + + +#if defined(DEBUG) +void COMPONENT::Show( int aNestLevel, REPORTER& aReporter ) +{ + NestedSpace( aNestLevel, aReporter ); + aReporter.Report( wxT( "\n" ) ); + NestedSpace( aNestLevel+1, aReporter ); + aReporter.Report( wxString::Format( wxT( "\n" ), + GetChars( m_reference ), GetChars( m_value ), + GetChars( m_name ), GetChars( m_library ), + m_fpid.Format().c_str(), + GetChars( m_timeStamp ) ) ); + + if( !m_footprintFilters.IsEmpty() ) + { + NestedSpace( aNestLevel+1, aReporter ); + aReporter.Report( wxT( "\n" ) ); + + for( unsigned i = 0; i < m_footprintFilters.GetCount(); i++ ) + { + NestedSpace( aNestLevel+2, aReporter ); + aReporter.Report( wxString::Format( wxT( "<%s>\n" ), + GetChars( m_footprintFilters[i] ) ) ); + } + + NestedSpace( aNestLevel+1, aReporter ); + aReporter.Report( wxT( "\n" ) ); + } + + if( !m_nets.empty() ) + { + NestedSpace( aNestLevel+1, aReporter ); + aReporter.Report( wxT( "\n" ) ); + + for( unsigned i = 0; i < m_nets.size(); i++ ) + m_nets[i].Show( aNestLevel+3, aReporter ); + + NestedSpace( aNestLevel+1, aReporter ); + aReporter.Report( "\n" ); + } + + NestedSpace( aNestLevel, aReporter ); + aReporter.Report( "\n" ); +} +#endif + + +void NETLIST::AddComponent( COMPONENT* aComponent ) +{ + m_components.push_back( aComponent ); +} + + +COMPONENT* NETLIST::GetComponentByReference( const wxString& aReference ) +{ + COMPONENT* component = NULL; + + for( unsigned i = 0; i < m_components.size(); i++ ) + { + if( m_components[i].GetReference() == aReference ) + { + component = &m_components[i]; + break; + } + } + + return component; +} + + +COMPONENT* NETLIST::GetComponentByTimeStamp( const wxString& aTimeStamp ) +{ + COMPONENT* component = NULL; + + for( unsigned i = 0; i < m_components.size(); i++ ) + { + if( m_components[i].GetTimeStamp() == aTimeStamp ) + { + component = &m_components[i]; + break; + } + } + + return component; +} + + +/** + * Function ByFPID + * is a helper function used to sort the component list used by loadNewModules. + */ +static bool ByFPID( const COMPONENT& ref, const COMPONENT& cmp ) +{ + return ref.GetFPID() > cmp.GetFPID(); +} + + +void NETLIST::SortByFPID() +{ + m_components.sort( ByFPID ); +} + + +/** + * Operator < + * compares two #COMPONENT objects by reference designator. + */ +bool operator < ( const COMPONENT& item1, const COMPONENT& item2 ) +{ + return StrNumCmp( item1.GetReference(), item2.GetReference(), INT_MAX, true ) < 0; +} + + +void NETLIST::SortByReference() +{ + m_components.sort(); +} + + +bool NETLIST::AnyFootprintsLinked() const +{ + for( unsigned i = 0; i < m_components.size(); i++ ) + { + if( !m_components[i].GetFPID().empty() ) + return true; + } + + return false; +} + + +bool NETLIST::AllFootprintsLinked() const +{ + for( unsigned i = 0; i < m_components.size(); i++ ) + { + if( m_components[i].GetFPID().empty() ) + return false; + } + + return true; +} + + +#if defined( DEBUG ) +void NETLIST::Show( int aNestLevel, REPORTER& aReporter ) +{ + NestedSpace( aNestLevel, aReporter ); + aReporter.Report( "\n" ); + + if( !m_components.empty() ) + { + NestedSpace( aNestLevel+1, aReporter ); + aReporter.Report( "\n" ); + + for( unsigned i = 0; i < m_components.size(); i++ ) + { + m_components[i].Show( aNestLevel+2, aReporter ); + } + + NestedSpace( aNestLevel+1, aReporter ); + + aReporter.Report( "\n" ); + } + + NestedSpace( aNestLevel, aReporter ); + aReporter.Report( "\n" ); +} +#endif diff --git a/pcbnew/pcb_netlist.h b/pcbnew/pcb_netlist.h new file mode 100644 index 0000000000..90605d29a3 --- /dev/null +++ b/pcbnew/pcb_netlist.h @@ -0,0 +1,367 @@ +#ifndef PCB_NETLIST_H +#define PCB_NETLIST_H + +/** + * @file pcb_netlist.h + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras. + * Copyright (C) 2013 Wayne Stambaugh . + * Copyright (C) 2012 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include + + +class MODULE; +class REPORTER; + + +/** + * Class COMPONENT_NET + * is used to store the component pin name to net name associations stored in a netlist. + */ +class COMPONENT_NET +{ + wxString m_pinName; + wxString m_netNumber; + wxString m_netName; + +public: + COMPONENT_NET() {} + + COMPONENT_NET( const wxString& aPinName, const wxString& aNetName ) + { + m_pinName = aPinName; + m_netName = aNetName; + } + + const wxString& GetPinName() const { return m_pinName; } + + const wxString& GetNetName() const { return m_netName; } + + bool IsValid() const { return !m_pinName.IsEmpty(); } + + bool operator <( const COMPONENT_NET& aNet ) const + { + return m_pinName < aNet.m_pinName; + } + +#if defined(DEBUG) + /** + * Function Show + * is used to output the object tree, currently for debugging only. + * @param aNestLevel An aid to prettier tree indenting, and is the level + * of nesting of this object within the overall tree. + * @param aReporter A reference to a #REPORTER object to output to. + */ + virtual void Show( int aNestLevel, REPORTER& aReporter ); +#endif +}; + + +typedef std::vector< COMPONENT_NET > COMPONENT_NETS; + + +/** + * Class COMPONENT + * is used to store components and all of their related information found in a netlist. + */ +class COMPONENT +{ + COMPONENT_NETS m_nets; + wxArrayString m_footprintFilters; ///< Footprint filters found in netlist. + wxString m_reference; ///< The component reference designator found in netlist. + wxString m_value; ///< The component value found in netlist. + + // ZZZ This timestamp is string, not time_t + wxString m_timeStamp; ///< The component full time stamp found in netlist. + + /// The name of the component in #m_library used when it was placed on the schematic.. + wxString m_name; + + /// The name of the component library where #m_name was found. + wxString m_library; + + /// The #FPID of the footprint assigned to the component. + FPID m_fpid; + + /// The #MODULE loaded for #m_footprintName found in #m_footprintLib. + std::auto_ptr< MODULE > m_footprint; + + /// Set to true if #m_footprintName or #m_footprintLib was changed when the footprint + /// link file was read. + bool m_footprintChanged; + + static COMPONENT_NET m_emptyNet; + +public: + COMPONENT( const FPID& aFPID, + const wxString& aReference, + const wxString& aValue, + const wxString& aTimeStamp ) + { + m_fpid = aFPID; + m_reference = aReference; + m_value = aValue; + m_timeStamp = aTimeStamp; + m_footprintChanged = false; + } + + virtual ~COMPONENT() { }; + + void AddNet( const wxString& aPinName, const wxString& aNetName ) + { + m_nets.push_back( COMPONENT_NET( aPinName, aNetName ) ); + } + + unsigned GetNetCount() const { return m_nets.size(); } + + const COMPONENT_NET& GetNet( unsigned aIndex ) const { return m_nets[aIndex]; } + + const COMPONENT_NET& GetNet( const wxString& aPinName ); + + void SortPins() { sort( m_nets.begin(), m_nets.end() ); } + + void SetName( const wxString& aName ) { m_name = aName;} + const wxString& GetName() const { return m_name; } + + void SetLibrary( const wxString& aLibrary ) { m_library = aLibrary; } + const wxString& GetLibrary() const { return m_library; } + + const wxString& GetReference() const { return m_reference; } + + const wxString& GetValue() const { return m_value; } + + void SetFPID( const FPID& aFPID ) + { + m_footprintChanged = !m_fpid.empty() && (m_fpid != aFPID); + m_fpid = aFPID; + } + + const FPID& GetFPID() const { return m_fpid; } + + const wxString& GetTimeStamp() const { return m_timeStamp; } + + void SetFootprintFilters( const wxArrayString& aFilterList ) + { + m_footprintFilters = aFilterList; + } + + const wxArrayString& GetFootprintFilters() const { return m_footprintFilters; } + + /** + * Function MatchesFootprintFilters + * + * @return true if \a aFootprintName matches any of the footprint filters or no footprint + * filters are defined. + */ + bool MatchesFootprintFilters( const wxString& aFootprintName ) const; + + MODULE* GetModule( bool aRelease = false ) + { + return ( aRelease ) ? m_footprint.release() : m_footprint.get(); + } + + void SetModule( MODULE* aModule ); + + bool IsLibSource( const wxString& aLibrary, const wxString& aName ) const + { + return aLibrary == m_library && aName == m_name; + } + + bool FootprintChanged() const { return m_footprintChanged; } + +#if defined(DEBUG) + /** + * Function Show + * is used to output the object tree, currently for debugging only. + * @param aNestLevel An aid to prettier tree indenting, and is the level + * of nesting of this object within the overall tree. + * @param aReporter A reference to a #REPORTER object to output to. + */ + virtual void Show( int aNestLevel, REPORTER& aReporter ); +#endif +}; + + +typedef boost::ptr_vector< COMPONENT > COMPONENTS; +typedef COMPONENTS::iterator COMPONENTS_ITER; +typedef COMPONENTS::const_iterator COMPONENTS_CITER; + + +/** + * Class NETLIST + * stores all of information read from a netlist along with the flags used to update + * the NETLIST in the #BOARD. + */ +class NETLIST +{ + COMPONENTS m_components; ///< Components found in the netlist. + + /// Remove footprints from #BOARD not found in netlist when true. + bool m_deleteExtraFootprints; + + /// Do not actually make any changes. Only report changes to #BOARD from netlist + /// when true. + bool m_isDryRun; + + /// Find component by time stamp if true or reference designator if false. + bool m_findByTimeStamp; + + /// Replace component footprints when they differ from the netlist if true. + bool m_replaceFootprints; + +public: + NETLIST() : + m_deleteExtraFootprints( false ), + m_isDryRun( false ), + m_findByTimeStamp( false ), + m_replaceFootprints( false ) + { + } + + /** + * Function IsEmpty() + * @return true if there are no components in the netlist. + */ + bool IsEmpty() const { return m_components.empty(); } + + /** + * Function Clear + * removes all components from the netlist. + */ + void Clear() { m_components.clear(); } + + /** + * Function GetCount + * @return the number of components in the netlist. + */ + unsigned GetCount() const { return m_components.size(); } + + /** + * Function GetComponent + * returns the #COMPONENT at \a aIndex. + * + * @param aIndex the index in #m_components to fetch. + * @return a pointer to the #COMPONENT at \a Index. + */ + COMPONENT* GetComponent( unsigned aIndex ) { return &m_components[ aIndex ]; } + + /** + * Function AddComponent + * adds \a aComponent to the NETLIST. + * + * @note If \a aComponent already exists in the NETLIST, \a aComponent is deleted + * to prevent memory leaks. An assertion is raised in debug builds. + * + * @param aComponent is the COMPONENT to save to the NETLIST. + */ + void AddComponent( COMPONENT* aComponent ); + + /* + * Function GetComponentByReference + * returns a #COMPONENT by \a aReference. + * + * @param aReference is the reference designator the #COMPONENT. + * @return a pointer to the #COMPONENT that matches \a aReference if found. Otherwise NULL. + */ + COMPONENT* GetComponentByReference( const wxString& aReference ); + + /* + * Function GetComponentByTimeStamp + * returns a #COMPONENT by \a aTimeStamp. + * + * @param aTimeStamp is the time stamp the #COMPONENT. + * @return a pointer to the #COMPONENT that matches \a aTimeStamp if found. Otherwise NULL. + */ + COMPONENT* GetComponentByTimeStamp( const wxString& aTimeStamp ); + + void SortByFPID(); + + void SortByReference(); + + void SetDeleteExtraFootprints( bool aDeleteExtraFootprints ) + { + m_deleteExtraFootprints = aDeleteExtraFootprints; + } + + bool GetDeleteExtraFootprints() const { return m_deleteExtraFootprints; } + + void SetIsDryRun( bool aIsDryRun ) { m_isDryRun = aIsDryRun; } + + bool IsDryRun() const { return m_isDryRun; } + + void SetFindByTimeStamp( bool aFindByTimeStamp ) { m_findByTimeStamp = aFindByTimeStamp; } + + bool IsFindByTimeStamp() const { return m_findByTimeStamp; } + + void SetReplaceFootprints( bool aReplaceFootprints ) + { + m_replaceFootprints = aReplaceFootprints; + } + + bool GetReplaceFootprints() const { return m_replaceFootprints; } + + /** + * Function AnyFootprintsLinked + * @return true if any component with a footprint link is found. + */ + bool AnyFootprintsLinked() const; + + /** + * Function AllFootprintsLinked + * @return true if all components have a footprint link. + */ + bool AllFootprintsLinked() const; + + /** + * Function NoFootprintsLinked + * @return true if none of the components have a footprint link. + */ + bool NoFootprintsLinked() const { return !AnyFootprintsLinked(); } + + /** + * Function AnyFootprintsChanged + * @return true if any components footprints were changed when the footprint link file + * (*.cmp) was loaded. + */ + bool AnyFootprintsChanged() const; + +#if defined(DEBUG) + /** + * Function Show + * is used to output the object tree, currently for debugging only. + * @param aNestLevel An aid to prettier tree indenting, and is the level + * of nesting of this object within the overall tree. + * @param aReporter A reference to a #REPORTER object to output to. + */ + virtual void Show( int aNestLevel, REPORTER& aReporter ); +#endif +}; + + +#endif // PCB_NETLIST_H From eaada4cf1ff55007c4b3ec9c06d52d8a449034e9 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Mon, 16 Sep 2013 19:56:45 -0400 Subject: [PATCH 22/29] Fix broken CvPcb footprint preview. (fixes lp:1226272) --- cvpcb/class_DisplayFootprintsFrame.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cvpcb/class_DisplayFootprintsFrame.cpp b/cvpcb/class_DisplayFootprintsFrame.cpp index 44810b1abc..9f28f4b220 100644 --- a/cvpcb/class_DisplayFootprintsFrame.cpp +++ b/cvpcb/class_DisplayFootprintsFrame.cpp @@ -476,7 +476,7 @@ EDA_COLOR_T DISPLAY_FOOTPRINTS_FRAME::GetGridColor() const MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) { - MODULE* footprint; + MODULE* footprint = NULL; try { @@ -550,6 +550,9 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) } footprint = pi->FootprintLoad( libPath, aFootprintName ); + + if( footprint != NULL ) + break; } #endif } From 3724c40afdd0c6c1031b8491382b8c9376479846 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Mon, 16 Sep 2013 20:52:08 -0400 Subject: [PATCH 23/29] Fix but reading empty footprints in netlist. (fixes lp:1226283) * Remove fp_lib token from board and s-expr netlist file format. * Fix a bunch of Doxygen warnings. * Remove some extra debug log messages. --- common/edaappl.cpp | 2 -- common/footprint_info.cpp | 2 +- common/fp_lib_table.cpp | 13 ---------- common/fpid.cpp | 6 +++++ common/netlist.keywords | 1 - common/page_layout/class_worksheet_layout.cpp | 2 +- .../page_layout_default_description.cpp | 2 +- common/page_layout/page_layout_reader.cpp | 2 +- common/page_layout/title_block_shapes.cpp | 2 +- .../page_layout/title_block_shapes_gost.cpp | 2 +- common/page_layout_default_description.cpp | 2 +- common/page_layout_reader.cpp | 2 +- common/pcb.keywords | 1 - cvpcb/class_DisplayFootprintsFrame.cpp | 2 +- cvpcb/class_components_listbox.cpp | 2 +- cvpcb/readwrite_dlgs.cpp | 2 +- include/fp_lib_table.h | 2 +- include/fpid.h | 2 ++ include/worksheet_shape_builder.h | 2 ++ include/wxstruct.h | 2 -- pagelayout_editor/events_functions.cpp | 2 +- pagelayout_editor/files.cpp | 2 +- pagelayout_editor/invoke_pl_editor_dialog.h | 2 +- pcbnew/kicad_netlist_reader.cpp | 24 +++++++++---------- pcbnew/kicad_plugin.cpp | 6 +---- pcbnew/legacy_netlist_reader.cpp | 4 +++- pcbnew/loadcmp.cpp | 4 ++-- pcbnew/netlist_reader.cpp | 14 ++++++++++- pcbnew/pcb_netlist.h | 5 ++-- pcbnew/pcb_parser.cpp | 15 ++++++------ pcbnew/target_edit.cpp | 2 +- 31 files changed, 67 insertions(+), 66 deletions(-) diff --git a/common/edaappl.cpp b/common/edaappl.cpp index cb3c15042c..7a218868df 100644 --- a/common/edaappl.cpp +++ b/common/edaappl.cpp @@ -1173,7 +1173,6 @@ bool EDA_APP::SetFootprintLibTablePath() if( m_commonSettings->Read( kicadFpLibPath, &path ) && wxFileName::DirExists( path ) ) { wxSetEnv( wxT( "KISYSMOD" ), path ); - wxLogDebug( wxT( "Setting $KISYSMOD=\"%s\"." ), GetChars( path ) ); return true; } @@ -1199,7 +1198,6 @@ bool EDA_APP::SetFootprintLibTablePath() if( modFileCount != 0 ) { - wxLogDebug( wxT( "Setting $KISYSMOD=\"%s\"." ), GetChars( bestPath ) ); wxSetEnv( wxT( "KISYSMOD" ), bestPath ); return true; } diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index 5a4ce2970a..e6fbdad856 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -190,7 +190,7 @@ FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString & aFootprintName ) #if defined( USE_FP_LIB_TABLE ) FPID fpid; - wxCHECK_MSG( fpid.Parse( TO_UTF8( aFootprintName ) ) < 0, NULL, + wxCHECK_MSG( fpid.Parse( aFootprintName ) < 0, NULL, wxString::Format( wxT( "<%s> is not a valid FPID." ), GetChars( aFootprintName ) ) ); diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index 2ab1ad8290..d4f8500b50 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -103,7 +103,6 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR // After (name), remaining (lib) elements are order independent, and in // some cases optional. - bool sawType = false; bool sawOpts = false; bool sawDesc = false; @@ -460,11 +459,6 @@ bool FP_LIB_TABLE::ConvertFromLegacy( NETLIST& aNetList, const wxArrayString& aL } else { - wxLogDebug( wxT( "Found component %s footprint %s in legacy library <%s>." ), - GetChars( component->GetReference() ), - GetChars( GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ), - GetChars( libPath ) ); - wxString libNickname; FP_LIB_TABLE* cur = this; @@ -481,9 +475,6 @@ bool FP_LIB_TABLE::ConvertFromLegacy( NETLIST& aNetList, const wxArrayString& aL && uri.Find( wxChar( '/' ) ) >= 0 ) uri.Replace( wxT( "/"), wxT( "\\" ) ); - wxLogDebug( wxT( "Comparing legacy path <%s> to lib table path <%s>." ), - GetChars( libPath ), GetChars( uri ) ); - if( uri == libPath ) { libNickname = cur->rows[i].GetNickName(); @@ -537,8 +528,6 @@ bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARS bool tableExists = true; wxFileName fn = GetGlobalTableFileName(); - wxLogDebug( wxT( "Loading global footprint table file: %s" ), GetChars( fn.GetFullPath() ) ); - if( !fn.FileExists() ) { tableExists = false; @@ -548,8 +537,6 @@ bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARS wxString fileName( wxT( "fp_global_table" ) ); fileName = wxGetApp().FindLibraryPath( fileName ); - wxLogDebug( wxT( "Copying global footprint table from <%s>." ), GetChars( fileName ) ); - // The fallback is to create an empty global footprint table for the user to populate. if( fileName.IsEmpty() || !::wxCopyFile( fileName, fn.GetFullPath(), false ) ) { diff --git a/common/fpid.cpp b/common/fpid.cpp index a07bf4707a..92e1ee2786 100644 --- a/common/fpid.cpp +++ b/common/fpid.cpp @@ -171,6 +171,12 @@ int FPID::Parse( const std::string& aId ) } +int FPID::Parse( const wxString& aId ) +{ + return Parse( std::string( TO_UTF8( aId ) ) ); +} + + FPID::FPID( const std::string& aId ) throw( PARSE_ERROR ) { int offset = Parse( aId ); diff --git a/common/netlist.keywords b/common/netlist.keywords index 9f2932e190..2132e6b974 100644 --- a/common/netlist.keywords +++ b/common/netlist.keywords @@ -12,7 +12,6 @@ fields footprint footprints fp -fp_lib lib libpart libparts diff --git a/common/page_layout/class_worksheet_layout.cpp b/common/page_layout/class_worksheet_layout.cpp index 6f2cad1662..67cd12277d 100644 --- a/common/page_layout/class_worksheet_layout.cpp +++ b/common/page_layout/class_worksheet_layout.cpp @@ -1,5 +1,5 @@ /** - * @file class_worksheet_layuout.cpp + * @file class_worksheet_layout.cpp * @brief description of graphic items and texts to build a title block */ diff --git a/common/page_layout/page_layout_default_description.cpp b/common/page_layout/page_layout_default_description.cpp index 8e5d2ae283..c72cd1c14a 100644 --- a/common/page_layout/page_layout_default_description.cpp +++ b/common/page_layout/page_layout_default_description.cpp @@ -1,5 +1,5 @@ /** - * @file page_layout_default_description.cpp + * @file common/page_layout/page_layout_default_description.cpp */ /* diff --git a/common/page_layout/page_layout_reader.cpp b/common/page_layout/page_layout_reader.cpp index d87fa8fccf..fe101b410e 100644 --- a/common/page_layout/page_layout_reader.cpp +++ b/common/page_layout/page_layout_reader.cpp @@ -1,5 +1,5 @@ /** - * @file page_layout_reader.cpp + * @file common/page_layout/page_layout_reader.cpp * @brief read an S expression of description of graphic items and texts * to build a title block and page layout */ diff --git a/common/page_layout/title_block_shapes.cpp b/common/page_layout/title_block_shapes.cpp index cfa814d414..f2a967cbab 100644 --- a/common/page_layout/title_block_shapes.cpp +++ b/common/page_layout/title_block_shapes.cpp @@ -1,5 +1,5 @@ /** - * @file title_block_shape.cpp + * @file title_block_shapes.cpp * @brief description of graphic items and texts to build a title block */ diff --git a/common/page_layout/title_block_shapes_gost.cpp b/common/page_layout/title_block_shapes_gost.cpp index aafa906210..3bd1d47afd 100644 --- a/common/page_layout/title_block_shapes_gost.cpp +++ b/common/page_layout/title_block_shapes_gost.cpp @@ -1,5 +1,5 @@ /** - * @file title_block_shape_gost.h + * @file title_block_shapes_gost.cpp * @brief description of graphic items and texts to build a title block * using GOST standard */ diff --git a/common/page_layout_default_description.cpp b/common/page_layout_default_description.cpp index faced42fea..972c90eae7 100644 --- a/common/page_layout_default_description.cpp +++ b/common/page_layout_default_description.cpp @@ -1,5 +1,5 @@ /** - * @file page_layout_default_description.cpp + * @file common/page_layout_default_description.cpp */ /* diff --git a/common/page_layout_reader.cpp b/common/page_layout_reader.cpp index 7cbd93f71b..3bdf4882eb 100644 --- a/common/page_layout_reader.cpp +++ b/common/page_layout_reader.cpp @@ -1,5 +1,5 @@ /** - * @file page_layout_reader.cpp + * @file common/page_layout_reader.cpp * @brief read an S expression of description of graphic items and texts * to build a title block and page layout */ diff --git a/common/pcb.keywords b/common/pcb.keywords index 2e19147bdb..0126f5602e 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -72,7 +72,6 @@ font fp_arc fp_circle fp_curve -fp_lib fp_line fp_poly fp_text diff --git a/cvpcb/class_DisplayFootprintsFrame.cpp b/cvpcb/class_DisplayFootprintsFrame.cpp index 9f28f4b220..4d4a1e6f74 100644 --- a/cvpcb/class_DisplayFootprintsFrame.cpp +++ b/cvpcb/class_DisplayFootprintsFrame.cpp @@ -483,7 +483,7 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName ) #if defined( USE_FP_LIB_TABLE ) FPID fpid; - if( fpid.Parse( TO_UTF8( aFootprintName ) ) >= 0 ) + if( fpid.Parse( aFootprintName ) >= 0 ) { DisplayInfoMessage( this, wxString::Format( wxT( "Footprint ID <%s> is not valid." ), GetChars( aFootprintName ) ) ); diff --git a/cvpcb/class_components_listbox.cpp b/cvpcb/class_components_listbox.cpp index 11a4a7c03f..a99517370b 100644 --- a/cvpcb/class_components_listbox.cpp +++ b/cvpcb/class_components_listbox.cpp @@ -22,7 +22,7 @@ */ /** - * @file class_components_listbox.h + * @file class_components_listbox.cpp */ #include diff --git a/cvpcb/readwrite_dlgs.cpp b/cvpcb/readwrite_dlgs.cpp index 4eb58bf9b5..1096833b90 100644 --- a/cvpcb/readwrite_dlgs.cpp +++ b/cvpcb/readwrite_dlgs.cpp @@ -77,7 +77,7 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) #if defined( USE_FP_LIB_TABLE ) FPID fpid; - wxCHECK_RET( fpid.Parse( TO_UTF8( aFootprintName ) ) < 0, + wxCHECK_RET( fpid.Parse( aFootprintName ) < 0, wxString::Format( wxT( "<%s> is not a valid FPID." ), GetChars( aFootprintName ) ) ); diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 98796040fc..1ac53c7576 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -360,7 +360,7 @@ public: /** * Function FindRowByURI - * returns a #ROW if aURE is found in this table or in any chained + * returns a #FP_LIB_TABLE::ROW if aURE is found in this table or in any chained * fallBack table fragments, else NULL. */ const ROW* FindRowByURI( const wxString& aURI ); diff --git a/include/fpid.h b/include/fpid.h index bd0be419a6..6417cfbc6f 100644 --- a/include/fpid.h +++ b/include/fpid.h @@ -82,6 +82,8 @@ public: */ int Parse( const std::string& aId ); + int Parse( const wxString& aId ); + /** * Function GetLibNickname * returns the logical library name portion of a FPID. diff --git a/include/worksheet_shape_builder.h b/include/worksheet_shape_builder.h index 103ec0d7f2..04f08c914c 100644 --- a/include/worksheet_shape_builder.h +++ b/include/worksheet_shape_builder.h @@ -599,6 +599,8 @@ public: /** * Populates the list from a S expr description stored in a string * @param aPageLayout = the S expr string + * @param Append Do not delete old layout if true and append \a aPageLayout + * the existing one. */ void SetPageLayout( const char* aPageLayout, bool Append = false ); diff --git a/include/wxstruct.h b/include/wxstruct.h index 4c3144ea28..9e1bfb73b9 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -509,7 +509,6 @@ public: * Function SetCrossHairPosition * sets the screen cross hair position to \a aPosition in logical (drawing) units. * @param aPosition The new cross hair position. - * @param aGridOrigin Origin point of the snap grid. * @param aSnapToGrid Sets the cross hair position to the nearest grid position to * \a aPosition. * @@ -520,7 +519,6 @@ public: * Function GetCursorPosition * returns the current cursor position in logical (drawing) units. * @param aOnGrid Returns the nearest grid position at the current cursor position. - * @param aGridOrigin Origin point of the snap grid. * @param aGridSize Custom grid size instead of the current grid size. Only valid * if \a aOnGrid is true. * @return The current cursor position. diff --git a/pagelayout_editor/events_functions.cpp b/pagelayout_editor/events_functions.cpp index d6b81f617f..70b88d2949 100644 --- a/pagelayout_editor/events_functions.cpp +++ b/pagelayout_editor/events_functions.cpp @@ -1,5 +1,5 @@ /** - * @file pagelayout_editor/events_called_functions.cpp + * @file pagelayout_editor/events_functions.cpp * @brief page layout editor command event functions. */ /* diff --git a/pagelayout_editor/files.cpp b/pagelayout_editor/files.cpp index cc6ef4de7d..a43c3738f9 100644 --- a/pagelayout_editor/files.cpp +++ b/pagelayout_editor/files.cpp @@ -1,5 +1,5 @@ /** - * @file pl_editor/files.cpp + * @file pagelayout_editor/files.cpp */ /* diff --git a/pagelayout_editor/invoke_pl_editor_dialog.h b/pagelayout_editor/invoke_pl_editor_dialog.h index a0aee5cf4d..ecd4b96cbe 100644 --- a/pagelayout_editor/invoke_pl_editor_dialog.h +++ b/pagelayout_editor/invoke_pl_editor_dialog.h @@ -1,5 +1,5 @@ /** - * @file invoke_pl_editor.h + * @file invoke_pl_editor_dialog.h */ /* diff --git a/pcbnew/kicad_netlist_reader.cpp b/pcbnew/kicad_netlist_reader.cpp index fb40685ee8..aea7a3e5ad 100644 --- a/pcbnew/kicad_netlist_reader.cpp +++ b/pcbnew/kicad_netlist_reader.cpp @@ -283,10 +283,11 @@ void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR ) * A component need a reference, value, footprint name and a full time stamp * The full time stamp is the sheetpath time stamp + the component time stamp */ + FPID fpid; + wxString footprint; + wxString tmp; wxString ref; wxString value; - wxString footprintName; - wxString footprintLib; wxString library; wxString name; wxString pathtimestamp, timestamp; @@ -313,13 +314,7 @@ void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR ) case T_footprint: NeedSYMBOLorNUMBER(); - footprintName = FROM_UTF8( CurText() ); - NeedRIGHT(); - break; - - case T_fp_lib: - NeedSYMBOLorNUMBER(); - footprintLib = FROM_UTF8( CurText() ); + footprint = FromUTF8(); NeedRIGHT(); break; @@ -370,10 +365,15 @@ void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR ) } } - FPID fpid; + if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 ) + { + wxString error; + error.Printf( _( "invalid PFID in\nfile: <%s>\nline: %d\noffset: %d" ), + GetChars( CurSource() ), CurLineNumber(), CurOffset() ); + + THROW_IO_ERROR( error ); + } - fpid.SetFootprintName( footprintName ); - fpid.SetLibNickname( footprintName ); pathtimestamp += timestamp; COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp ); component->SetName( name ); diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 4e26452b3b..04d28d692c 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -869,7 +869,7 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const } m_out->Print( aNestLevel, "(module %s", - m_out->Quotes( aModule->GetFPID().GetFootprintName() ).c_str() ); + m_out->Quotes( aModule->GetFPID().Format() ).c_str() ); if( aModule->IsLocked() ) m_out->Print( 0, " locked" ); @@ -877,10 +877,6 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const if( aModule->IsPlaced() ) m_out->Print( 0, " placed" ); - if( !aModule->GetFPID().IsLegacy() ) - m_out->Print( 0, " (fp_lib %s)", - m_out->Quotes( aModule->GetFPID().GetLibNickname() ).c_str() ); - formatLayer( aModule ); if( !( m_ctl & CTL_OMIT_TSTAMPS ) ) diff --git a/pcbnew/legacy_netlist_reader.cpp b/pcbnew/legacy_netlist_reader.cpp index e215a67720..f4973d6fa3 100644 --- a/pcbnew/legacy_netlist_reader.cpp +++ b/pcbnew/legacy_netlist_reader.cpp @@ -168,7 +168,9 @@ COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText ) throw( PARSE_ERRO FPID fpid; - fpid.SetFootprintName( footprintName ); + if( !footprintName.IsEmpty() ) + fpid.SetFootprintName( footprintName ); + COMPONENT* component = new COMPONENT( fpid, reference, value, timeStamp ); component->SetName( name ); m_netlist->AddComponent( component ); diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index fbdfdd5a29..d4a6134d7c 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -224,7 +224,7 @@ MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary, #else FPID fpid; - wxCHECK_MSG( fpid.Parse( TO_UTF8( moduleName ) ) < 0, NULL, + wxCHECK_MSG( fpid.Parse( moduleName ) < 0, NULL, wxString::Format( wxT( "Could not parse FPID string <%s>." ), GetChars( moduleName ) ) ); @@ -260,7 +260,7 @@ MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary, #else FPID fpid; - wxCHECK_MSG( fpid.Parse( TO_UTF8( moduleName ) ) < 0, NULL, + wxCHECK_MSG( fpid.Parse( moduleName ) < 0, NULL, wxString::Format( wxT( "Could not parse FPID string <%s>." ), GetChars( moduleName ) ) ); diff --git a/pcbnew/netlist_reader.cpp b/pcbnew/netlist_reader.cpp index a970d53940..0f02cec54d 100644 --- a/pcbnew/netlist_reader.cpp +++ b/pcbnew/netlist_reader.cpp @@ -197,7 +197,19 @@ bool CMP_READER::Load( NETLIST* aNetlist ) throw( IO_ERROR, PARSE_ERROR ) // assignment list. This is an usual case during the life of a design. if( component ) { - component->SetFPID( FPID( footprint ) ); + FPID fpid; + + if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 ) + { + wxString error; + error.Printf( _( "invalid PFID in\nfile: <%s>\nline: %d" ), + GetChars( m_lineReader->GetSource() ), + m_lineReader->LineNumber() ); + + THROW_IO_ERROR( error ); + } + + component->SetFPID( fpid ); } else { diff --git a/pcbnew/pcb_netlist.h b/pcbnew/pcb_netlist.h index 90605d29a3..ff9544e10f 100644 --- a/pcbnew/pcb_netlist.h +++ b/pcbnew/pcb_netlist.h @@ -109,11 +109,10 @@ class COMPONENT /// The #FPID of the footprint assigned to the component. FPID m_fpid; - /// The #MODULE loaded for #m_footprintName found in #m_footprintLib. + /// The #MODULE loaded for #m_fpid. std::auto_ptr< MODULE > m_footprint; - /// Set to true if #m_footprintName or #m_footprintLib was changed when the footprint - /// link file was read. + /// Set to true if #m_fpid was changed when the footprint link file was read. bool m_footprintChanged; static COMPONENT_NET m_emptyNet; diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 58208e320b..5712ab3992 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1549,7 +1549,14 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR module->SetInitialComments( aInitialComments ); NeedSYMBOLorNUMBER(); - fpid.SetFootprintName( FromUTF8() ); + + if( fpid.Parse( FromUTF8() ) >= 0 ) + { + wxString error; + error.Printf( _( "invalid PFID in\nfile: <%s>\nline: %d\noffset: %d" ), + GetChars( CurSource() ), CurLineNumber(), CurOffset() ); + THROW_IO_ERROR( error ); + } for( token = NextTok(); token != T_RIGHT; token = NextTok() ) { @@ -1566,12 +1573,6 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR module->SetIsPlaced( true ); break; - case T_fp_lib: - NeedSYMBOLorNUMBER(); - fpid.SetLibNickname( FromUTF8() ); - NeedRIGHT(); - break; - case T_layer: module->SetLayer( parseBoardItemLayer() ); NeedRIGHT(); diff --git a/pcbnew/target_edit.cpp b/pcbnew/target_edit.cpp index 348f56b102..ed31e1dfc8 100644 --- a/pcbnew/target_edit.cpp +++ b/pcbnew/target_edit.cpp @@ -24,7 +24,7 @@ */ /** - * @file dialog_target_properties.cpp + * @file target_edit.cpp * @brief Functions to edit targets (class #PCB_TARGET). */ From b00d23c46c638a97dc22b1f81cc1e5840046997d Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Tue, 17 Sep 2013 10:03:16 -0400 Subject: [PATCH 24/29] Fix board parsing error when module name is empty. (fixes lp:1226546) --- pcbnew/pcb_parser.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 5712ab3992..4ef1695f2d 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1540,17 +1540,19 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR wxCHECK_MSG( CurTok() == T_module, NULL, wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) ); - wxPoint pt; - T token; - FPID fpid; + wxString name; + wxPoint pt; + T token; + FPID fpid; auto_ptr< MODULE > module( new MODULE( m_board ) ); module->SetInitialComments( aInitialComments ); NeedSYMBOLorNUMBER(); + name = FromUTF8(); - if( fpid.Parse( FromUTF8() ) >= 0 ) + if( !name.IsEmpty() && fpid.Parse( FromUTF8() ) >= 0 ) { wxString error; error.Printf( _( "invalid PFID in\nfile: <%s>\nline: %d\noffset: %d" ), From df0a195f389e23c4ed961e55d2fd012efc2ee34e Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Tue, 17 Sep 2013 11:51:05 -0400 Subject: [PATCH 25/29] Fix two more FPID empty string parsing bugs. --- cvpcb/readwrite_dlgs.cpp | 13 ++++++------- pcbnew/legacy_plugin.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cvpcb/readwrite_dlgs.cpp b/cvpcb/readwrite_dlgs.cpp index 1096833b90..43d94bbdb5 100644 --- a/cvpcb/readwrite_dlgs.cpp +++ b/cvpcb/readwrite_dlgs.cpp @@ -74,17 +74,16 @@ void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) // Check to see if the component has already a footprint set. hasFootprint = !component->GetFPID().empty(); -#if defined( USE_FP_LIB_TABLE ) FPID fpid; - wxCHECK_RET( fpid.Parse( aFootprintName ) < 0, - wxString::Format( wxT( "<%s> is not a valid FPID." ), - GetChars( aFootprintName ) ) ); + if( !aFootprintName.IsEmpty() ) + { + wxCHECK_RET( fpid.Parse( aFootprintName ) < 0, + wxString::Format( wxT( "<%s> is not a valid FPID." ), + GetChars( aFootprintName ) ) ); + } component->SetFPID( fpid ); -#else - component->SetFPID( FPID( aFootprintName ) ); -#endif // create the new component description description.Printf( CMP_FORMAT, componentIndex + 1, diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index c03dacbf76..2b8e98fff2 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -278,8 +278,13 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) { auto_ptr module( new MODULE( m_board ) ); + FPID fpid; std::string fpName = StrPurge( line + SZ( "$MODULE" ) ); - module->SetFPID( FPID( fpName ) ); + + if( !fpName.empty() ) + fpid = FPID( fpName ); + + module->SetFPID( fpid ); LoadMODULE( module.get() ); m_board->Add( module.release(), ADD_APPEND ); From 5761c182ee5b90f322881d5665c91757ede45e6b Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Wed, 18 Sep 2013 07:15:17 -0400 Subject: [PATCH 26/29] Fix std::string to wxString conversion bug in Pcbnew. (fixes lp:1226670) --- pcbnew/xchgmod.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pcbnew/xchgmod.cpp b/pcbnew/xchgmod.cpp index 11dbbf7b5d..b2cc016880 100644 --- a/pcbnew/xchgmod.cpp +++ b/pcbnew/xchgmod.cpp @@ -324,14 +324,15 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ) check_module_value = true; value = m_CurrentModule->GetValue(); msg.Printf( _( "Change modules %s -> %s (for value = %s)?" ), - m_CurrentModule->GetFPID().Format().c_str(), + GetChars( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ), GetChars( newmodulename ), GetChars( m_CurrentModule->GetValue() ) ); } else { msg.Printf( _( "Change modules %s -> %s ?" ), - lib_reference.GetFootprintName().c_str(), GetChars( newmodulename ) ); + GetChars( FROM_UTF8( lib_reference.Format().c_str() ) ), + GetChars( newmodulename ) ); } if( !IsOK( this, msg ) ) From 7ceb13d041d6365337871a09c8619912a55c607b Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 18 Sep 2013 21:21:11 +0200 Subject: [PATCH 27/29] Fix minor bugs in cleanup dialog options and plot solder mask function (thanks to Lorenzo to locate these bugs) --- pcbnew/class_board.cpp | 6 ++++- pcbnew/class_board.h | 6 +++-- pcbnew/clean.cpp | 27 ++++++++++++------- .../dialogs/dialog_cleaning_options_base.fbp | 12 ++++----- pcbnew/dialogs/dialog_cleaning_options_base.h | 3 --- pcbnew/editrack.cpp | 5 +++- pcbnew/plot_board_layers.cpp | 6 ++--- 7 files changed, 40 insertions(+), 25 deletions(-) diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index d7e8dcb6cd..97d8b0b622 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -1500,7 +1500,8 @@ void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDr ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos, LAYER_NUM aStartLayer, - LAYER_NUM aEndLayer ) + LAYER_NUM aEndLayer, + int aNetCode ) { if( aEndLayer < 0 ) aEndLayer = aStartLayer; @@ -1520,6 +1521,9 @@ ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos, if( area->GetState( BUSY ) ) continue; + if( aNetCode >= 0 && area->GetNet() != aNetCode ) + continue; + if( area->HitTestFilledArea( aRefPos ) ) return area; } diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 5ba5c2174d..b234a1cd3d 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -1079,12 +1079,14 @@ public: * Note: if a zone has its flag BUSY (in .m_State) is set, it is ignored. * @param aRefPos A wxPoint to test * @param aStartLayer the first layer to test - * @param aEndLayer the last layer (-1 to ignore it) to test + * @param aEndLayer the last layer to test + * @param aNetCode = the netcode used to filter zones (-1 to to test all zones) * @return ZONE_CONTAINER* return a pointer to the ZONE_CONTAINER found, else NULL */ ZONE_CONTAINER* HitTestForAnyFilledArea( const wxPoint& aRefPos, LAYER_NUM aStartLayer, - LAYER_NUM aEndLayer = UNDEFINED_LAYER ); + LAYER_NUM aEndLayer, + int aNetCode ); /** * Function RedrawAreasOutlines diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index dc426d0c6c..2fdd6e9975 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -117,9 +117,9 @@ void PCB_EDIT_FRAME::Clean_Pcb() wxBusyCursor( dummy ); TRACKS_CLEANER cleaner( GetBoard() ); - cleaner.SetdeleteUnconnectedTracksOpt( dlg.deleteUnconnectedSegm ); - cleaner.SetMergeSegmentsOpt( dlg.mergeSegments ); - cleaner.SetCleanViasOpt( dlg.cleanVias ); + cleaner.SetdeleteUnconnectedTracksOpt( dlg.m_deleteUnconnectedSegm ); + cleaner.SetMergeSegmentsOpt( dlg.m_mergeSegments ); + cleaner.SetCleanViasOpt( dlg.m_cleanVias ); if( cleaner.CleanupBoard() ) { @@ -321,13 +321,16 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() if( track->Type() != PCB_VIA_T ) { zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(), - track->GetLayer() ); + track->GetLayer(), + track->GetLayer(), + track->GetNet() ); } else { ((SEGVIA*)track)->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(), - top_layer, bottom_layer ); + top_layer, bottom_layer, + track->GetNet() ); } } @@ -354,7 +357,9 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() { via->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( via->GetStart(), - bottom_layer, top_layer ); + bottom_layer, + top_layer, + via->GetNet() ); } if( (other == NULL) && (zone == NULL) ) @@ -376,13 +381,16 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() if( track->Type() != PCB_VIA_T ) { zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(), - track->GetLayer() ); + track->GetLayer(), + track->GetLayer(), + track->GetNet() ); } else { ((SEGVIA*)track)->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(), - top_layer, bottom_layer ); + top_layer, bottom_layer, + track->GetNet() ); } } @@ -410,7 +418,8 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() { via->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( via->GetEnd(), - bottom_layer, top_layer ); + bottom_layer, top_layer, + via->GetNet() ); } if( (other == NULL) && (zone == NULL) ) diff --git a/pcbnew/dialogs/dialog_cleaning_options_base.fbp b/pcbnew/dialogs/dialog_cleaning_options_base.fbp index 049bec3cf1..c58c091a28 100644 --- a/pcbnew/dialogs/dialog_cleaning_options_base.fbp +++ b/pcbnew/dialogs/dialog_cleaning_options_base.fbp @@ -155,10 +155,10 @@ 0 remove vias on pads with a through hole - bool + wxFILTER_NUMERIC wxDefaultValidator - cleanVias + @@ -243,10 +243,10 @@ 0 merge aligned track segments, and remove null segments - bool + wxFILTER_NUMERIC wxDefaultValidator - mergeSegments + @@ -331,10 +331,10 @@ 0 delete track segment having a dangling end - bool + wxFILTER_NUMERIC wxDefaultValidator - deleteUnconnectedSegm + diff --git a/pcbnew/dialogs/dialog_cleaning_options_base.h b/pcbnew/dialogs/dialog_cleaning_options_base.h index 7ec1ebe541..deb7df99b4 100644 --- a/pcbnew/dialogs/dialog_cleaning_options_base.h +++ b/pcbnew/dialogs/dialog_cleaning_options_base.h @@ -50,9 +50,6 @@ class DIALOG_CLEANING_OPTIONS_BASE : public DIALOG_SHIM public: - bool cleanVias; - bool mergeSegments; - bool deleteUnconnectedSegm; DIALOG_CLEANING_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Cleaning Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 243,146 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_CLEANING_OPTIONS_BASE(); diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index b3ea13790d..9c39eaf228 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -147,7 +147,10 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) // Not a starting point, but a filled zone area can exist. This is also a // good starting point. ZONE_CONTAINER* zone; - zone = GetBoard()->HitTestForAnyFilledArea( pos, GetScreen()-> m_Active_Layer ); + zone = GetBoard()->HitTestForAnyFilledArea( pos, + GetScreen()-> m_Active_Layer, + GetScreen()-> m_Active_Layer, + -1 ); if( zone ) GetBoard()->SetHighLightNet( zone->GetNet() ); diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index eab18aa97f..8ba01ab009 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -58,7 +58,7 @@ * unless the minimum thickness is 0. */ static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, - long aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt, + LAYER_MSK aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness ); /* Creates the plot for silkscreen layers @@ -463,7 +463,7 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, * (shapes will be better, and calculations faster) */ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, - long aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt, + LAYER_MSK aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness ) { LAYER_NUM layer = ( aLayerMask & SOLDERMASK_LAYER_BACK ) ? @@ -480,7 +480,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, { for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { - if( aLayerMask != item->GetLayer() ) + if( layer != item->GetLayer() ) continue; switch( item->Type() ) From c1025612d149635212b2b49a90266683a68f873b Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Thu, 19 Sep 2013 18:50:30 -0500 Subject: [PATCH 28/29] Lorenzo's help enabled a fix to UTF8 support in csv.writer in python bom generators. --- scripts/bom-in-python/bom_csv_by_ref.py | 19 ++++++--- scripts/bom-in-python/bom_csv_by_ref_v2.py | 19 ++++++--- .../bom-in-python/bom_csv_grouped_by_value.py | 39 +++++++++++-------- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/scripts/bom-in-python/bom_csv_by_ref.py b/scripts/bom-in-python/bom_csv_by_ref.py index 51f8e34a39..b651afac2a 100644 --- a/scripts/bom-in-python/bom_csv_by_ref.py +++ b/scripts/bom-in-python/bom_csv_by_ref.py @@ -27,16 +27,23 @@ except IOError: # are created a tab delimited list instead! out = csv.writer(f, lineterminator='\n', delimiter='\t', quoting=csv.QUOTE_NONE) +# override csv.writer's writerow() to support utf8 encoding: +def writerow( acsvwriter, columns ): + utf8row = [] + for col in columns: + utf8row.append( str(col).encode('utf8') ) + acsvwriter.writerow( utf8row ) + # Output a field delimited header line -out.writerow(['Source:', net.getSource()]) -out.writerow(['Date:', net.getDate()]) -out.writerow(['Tool:', net.getTool()]) -out.writerow(['Component Count:', len(net.components)]) -out.writerow(['Ref', 'Value', 'Part', 'Documentation', 'Description', 'Vendor']) +writerow( out, ['Source:', net.getSource()] ) +writerow( out, ['Date:', net.getDate()] ) +writerow( out, ['Tool:', net.getTool()] ) +writerow( out, ['Component Count:', len(net.components)] ) +writerow( out, ['Ref', 'Value', 'Part', 'Documentation', 'Description', 'Vendor'] ) components = net.getInterestingComponents() # Output all of the component information for c in components: - out.writerow([c.getRef(), c.getValue(), c.getLibName() + ":" + c.getPartName(), + writerow( out, [c.getRef(), c.getValue(), c.getLibName() + ":" + c.getPartName(), c.getDatasheet(), c.getDescription(), c.getField("Vendor")]) diff --git a/scripts/bom-in-python/bom_csv_by_ref_v2.py b/scripts/bom-in-python/bom_csv_by_ref_v2.py index e3bef12118..30c8faaabb 100644 --- a/scripts/bom-in-python/bom_csv_by_ref_v2.py +++ b/scripts/bom-in-python/bom_csv_by_ref_v2.py @@ -26,17 +26,24 @@ except IOError: # Create a new csv writer object to use as the output formatter out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar="\"", quoting=csv.QUOTE_ALL) +# override csv.writer's writerow() to support utf8 encoding: +def writerow( acsvwriter, columns ): + utf8row = [] + for col in columns: + utf8row.append( str(col).encode('utf8') ) + acsvwriter.writerow( utf8row ) + # Output a field delimited header line -out.writerow(['Source:', net.getSource()]) -out.writerow(['Date:', net.getDate()]) -out.writerow(['Tool:', net.getTool()]) -out.writerow(['Component Count:', len(net.components)]) -out.writerow(['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor']) +writerow( out, ['Source:', net.getSource()] ) +writerow( out, ['Date:', net.getDate()] ) +writerow( out, ['Tool:', net.getTool()] ) +writerow( out, ['Component Count:', len(net.components)] ) +writerow( out, ['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor'] ) components = net.getInterestingComponents() # Output all of the component information (One component per row) for c in components: - out.writerow([c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(), + writerow( out, [c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(), c.getField("Manufacturer"), c.getField("Vendor")]) diff --git a/scripts/bom-in-python/bom_csv_grouped_by_value.py b/scripts/bom-in-python/bom_csv_grouped_by_value.py index dba801bc06..29203e33f2 100644 --- a/scripts/bom-in-python/bom_csv_grouped_by_value.py +++ b/scripts/bom-in-python/bom_csv_grouped_by_value.py @@ -47,15 +47,22 @@ columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Data # Create a new csv writer object to use as the output formatter out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL) +# override csv.writer's writerow() to support utf8 encoding: +def writerow( acsvwriter, columns ): + utf8row = [] + for col in columns: + utf8row.append( str(col).encode('utf8') ) + acsvwriter.writerow( utf8row ) + # Output a set of rows as a header providing general information -out.writerow(['Source:', net.getSource()]) -out.writerow(['Date:', net.getDate()]) -out.writerow(['Tool:', net.getTool()]) -out.writerow(['Component Count:', len(components)]) -out.writerow([]) -out.writerow(['Individual Components:']) -out.writerow([]) # blank line -out.writerow(columns) +writerow( out, ['Source:', net.getSource()] ) +writerow( out, ['Date:', net.getDate()] ) +writerow( out, ['Tool:', net.getTool()] ) +writerow( out, ['Component Count:', len(components)] ) +writerow( out, [] ) +writerow( out, ['Individual Components:'] ) +writerow( out, [] ) # blank line +writerow( out, columns ) # Output all the interesting components individually first: row = [] @@ -74,16 +81,16 @@ for c in components: for field in columns[7:]: row.append( c.getField( field ) ); - out.writerow(row) + writerow( out, row ) -out.writerow([]) # blank line -out.writerow([]) # blank line -out.writerow([]) # blank line +writerow( out, [] ) # blank line +writerow( out, [] ) # blank line +writerow( out, [] ) # blank line -out.writerow(['Collated Components:']) -out.writerow([]) # blank line -out.writerow(columns) # reuse same columns +writerow( out, ['Collated Components:'] ) +writerow( out, [] ) # blank line +writerow( out, columns ) # reuse same columns @@ -121,6 +128,6 @@ for group in grouped: for field in columns[7:]: row.append( net.getGroupField(group, field) ); - out.writerow( row ) + writerow( out, row ) f.close() From 180e0a3645c8e439f4fe207e1535c65b1f0d901b Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Fri, 20 Sep 2013 10:11:45 -0500 Subject: [PATCH 29/29] BOM generators now report count of "interesting" components, rather than total components --- scripts/bom-in-python/bom_csv_by_ref.py | 6 +++--- scripts/bom-in-python/bom_csv_by_ref_v2.py | 6 +++--- scripts/bom-in-python/bom_html_by_value.py | 6 +++--- scripts/bom-in-python/bom_html_grouped_by_value.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/bom-in-python/bom_csv_by_ref.py b/scripts/bom-in-python/bom_csv_by_ref.py index b651afac2a..046272dec4 100644 --- a/scripts/bom-in-python/bom_csv_by_ref.py +++ b/scripts/bom-in-python/bom_csv_by_ref.py @@ -34,15 +34,15 @@ def writerow( acsvwriter, columns ): utf8row.append( str(col).encode('utf8') ) acsvwriter.writerow( utf8row ) +components = net.getInterestingComponents() + # Output a field delimited header line writerow( out, ['Source:', net.getSource()] ) writerow( out, ['Date:', net.getDate()] ) writerow( out, ['Tool:', net.getTool()] ) -writerow( out, ['Component Count:', len(net.components)] ) +writerow( out, ['Component Count:', len(components)] ) writerow( out, ['Ref', 'Value', 'Part', 'Documentation', 'Description', 'Vendor'] ) -components = net.getInterestingComponents() - # Output all of the component information for c in components: writerow( out, [c.getRef(), c.getValue(), c.getLibName() + ":" + c.getPartName(), diff --git a/scripts/bom-in-python/bom_csv_by_ref_v2.py b/scripts/bom-in-python/bom_csv_by_ref_v2.py index 30c8faaabb..ccb303e097 100644 --- a/scripts/bom-in-python/bom_csv_by_ref_v2.py +++ b/scripts/bom-in-python/bom_csv_by_ref_v2.py @@ -33,15 +33,15 @@ def writerow( acsvwriter, columns ): utf8row.append( str(col).encode('utf8') ) acsvwriter.writerow( utf8row ) +components = net.getInterestingComponents() + # Output a field delimited header line writerow( out, ['Source:', net.getSource()] ) writerow( out, ['Date:', net.getDate()] ) writerow( out, ['Tool:', net.getTool()] ) -writerow( out, ['Component Count:', len(net.components)] ) +writerow( out, ['Component Count:', len(components)] ) writerow( out, ['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor'] ) -components = net.getInterestingComponents() - # Output all of the component information (One component per row) for c in components: writerow( out, [c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(), diff --git a/scripts/bom-in-python/bom_html_by_value.py b/scripts/bom-in-python/bom_html_by_value.py index 244248ad71..b4493f5fe4 100644 --- a/scripts/bom-in-python/bom_html_by_value.py +++ b/scripts/bom-in-python/bom_html_by_value.py @@ -77,12 +77,14 @@ except IOError: print(__file__, ":", e, file=sys.stderr) f = stdout +components = net.getInterestingComponents() + # Output a set of rows for a header providing general information html = html.replace('', net.getSource()) html = html.replace('', net.getDate()) html = html.replace('', net.getTool()) html = html.replace('', "Component Count:" + \ - str(len(net.components))) + str(len(components))) row = "Ref" + "Qnty" row += "Value" + "Part" @@ -92,8 +94,6 @@ row += "PartNumber" + "Vendor" html = html.replace('', row + "") -components = net.getInterestingComponents() - # Get all of the components in groups of matching parts + values # (see kicad_netlist_reader.py) grouped = net.groupComponents(components) diff --git a/scripts/bom-in-python/bom_html_grouped_by_value.py b/scripts/bom-in-python/bom_html_grouped_by_value.py index 11bcc5dfb0..175191bcc4 100644 --- a/scripts/bom-in-python/bom_html_grouped_by_value.py +++ b/scripts/bom-in-python/bom_html_grouped_by_value.py @@ -42,12 +42,14 @@ except IOError: print(__file__, ":", e, file=sys.stderr) f = stdout +components = net.getInterestingComponents() + # Output a set of rows for a header providing general information html = html.replace('', net.getSource()) html = html.replace('', net.getDate()) html = html.replace('', net.getTool()) html = html.replace('', "Component Count:" + \ - str(len(net.components))) + str(len(components))) row = "Ref" + "Qnty" row += "Value" + "Part" + "Datasheet" @@ -55,8 +57,6 @@ row += "Description" + "Vendor" html = html.replace('', row + "") -components = net.getInterestingComponents() - # Get all of the components in groups of matching parts + values # (see kicad_netlist_reader.py) grouped = net.groupComponents(components)