From e2d5d30c64f7da3d2d2f07a75528586cb564193d Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 2 May 2025 20:13:44 -0400 Subject: [PATCH] GP-5327 - Fixed sizing issues with the data type and category editors --- .../images/CreateStructureDialog.png | Bin 21891 -> 17400 bytes ...reateStructureDialogWithTableSelection.png | Bin 23404 -> 22036 bytes .../app/cmd/data/CreateStructureCmd.java | 27 +- .../compositeeditor/CompositeEditorPanel.java | 23 +- .../core/data/CreateStructureAction.java | 4 +- .../core/data/CreateStructureDialog.java | 235 +++++++++--------- .../core/datamgr/DataTypeManagerPlugin.java | 1 + .../core/datamgr/archive/DataTypeIndexer.java | 59 ++++- .../archive/DataTypeManagerHandler.java | 8 + .../core/datamgr/tree/ArchiveRootNode.java | 54 ++-- .../datamgr/util/DataTypeChooserDialog.java | 37 ++- .../editor/ParameterDataTypeCellEditor.java | 31 +-- .../datatype/CategoryPathSelectionEditor.java | 145 +++++------ .../datatype/DataTypeSelectionEditor.java | 65 ++++- .../AbstractScreenShotGenerator.java | 5 +- .../docking/widgets/DropDownTextField.java | 2 +- .../docking/widgets/button/BrowseButton.java | 6 +- .../screenshot/DataPluginScreenShots.java | 19 +- 18 files changed, 423 insertions(+), 298 deletions(-) diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/images/CreateStructureDialog.png b/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/images/CreateStructureDialog.png index c7d030078b8889aad0689a03d92482025e5cb634..1b542fe2ad9b653dcd41368d5384c8c7c0f45407 100644 GIT binary patch literal 17400 zcmc({by!qy_b#p|AT82@q=M4jAq|2c-6f?WIdqD2i%6G%bjJY0&>b@%T>~gF^dLDj zXXEF6-|zQ#opY}1{LVk;4`w#Q?7i3X>}RcY-)r3u5pUEK32-0d-nny!Kv_vn^Uj^S zN5IdQ2N=L7)1#R2ckalxDa%P~dz$WMN`;fa>3X&Fe|ScbI>vW)wi{7;;@u;sZH~bs z$709Vr>y#7&d?##Nv2p8Z_e-=7l-^&#Y2}6C%p#{nedp0cno?ptC2y*&OPMhMwgKs z><2!~3F+zSvkM;47jotqzF6_LO_ z*G6aGbPVzbMJ74^D1 z4u^O;x1+*d6^48xI-u~m3vRy5n^;=lj}O`vG-hrTxQc#5i1{^3+XGmc1R=X4u|KP z52e}F;7@4COXg<}=2hLwfBMRT)R`$M^ZV91pAdEu?y;%x8vzQ=o9wn$!USsVwQ3s+_-ak?+2*(67WS_ zj>KCiearp^U0y870tKYKC~m7zoNyY;&#Wj~cfae$r;Dlk&h=5gl_70*374JHw60wZ z*68_RB;Wg%^W4awFcVu>f_*g38OfJeU%`Os1%%Rkhp062I>*F>0%l|spHyJ!B>J+3K2Gv`-+QIC^|Ocy880y@$xhi ztmV9!_jFW`zTvt=*VmxPpDdKKRq;yONf!@H0huc`c9v*6sH-|CdgE(S6n+L3zC*7e zVO;DtsG|qUS7h_He|ndHN#M|fdx6m3w&%ySn#H!3B4@pjp?>$OHm7d3UUm3mnC4A6 zecMe-nCqqn&U?xwV*!3sp@W2iXHKiAbq>g2(Hnk`rUc5>nu%Xf{j&0@_=?I&o$cYE z+|djTTR8%E5Klw+)3}qqdf_BH`aZ(+2vc>~WAmNjxesoQLKCxdJN#3u@MN~~)A?IDT8Ao=Ooay=W@oxZ4yzv=X=o^;=lW}E!H|#$ z7D^Q14tUs#Ok9n#ezC!-iqNJ*KV*8Ws|M6oba1gGS3Ee5JNC}nh5)ODOJX%SJAC;L ziEXN*ws4(j1VOy~>f0+fSpf#4O7Tic`&75kX>%cpfGDM}Gv{?{2)0+zbx&vlO$Gf4 zoHp-(`o8Zt^82VqUL}VNCm5StLSI%KIOLx}#x5cUlp4UZMGi?J^?mH~C|}C`KViZ$=AYhH-++bceEG^kA3P>; zEN{(-wHgmESIg2rTy+Y``|M&g>%FNl`>wN$uNeyp;rmFee8(lY$Rdwf`R$B;hs8!d zU}ISx%y`XzYtzLj=ev7YH$B5QRjreG@31s;)lP8@Eg``Ma8(>%$*X zi_{G}1wY_LkGNT&_71Ku5`VkrT|j29jko=_kJ{YCvJDf7@&_xJS{2F6^2u4Hn0*Jt zMnEwQlT+SWen=dKU}LhoNXa?sMlm%iUh-hGUa*0g3R|IL zp6SKqR*Umkb9^M4+%hSWewd~Ew6T}1=2L%* zYssP3k_cFMx`0Z7*@d$Y(Y3f1-oX5JGXK##)OZixPH$Psj*uv$J{#HgZi?=^buMat zG@gR*^>KVPHGf+bAIpj|!=XJ$B*bJuS%(D-e>eR>{+lLY?j&egGB9zYHE-;^kh4fz z-~T1F);)w>a$$Alm0IH1Sp7{_9a*bw!SVJL(Oz>VVN8P|j*;7k?M}T+#wz(M_*Xlo z6*riBxkCmkrFJ?y??QqC+uO-~!#q|3pSalz@v4Xf?!3^Ao_zTfAHQ@ zaNn~`Oe9*O9nnWBuQ74(ju3>tStpTsV1WA$75wn)%V7u9;>~48&h)~es8sWb(0(Mp zi+Jfji-0ff;!pp!FFH*uueVV8%CfC>w2N)5Us`f%j)Pd{!I^zV58@)sbh~tZhNe!E z===h;!D6#-*~}P26Mr))AH6`y5d3AS3xSL^5NW19JX*}cQ*QvyW(+;_0Du)MlFwr= zz<(VY27$P^Q#knl@^JTSZc1xo!iqmRMt7jTpMFmnuo?@<*F%+kw0E5K6TMfgJvbbV zC7Pd0>z@CrFxbnHd{+SiG{!uKGOy5j!()qb6D>8H!by}x!++xV6{ zEH7lI-JoJ7>lN=SZCCIMq8alQ^O4@;{dG(LINVGbK|p;>R}vbBIoEfZYS{vk4?Vi+ zAMJZva*v;vHZ9-;ESHpflz$W~-64yg-8O*j52+6>j=YyR@1~0w{jHRwqe+HEE@bE$ zhd@X{I^qJes5E3zy~<7(vPR5bf_(E_fB_pK`Ow2emDkl=ZPL3>PD5)|zU;kjHIu(J zliQvSMX;-ON}|WH$Q4T%Y;X^T;we_-zN82X-ij)LjohU7`O@h|MFgxFVAhvLZi7R} zgbcgcKCmHJJs0b;OS0M@|IE$UT!GzFq&T|!e!uNxgw_2j7~mf;Th#8Jsb3z~Ix=&? z9HiKqG0k*4vSPd9cI7(##8(|WlesBx_SDw?r~p-WF6wZkH~T>dBiUz{vtk zd{tOGVPjp79>q)(&=fh91oFFlanuH2xZaR2(!ZF`!;dFZO}(;~Mg@s(JJ!248nEJ3 zXniF|F|CoBQoj=X9i3lji#0`0$U>4lvIMitCUv0rq7a+W2}F=(?rezJmVk#JF^R1o zW5Cw{rs?aS?s3M#yrw$EDLrmSjLS`DQX-ypgZQO)!;*&k)P5&bxiz~BiuG4_0rBty z5D$Axv6$;3Rho>j60F_$a(@rQ8(yzh+#5Oe_f9FN*rTwPjOGcJWLGRQPO@e&REn1tFN%z^*D28y-ikI8Y#p4ZqPKQnycaX|+M3K)S7MO(4 z>JEP_zuOLWo9l_|iX{yExOv6Ikgd*f&q=(03064%zWJo}$Z*dHLY+`(xWxJWTS>`v zNmfgiJi!`^_1^kGP%h`6Q(_xbOJz%E`R5%A+giRU=F!0q@$UlO<%RJou9bqvCn~EE z4<8t@>QU*)v)NF}YYgQ#B2CRoeWXl!_INy+-94KANROnaRl@F{1sv*QYPp*<9F$=M z>E0cdux%9TW^K%>y1tMHHy$iS;@dU97xs{+jHMHnDrzlyyleWv0!hfUIJbD<7tkoh zF2y;d+GSN89zYQ0nq&H{ zKc$|DjnD3QN=fJ&?MpkGf)wqCO|bj$Cq9|HX*R2~99B<(c!P}P=-gN6 zq0EB1*yisy1v2J!#Uo5p={(^JMXZMW9+9tpB=sWh8mn46*gIN`r8OlDnvQf9uM2nt zEbkRbBjiD)pWryrA}kij*x~gXGW6m1&Bf^~*vAT?H63QiJ5SD7i$Ca10zo=47Q29$ zZM#BL5|xoo$O|_^C zvpVNO%owB0fz^MNdV2^Mms|0QAFUFMRMVKyi9q^C9F>Q~1M$qU%js#_MTo_ooy>z& zig}}9EcjLD2H=wN8tWu*KjOc>rZ$S8`0HNlr2qM76DcW5L*S3U6Llc^;Ej3#Ulsi7 z!?iH`-CKtgE&K+FBUD(vX$eTZTi_pYL#0jhVhq4Dl(&`)zpzH7d>wIjFE+Eh8Xb?s zu z!fl89$*s@hXkoxxj*7GcbQ%t?#`(OTt~Owwx6zg;O?&}d(CSQi_F{8D^(m`5+cI&1 zkPG}c0o#wh?YudX3HPN;57YPKibS|gd^?VuPhR;}Um*6G@JT;+B3J4*{QL9Bn#7kN zijl~9Jb&2x>m_mK18%d%4?t4uF>^Ejr;_D8+1yi`k`aSDv>|F_KWy{OO9aAr|6jC2&R_-Y3{#u zrPUTSaMEHoR*fC8}>`HI0am2*GG_@(I6G25-VN9loA-BaG1rAp&91k(VJTkB;fm*+zk$*Fyd|eya zY=nh#aO+kjl^I zLPiviy>u=$x~_jhw(0G$<$iik4=%yx&jdj&Q~(aG|MuE!YKdsVbPACd|8^GMa#o)T zx9M3+E@VkITmJGY!cIC+QJ(tm9DH+0k2+uBzI_79>5v=R+XR%Ub*_D&d415(YKS)0 zlLp1zgJTn@9$|m9mrw3+m9yhr;Bk7 z0cAc-l8-1LuK)cj7x34c+YFr_dYhhcfFSX|e0@5Du;a2rjVb}DEH6mo#;6TCzA(4g z3E+lXY!iHG^TTmljnGnka@q!lXvsF+vmg(Bjt1Ld5G8{e%eO9BHMie_*`p3bq3_p|Fe=-y4Q5Qx{2w za!m(ix!CjY;)u4$QIcJv-OJa+W{oD4mz4d!N7w{8ju2`H(wnb}1t@*LM*W1nbqK8i%G^9 zqxT~|4;x$1Ry#l42S`MXQgXh2<*{>C{`O!b0^}5n@pGg->$W;;>kqm?2*ilXh4Vkg zJ8C6qXvwl~weNg+3{KJQ^0oGM6_!yoCkQ<{of~>=8n4^IOFWZdXvfZ&Q^DH-6xWmA ztIp`4xif_#ft8}e(+0`5Mf!7C8|!uC@^)W0NZRxrJnEY|NrDB(Y*jqj$O=q-zO5Oby)me*k5|A z96;z1=WM7H#4g{d^vg9H!IyUd!Voqrt&d(8xTeP{qJKPKOFj0i4Y(T-Cbol*c!%PK z$~{;-hWHox2h|68g>yxMb1YeV)hMI39H=q^zJJ_$3_#SHhX8GCvAz!3T4SidFi1`T zF#IdwD9FX7BUQ}S;ns#ZKY~uw_4yMorsI2bHF2pgMOC+Db6y|&>Vu=F|*d1(7{@gV6~zt&nM@6Spo}gLDlFoQM5=Mr03pUrVH8m;PY%yK51Q~^VwHL^)P^B2 z4d+U`aMWT=sQvsn&b`904yN&xj&HO{RVmkO zG52)`%zc~yPdpIn(Hhf5mEog9O9WX}`O)&)`~DiHk=5nn^}hhJ-!ak-8Q^NJIjM2iwD}!EXjxw|zWA<70M_VvJ0!`bV91Sx0Q$1c zYyarAneQs#+`<;%l{LmPx;(-_;ip|o$6)R6?@&?CKT0ys9lWndVFJLy^}gI9?Gb7; zqG!g=nh~u&oV62-Ne$dFMIvHbp5(VyBvp$c_!O7lBL(x3t6vAID2cn_nX|~B z8hk9sW3`ia+CJ3Ru_Ga^Nw@$s8x=s%b$;bePL4YH9#{Lk;;>s7=YcW*fridj-4Pg% z6DZPI_5roIn7m>t2^D_ysb-$MZ_armJ6GFF;j(2p?t}r#t^rED(WqN%Rp>_!#{ym# zvX15%3pqD~KiFra`sf=l;p=3cF&-zX+{oxq)ITUxR63P5a|@0@(wbSgN0VsL7`F_- z`8)}z-Tt{uR8i+HhC=h7p92fLiMC_{puTQwkQdqe=z~NtHh`gf^1mXZBb}UUw?irD zSXjp}8}1nnOJHLXN4%$CJO->z5wqDKzHiF;fCMhl+PNc~4hQh{fU~K$zNW?Kig=me zt7#hKqUYov9g#G)Cz4>aWQn zTh~?HES=hEmK%XIIQbq0)T|Jm&rW6SrmcEj>3Y2+V-FT|kzndYbtzA#F)nw#vA$=d z=T=gs%DjT$B0N!4X#L76HbYGwM`zURVr#t(65^J0Gyc&g=87UC#{bfuyP({1oCs9| zwdB7AY9ofm?pV++L`+7dh|L&efrx=79S7!?Ef{&@8-v8w8lt==`z^w%sdpE~~F*4Zmf@6NrbeN1)Ib@5PF zT-4vjxy8+=`(Cv9zOV$F8MeTLnb3}Jh{l`lHc_zDJ?QUjhnCatGm9JaqjMYd=Y`5(kLqJj^a?U;a8k zGAx6RGkKHUti()0Q%kL|Eu5XGNByTHd!AEl@upYU!XqFu3hO*J(h?PDEi!R03RKi* zVE}(pS&p{%dfGieI_BN(#9(|bpBA^*QPm810l80WXML6B5a-%SnK08MW=7E$mXlg($q3PQ%;a!=#bf#fx``J68qm|7KT@ z9U1kjit39H3V&x}RvI>tV1Ous> zvJ)_Q5V!>Q_v0Lsx{BopJKuy#fmI%}MVU{polP9=pklSim)cdQk8b+DpD(YfTy98G z_E`2(%hgp>3e*>!R!xZenL5(5FfEgRmUYAHD2}DVvO=%~rta8};vyD5Jizy(ONqNzB*y=LZS6ygk#wage-p0!90p8X@| zPRX#|M`KI!pI;+z{#)SdUrxJ7$$cIvT6)W=G;l}(67`%l5D1^7^3Q;lZe(uJeE<(> zkS4z5NPrY-zDNX0bJ?aZuJOz;l?0X|!}ynVMuLr}%Oxw34yv^5UJ^#WZ?xf=*H^(m zH**VryyZ<*-S>BP<>oy|w34hZZPgvQN>C{rf7ftSG;!l!liJn7z#1QCD~A#FA+ba{ zc~HBYa^X|xMc3Dp@P3rq^z+;wku#b+ML(QW#5=|=HaG2Js#1I`X~rb@ymR0Cu5x}I zGx9)*mV0oJ1@XH~EI-4c4#~0pG0FTx*wr#R)wzG>XVmjz#(Hho7{LPGXiXaQG+<(6 z98Enpw&=(-k@2+rCdX{PP=N|>saqNHBlIy zF<2YvdDwlAMj;bUc+RfJz<20T09kZpk->;Mrxz<;(?4JQf|Ezh;zkQ`NzT2e5HGCR zF=G<6uo-ZWbJIIlyZfW&OvZ&M?egJSVcvu zCG*>l_jM@?)}Ay`Th zamRW^q>#;1Tz%*k(Z_l{A_QV#Ri_;(S~su0{J}mRNH!-6@@=9ns@*Th(cQ!?<5qQd zGGFR!vY<$g+{pT-!F|m+X4HqM2MGRsfZy;Wv#7TIf+(cP>P^FVNO%M>*zgkos?t#9 zFw>LI*u>(-Ad9{<)CKjisXbbQSnQR0R{fym&ho98qqctvM3_N}Fw`HC?5YO7H>~=! zE|bR0Wsh8Cvqs+1T9iFfJXpaAAtfKxNhK`%Nt>o1v?H4M_Xg28Q49aMg*9p2$~}+x zQPJUm!<)z5hmUvt~?(m8xfztdbg#28&;o7z=Rk0o*q`4cpm=Z6&7BJhSnP%#@Wh-^GFKn z%jr!T`X$B}3%Qn17dB`oo5~GF|0JzCNiH&Go-}N!7xrPw_0eS2ZWSEwE_D6v*)MiUgcTRduC`ts}jpVGzwW-Z~y>G7UWuk*={$~@4FB5A_ zCVa(X7t2BxjSDnMG+0)gS*cJ&7D69P1y^Qbo$0w~=v43tOGp0B%kt5i0m9g<>uv-! z@j?PG?%aN%yN1#>FTP#geADyE>8-8%#_H)l5wdy}1e>8Ig_;?(tg{_M0V-r6zbN zbl58tC@ihJR3GBTv^;1IqkT2o5vYgX^FvY5MKr)7W9)%k(&8?mvsHm_PW z!SC@{$?!PTYEls3U}@KK0ojY*OPy5J-lg7VKKlH=(#mf4daCo!JIFfaBU zM82d!gn(seO&Yx@Z&9uia@_HSmOLr;=fnXsiH?K>;gZTL-fY=qSv|U@^O7ppV4!u| zD}kkXN?C;W-BX2CU7eQQz}wSh++lD`nJg(94AjlN5`qkRoGA@E#KPRyLWTemdX(M} zQQ*<3wu%5nJKp@MR=ipBs{tf0y2a=D+Csg(3yn7>?eNZ1D+L658E+rYNw09TkEZtz z?QTxq&&QeE^;4nBM0hHS4_GF)WGf2$e)}jZBS9N38(U)1W@Lc1ys2XH95vk8I&GP=;slCL9GD`pA#GSBzw~!1X1U*LF{?@R3<9+IqOty*8E3+=x{{JAjH+-fc}+4E3ksXA5|(y`uZPxxM$KkB z{+WUv=e7@J6bzn_B@9?)T=aBYKW}=3E;KWe@PGJh&QE{qNdw+FRCayw=tY#0xrXEO zDz`k5JZkeQA@&dI-iULAK;-k;<81=v*Vo@=#lu}zz0VDq*pZ8WWSeXi)Ss^8dBlHP zJRdYEge+?EC^0E=m_7Ny=OIhQB{VEe503Ik_bRMJcc<0g&ne@ zo+hHRymRX0=;~gkx>5hAN6aZcqW||{^j}C!N|amHT4v#~5<^Yfm^olM63x8){WA~7 z2fO3WU8>tie=v?4`WfA}|Hph{@gY&}x6&^-c<-9+m&YFf$XD{+&fHN81Brr=cIJ$N z@64ZK1#CuEd|6COkK;C?l93*>?f(k*E$yFqJmMF<_tHH>OMKC{jrAi@u6wTd{#$k? zonP1_*b`}!*WS($;;^SLzlr1NW$e{753wlvRr+L$LOunut=1ZjT$~lBD!6k&A#yI+ zxy}%v63r6L>PCqTNC06kjy|{{=Z3tw7x`2*cYL4Rr-uz==MP9pZi`UzkGh)^3Ea2} z$z@hjyG!TwtM2@2Zw+zl;^d6jFg5Qug(^7$==p)IbS{`7E2o5_?J0NSEqaFXiym;> zC2Uqbd89AclS6A6EgzlVj@wlgbnk+EiU8X9G}mVob7TNWrYYr@3EQtbo6Nd{p2z3y zF=e2@l6CRzY?6GebYaUKivzP69mYNem~?dQg`kA0S3mQ|n4JA1P2QD_v2cAI7?ouE zo15SpSX(q%72}-L*Z>fH2z9hrsESfyY@*QTMso5R_PuCpE(_GVI=cDVE=RV$fKqqn ztVB!2La>uwI~Vm)S`u5nsOse2`Nc-HMbT4}CT421*ONeSIUqv+7h}_|Ua8}=H%Dfc z4wqNtAKgtBO{#vkik%xqRp=OM)!O(F;tnkJ46f2yg11(VWE(#`wO984lL@9_qQ^C% zJCqVL{ec9te&cpgwLt8#ohTy*7UqXjOG}5Yh$r4 zy^%9W{q;r+q#KJ`}`fJ42PxD&K_q^8E8SkdV`lQm2!&?kpw`8cE) zTPyvNHCx*)gV_21BWHjp3`y7kj$yEgurr$^~xMQ!B3J%n&n zJCmij#IU9x0 zEyjei`SJKrl1H~DGI7cE&faDyO3XYD4gKwtITcJT$18VIF?vR+sCn)EmtM|OHshU1bqJiJVi4Ch@Y#~6UM5RbOBBqjzU^0_QPmLp9*wWW{cqr(fUOak?i81KA*N3;i8MG*)%` z{ab5)dcYxf)TqWEc$;@|s!tcuo~e0=|LWiTVO~ifdz(If&LYOzM)2A4cO!}!2TOuY zA^__UITh=Gbv1wKK+sw7b$T&GSlvJdBL_m_!n5kIie=j}e;{s+1GF6^)5mQMwPr1b zVuAGWpSJ*Jq%_|5-Ip^$vAQN*)z)gZBJAw$r-~pwa{8es9jW-}yi8e7vh^;VIQ} zq5y5x-SbDy*^R^@$e9w7t!;q5XVHB&7{ZSF9#O$g9OljVeprRs&5rI;+}m@pv`;;g zW|J1EnCV+_JsNDwCrUYMZOPcs({DV*rQLHlR1O>Z1kfNH-4uxBFzRCEdeqZN^~MPy zMTtJS+OKp*n-c~&w%B!yPfA1q5`E-+0m0=0Cp8I#LjgI_Ai!ew4y2c*cH4Zt#N|Ve zHF0~a?F=sELx_x}E&Iv?Xy&X5e$8dVV_n^0OFSSVt41kk3HNF}Woncis(8F+`f-HH z=fC$4hCs8pkA8Resl%??>8_3>x=$?|E%)7=oS%#w0>xrr?2ttSAW3k&Itujx^iFGE zO$3=;jG|#7f*xXHrqoZ|{Q;_%XdaU4ts6{Qo~=<>=~P!EMrXZiD1Pk(k^PH4%3Tk!%y3@{t_K=qB z?}ahbpcms@{*;sM&4b8pgp?1M%hY;)n@+W&Ssl68PJ)!IilUAtR1CyNhjFtxm)n#R zCQthL*vPZe=ue|PpY=`q@G66hM+fPHsqUS>X>SCk)-2U%9W|6I6HeX{= zF@*1tR-@NiLjMa#?{Y3vGk=KpbB7-hmbZ_Rd!nJt$qUMYWigE6%7bicrdr@Aqp}g^ z9!*f^kKLrEA(^`uxBzT=reB|*Bn3I<`s3UX@QWxQ78BJ7U1ushnPqcq92c`C?8%G= zR03ByPn5PzR8oCFEydAn7+omR|4i$ND-(OBTIoulwz;;uu4yunyVb1QwiX8pIMwD=bS?#z6=y z^;cCNL1>m~MCNqYpkl-2a0tY*-t=lUX$h}#dN2AYASM(1X_>gaV>I{Rxo1*t-NNsN^T_0d;4oIrLAy$ z^A>6Ck1OxY?PR?CJ97CH==Ry9IBc zb;{3?=cVU^0c>3@zc7S z*)}QlYzx1iLHa(?@lL>qO|7>yCLzv;#qyW<2!jHPrIajc>n;pAd+7Mw8+&uxTScG& z1}Ln$6ATC;nilsb~2Gof4|d%sFgXSd6!7mgm^_S@}%FEAac zx>8gsF=3xIKgoJ{AZB0;3iC)7YC&ChPjKAI4f>Y;r9QAxWRYq0Eebc`#<^uK#FiAQfaqXYK~5(nJxl~jI>p$_38;~FtvNiHlGO@pXFqOQ zC`-BnThfNRKBqyOhb6)Cj`$>84vmkTrEQvQXgseZIzNvn>%$L3FY45P<2GNT5N?1n zDQF?^bY=O|%nGNdAY0;Lpz%-^_lRc6AWFH%*7k?TEH*8GtPLou@tejg#L``d?+TBg-+agV zx1b@}4JC4*8NEB~4%%|Axn7mp=Gj&xa)v#ZVAV1EGx7q5frY&Yk}RpVj$Dvfa(Dma zOZ7=9uZ(9zhdjbS1PK8rzm=@8*$_Qvs$UULRUf@VNC^I+lKG*bYYZ|g|4kY6Li}-v zVrfM4D9s?FYB~H0bWkS+d9MHu{vwr%DS*byhNx`Wxs~-~=&c1yycHYf1Cy<%LbiW7 zY5E)Y8k=%%!7a$j0Cl6b$VSdq?IK9#!9K+lg6lF3%9Wk=4Gt)9J)fXnoAB-s&x7EI z5fFUg4iBJ|ZUn#UEzGZx?u`zRuskifTHkkz%TfHmcD$@BsGf!qJjtykx#e# zF9DAg$b94>fA~?x2~aYRLI(h)K-1CzKfNZ(Dtbs{!rQ8lD6=C! z)LP%#6f^;9{n+vG0d%}d@gugR*1RXGemHdx)aTm_?DNp=_CrnA3V#WwYov7ye?^(j zBpo*DMaqs~{UuSu#u9v44J^e&iV`4Z*#Kfzzv~7dEM_DEI0@&5>?@!Zvc`b{jl%xs z+c5MLD69X!d{tU*o#K-05L?Sjj_X5m^J7@BlSXSgq|ft(;;mrO$wjf93OYC|jwU z$|64WNMj3+eLt$LRVW%&EWfiexAlW1AgcU9DQi{PXfR!!MxX#?YMU1*7pFA!A#Va8 zO_r?dlHk+&JYunb?di&G(!E2Q;C&yexcudfA5S@fJG&1(J}Il zt`^z>^WGIRJySorA77GFWp2rXBy6zb<_$PR%8}^uF<3FL^P(rfT3Vf2rJ9`zlZ*v{ z+<2+IM>Mq}&vI85$G1&HOu{)&8=-69&l+jJ`SaCe+DN$-aEj;K zTp)S_+WV+eNRFrve#D&L7pLO!MYX)k&x*Q=6*I6 z2sO(ROBk4}rN}X)MbLY+p9oPTe2Iid*i@Lygbzbt66a~q*6@fQJX9ITrH9iU3rwSg zrd?$pZ2UPFVG>R}WsbsIu9D{=MvVBCnXlt5!(KSyw~wk7bj^L;s0d4l&@$q&E1}k% zdVn`ybb6WfUl;asI(JB2q*#Jbe8d(W_drF)i5kCz5$vf?=L)Nmq;^U0SZL>esl1R$ z2`TPL0n#r;*ZGvE#IQ||04^2K3)=ZW9H;plPe?mCvGbhE0K!*Mi6cvcidg<&|4aTu z9w1NP@o0SV{!h9POWH=oBN;~FWI!JIo>x`mD%mR=dQ}~~U@rOsr44a&S$n+SuWCYq z)~0`%*m?IJ+1xOh&CkXC1>PcTYmFRQa+4{dO`{v=siyQ|dk~;Gv($?UN@#A8^A};~ z>pJJ^P-8<#wlb{+)sr2ZeBD|7&U+?0UBO!R5%z?ZviJ}%AbKLT;svn`>AC3hKxrhyEr7|OA? z&{CsY01z@V4E1~j(E$xS4V5A)q=WkD?N)-j|0jI??{{cXqv1$3j6c`w4FR5OuPYmW zGvE7&SKnV-ug&{cn|!`>K5%FLGe?b3!lj532yL82eJcM7Vhnf|A1&;BG zv{|if!z%CXW{JVe%s^`>2}7W~)gX8f za=vuYzxUBy?Um^l&OwB_;HuI@=<={cAAZyQ|J)PUFW=()k>N!ZLQB_&r^4qi+ zj@6Uc$#vC0#uB`5exCv%=|E3L)8g!{A3591G!6HuUE4@zlJi|9XeF7wWwENX%&RR& zbLgl8+fqE3!n^@2)4EssO8X_vDB|YbJJi!JL);!b>QWiQ5V;K||-<{V9ZRg?6`Xl;TlXkzX@i`)4B+$%#rb zz-u(ZvR*3}2${!pqm>1*fL?-F0*${y%*r``B9dkPHLJnER)c>%#)oM>7;>PSyd1#V zf7bQi5&up|Niy|)G)_kd&%EDhTg2ILimxLBT+5RrfD0(1{B^&BGLA%`jFPf`(srD1 zw_g4-E(V;sN(7XN{+BZ2f4G2E=wH30%RjWU0LgisJ7?J78hsMxZbQG%G?33bN7n;W zrOacBed!X>K2`{HA9gNj13ZWnxphCuxfWQt(jTnIMgCe*8ga9hrrNyX7vk{G6h$%M z;(iGq#(&Dq%gy(ty}upy5`*a;UjR#>B(S4(!d$!)e)kbCz*9JhQbgEIQlOsv7p1+9 z-|G!aB`c@QChtDd#~=DOp(n3)Y#@-^7#msES~N8+M_JTTX2HYmVv`v;_aX1RStH=t zON=Os)WG`+STARMc>f# literal 21891 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 VDl0Yo71+{uK}|236rXd6_!q+Hc;5g3 diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/images/CreateStructureDialogWithTableSelection.png b/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/images/CreateStructureDialogWithTableSelection.png index be32a0fe221c27ec31e343b53feac2767dca32fd..e4bad542cd9e11daff29395c411581b09a05c825 100644 GIT binary patch literal 22036 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 literal 23404 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¥7SRDw~BTw*42mKkNYl=7ExmRH1EIF zF14LF5vXQ#{WYnOs{U6%^(a=UJm^xkMCn*3(%$y7Adc|&>moEXhtUbE&Y4gBGb?^0 zfM0gh%DV&Yv)5!?1*B8+$NoPUJMQ*jA7(6&Gi7rez~7y`ADKZ|N7049sQAAO;UAjt ze_#IVyZzsu3A`)#82?pBEYxh}B#~!Dnrw@DnTrqI7z!f1E!Kv1rdD~#%9`Q_ozQkSsmDw|v%(n^!JFO0W zUXCBw$N%FZR$zeZX%aS1|Hhw~Q@()YjOEnO3F%fJRjt1FYh`qjenXR|=i*jn7f;~z zjd?!QtTz@DBfi0;vgY`!bVy+F&4&*kfHS-}t5updHzz7f#J z2M5#qAIkGtp%s8BfWQD7FQb2_!nt-yhuY+^JIu0~jdCbOz0Q~J@%3>;wqC&8xX86> zdr#gu$@I++i$HfuiMGAdBBA!-wXYH6)AW+X#rRKd_=#MJILwEKwDtZt2JrJ{rB))P z&i_@J2LXLN035MZRRE9k_3|oop3?o#oMvog(F}}*O0_?E+hSY_C53ZtC2x-JyyU^S z!Al2o+(UjKhcgp`AR(%zGcKg4=`hSzR6=`P^XC9D$*n4zyPuNaCq5%V3Io6&0H)&Y z119`wT?q9B8<8P!IktW|)M2)Px>Iob-AL4XAdYtXfvUg7N2n4`+4I{Pk>R>G=wkPi z9y8*euaIchw^yS-FdkE9ga!gy5NKmf7(UG<>$@^)4xAexc3^ybT-*~_%~_hA`?3Ha ziP|OPTgksWay#b2Sb;%yjPh;)$Tbj;UE$cLkcRsEU4b&TmJ^i1OURjQGAVSdCa&V) z_0~w=#(NBeJ{gm0j}=OCxYE2S6Y9?CvOCMEVLxQgg}7N1sK zTMJTVK#JG}pqB@rx`NA(zCQBqVwt*{npPcUYq9+kfi9!03AR)*3s2vi>YzIu>p&)E(RoybnZa{R=y7o z3h24HiO*L0FIxnOvOV70SqBUfKz}T%U2}7D0h0^rJ)^?GF1b3?Jt(feT4SZ%P@&bl zRx1W`YWyRUn}SLxO|nki&7i0+%UntCob4Z(6h}J}U4nAOql*!X)f(?&L;pM&dU|@J zfzh$C_%uIHPk_{`b8+ZkqzzI6@FOEqUH~-8M1T-6a)5 z#oFDmR%QkD;!&mr*%G|#C6#i!2^|?|C%Zj5{j+tuJ?)bPKW;P2%8%_6ZHdkLZGyiM z`)Qw*AP|t&14yHah`b+}T~YV^VV`&#WT!M(lDXwx78j7-L0s4O9Y z(tIneQ0_K1D&7G3I|07FAQ)kDZS9g*Ok|`sz?GE|bpR=T zS$7VIlRbb|yR1x-ETTZUE^ztsWd=PhtxHtE0b#LN08mXa8n5*whDNbd7ct^N^X1aI z@C<8-sKATP1Z2iom1And)}0|ao6T)wp0RCfM4DkFl`+A(Ck`YK>U|7jxQw@#nw$U!4q}+jGKTg znMLa%4MPrBNJYi9F~!ZTEiP$iPx1!1A%ntT{mx-fP?=Hwk%o-Ied(4gq3T%ed))8H zuFODKAEQO3N{$!TT|Yp<14{a@vb?a9H>O|C;PKnMvdO^0LK}LDkugf6Zw%-sXxpux z^3Y_mpYcB0fj)y~2=)@uYMY+;9Q-}^R^ppRCY9M&WJZE!Cc)+Wi?n$O#mO`Wb27)? zyYepHt1V19T|~v`X%%H2y?Ub+=ZN@Y)n3`M9!^GAW=tkTLgGaDEvl6Y{r8@-$p=04 z)--ZUPG3xLwJqKr+^e>7zCnz%t^A%~zOH#EyH8kWU{~h-bF}j)F%H5xnWJ*;&fr4f zk6A=esSIWcYX+};UH$yVieAxj_$p=A3?p+nlb@5MI2(QYv9C=)&qS1wgOzZ0G4XDj zZ{#H>m>RUo70#^D=PB>Y?KD|(9tk}YemQeTNU)RV^v2pI7L^#lnExfM|FM4ydulcl z_)OH}>&_GIf1WKi)VMRzg}}R^|D53S;%A{|!s@flXOz refs = findExistingRefs(refMgr, program.getAddressFactory(), getStructureAddress(), endAddress); listing.clearCodeUnits(getStructureAddress(), endAddress, false); @@ -123,20 +116,20 @@ public class CreateStructureCmd extends AbstractCreateStructureCmd { return data.getDataType(); } - private Reference[] findExistingRefs(ReferenceManager refMgr, AddressFactory af, Address start, + private List findExistingRefs(ReferenceManager refMgr, AddressFactory af, + Address start, Address end) { - ArrayList list = new ArrayList(); + List list = new ArrayList(); AddressIterator it = refMgr.getReferenceSourceIterator(new AddressSet(start, end), true); while (it.hasNext()) { Address addr = it.next(); Reference[] refs = refMgr.getReferencesFrom(addr); Collections.addAll(list, refs); } - Reference[] refList = new Reference[list.size()]; - return list.toArray(refList); + return list; } - private void addRefs(Program p, ReferenceManager refMgr, Reference[] refs) { + private void addRefs(Program p, ReferenceManager refMgr, List refs) { for (Reference ref : refs) { refMgr.addReference(ref); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java index 79a5bdedcb..2abce33b4a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java @@ -1158,8 +1158,6 @@ public abstract class CompositeEditorPanel Swing.runLater(() -> stopEdit(tool))); + JButton browseButton = editor.getBrowseButton(); + browseButton.addActionListener(e -> Swing.runLater(() -> stopEdit(tool))); textField.addFocusListener(new FocusAdapter() { @Override @@ -1226,10 +1215,6 @@ public abstract class CompositeEditorPanel { + if (e.getValueIsAdjusting()) { + return; + } + + if (useExistingStructButton.isSelected()) { + setOkEnabled(table.getSelectedRowCount() > 0); + } + }); filterPanel = new GhidraTableFilterPanel<>(table, structureTableModel) { // make sure our height doesn't stretch @@ -527,6 +502,18 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { return false; } + JTextField getNameField() { + return nameTextField; + } + + JTable getTable() { + return matchingStructuresTable; + } + + CategoryPathSelectionEditor getCategoryEditor() { + return categoryPathEditor; + } + /** * Shows a dialog that allows the user to create a new structure. *

@@ -577,34 +564,58 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { @Override protected void okCallback() { - if (nameTextField.isEnabled()) { - // just use the name set by the user - String nameText = nameTextField.getText(); - - if (!setCategoryPath()) { - return; - } - - try { - currentStructure.setName(nameText); - } - catch (InvalidNameException ine) { - setStatusText(ine.getMessage()); - return; - } - catch (DuplicateNameException dne) { - setStatusText(dne.getMessage()); - return; - } - } - else { + if (useExistingStructButton.isSelected()) { // get the selected object in the table currentStructure = getSelectedStructure(); + close(); + return; + } + + // just use the name set by the user + String nameText = nameTextField.getText(); + try { + currentStructure.setName(nameText); + } + catch (InvalidNameException ine) { + setStatusText(ine.getMessage()); + return; + } + catch (DuplicateNameException dne) { + setStatusText(dne.getMessage()); + return; + } + + if (!setCategoryPath()) { + return; + } + + if (!validateName()) { + return; } close(); } + private boolean validateName() { + // Use the current name and category path to see if there is already an existing name. This + // allows us to avoid a conflict. + ProgramBasedDataTypeManager dtm = currentProgram.getDataTypeManager(); + CategoryPath path = currentStructure.getCategoryPath(); + Category category = dtm.getCategory(path); + if (category == null) { + return true; + } + + String nameText = currentStructure.getName(); + DataType existingDt = category.getDataType(nameText); + if (existingDt != null) { + setStatusText("Name already exists: " + nameText, MessageType.ERROR); + return false; + } + + return true; + } + private Structure getSelectedStructure() { int row = matchingStructuresTable.getSelectedRow(); if (row < 0) { @@ -616,66 +627,43 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { } private boolean setCategoryPath() { + + try { + doSetCategoryPath(); + } + catch (DuplicateNameException e) { + setStatusText(e.getMessage(), MessageType.ERROR); + return false; + } + return true; + } + + private void doSetCategoryPath() throws DuplicateNameException { CategoryPath path = categoryPathEditor.getCellEditorValue(); // First see if a category from the list was chosen and make sure the user didn't modify it. // If they did, path needs to be parsed separately. - if (path != null && path.getPath().equals(categoryPathEditor.getCellEditorValueAsText())) { - try { - currentStructure.setCategoryPath(path); - } - catch (DuplicateNameException dne) { - setStatusText(dne.getMessage(), MessageType.ERROR); - return false; - } - return true; + String editorValue = categoryPathEditor.getCellEditorValueAsText(); + if (path != null && path.getPath().equals(editorValue)) { + currentStructure.setCategoryPath(path); + return; } - String categoryText = categoryPathEditor.getCellEditorValueAsText(); // Selecting/entering a category is optional; root is default - if (!categoryText.isBlank()) { - try { - CategoryPath parsedPath = parseEnteredCategoryPath(categoryText); - currentStructure.setCategoryPath(parsedPath); - } - catch (DuplicateNameException dne) { - setStatusText(dne.getMessage(), MessageType.ERROR); - return false; - } + if (!editorValue.isBlank()) { + CategoryPath parsedPath = parseEnteredCategoryPath(editorValue); + currentStructure.setCategoryPath(parsedPath); + return; } - else { - try { - currentStructure.setCategoryPath(CategoryPath.ROOT); - } - catch (DuplicateNameException dne) { - setStatusText(dne.getMessage(), MessageType.ERROR); - return false; - } - } - return true; + + currentStructure.setCategoryPath(CategoryPath.ROOT); } private CategoryPath parseEnteredCategoryPath(String categoryText) { // entering a leading slash is optional, path is still generated accordingly if (categoryText.startsWith(CategoryPath.DELIMITER_STRING)) { - return generateCategoryPath(categoryText.substring(1)); + return new CategoryPath(categoryText); } - return generateCategoryPath(categoryText); - } - - private CategoryPath generateCategoryPath(String categoryText) { - if (!categoryText.contains(CategoryPath.DELIMITER_STRING)) { - return new CategoryPath(CategoryPath.ROOT, categoryText); - } - - // Additional slashes need parsed as branch(es) and final leaf - List parts = split(categoryText); - return new CategoryPath(CategoryPath.ROOT, parts); - } - - private List split(String categoryText) { - List parts = new ArrayList( - Arrays.asList(categoryText.split(CategoryPath.DELIMITER_STRING))); - return parts; + return new CategoryPath(CategoryPath.DELIMITER_STRING + categoryText); } // a table model that is used to allow for the easy updating of the table with new List data @@ -707,7 +695,7 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { case 0: return STRUCTURE_COLUMN_NAME; case 1: - return PATH_COLUMN_NAME; + return CATEGORY_COLUMN_NAME; } return null; } @@ -735,8 +723,7 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { case 1: { Structure structure = t.getStructure(); CategoryPath path = structure.getCategoryPath(); - String name = structure.getName(); - return path.toString() + '/' + name; + return path.toString(); } } return null; @@ -779,7 +766,7 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { } // we need this renderer in order to create nice tool tip text values - class StructureCellRenderer extends GTableCellRenderer { + private class StructureCellRenderer extends GTableCellRenderer { @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { @@ -799,7 +786,7 @@ public class CreateStructureDialog extends ReusableDialogComponentProvider { renderer.setToolTipText(ToolTipUtils.getToolTipText(structure)); } } - else if (PATH_COLUMN_NAME.equals(columnName)) { + else if (CATEGORY_COLUMN_NAME.equals(columnName)) { if (value != null) { renderer.setToolTipText(value.toString()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java index 8576090598..4d25970811 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java @@ -598,6 +598,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin public CategoryPath getCategoryPath(TreePath selectedPath) { DataTypeChooserDialog dialog = new DataTypeChooserDialog(this); dialog.setCategorySelectionMode(true); + dialog.setShowProgramArchiveOnly(true); if (selectedPath != null) { dialog.setSelectedPath(selectedPath); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeIndexer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeIndexer.java index d9c4ce1c0d..cc17249fce 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeIndexer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeIndexer.java @@ -169,10 +169,37 @@ public class DataTypeIndexer { } } + private class CaseInsensitiveCategoryComparator implements Comparator { + + @Override + public int compare(CategoryPath cp1, CategoryPath cp2) { + + String name1 = cp1.getName(); + String name2 = cp2.getName(); + + int result = name1.compareToIgnoreCase(name2); + if (result != 0) { + return result; + } + + result = name1.compareTo(name2); + if (result != 0) { + // let equivalent names be sorted by case ('-' for lower-case first) + return -result; + } + + // if the names are the same, then sort by full path + String p1 = cp1.getPath(); + String p2 = cp2.getPath(); + return p1.compareToIgnoreCase(p2); + } + } + private class IndexerTask extends Task { private List dataTypes = new ArrayList<>(); - private List categories; + private List categories = new ArrayList<>(); + private Set categorySet = new HashSet<>(); IndexerTask() { super("Data Type Indexer Task", false, true, true); @@ -184,26 +211,32 @@ public class DataTypeIndexer { monitor.initialize(dataTypeManagers.size()); monitor.setMessage("Preparing to index data types..."); - for (DataTypeManager dataTypeManager : dataTypeManagers) { - monitor.setMessage("Searching " + dataTypeManager.getName()); - dataTypeManager.getAllDataTypes(dataTypes); + for (DataTypeManager dtm : dataTypeManagers) { + monitor.setMessage("Searching " + dtm.getName()); + dtm.getAllDataTypes(dataTypes); + + Category root = dtm.getRootCategory(); + populateCategories(root); + monitor.incrementProgress(1); } Collections.sort(dataTypes, new CaseInsensitiveDataTypeComparator()); - populateCategoryList(dataTypes); + + categories.addAll(categorySet); + Collections.sort(categories, new CaseInsensitiveCategoryComparator()); } - private void populateCategoryList(List dataTypes) { + private void populateCategories(Category parent) { - Set set = new HashSet<>(); - for (DataType dt : dataTypes) { - CategoryPath path = dt.getCategoryPath(); - set.add(path); + categorySet.add(parent.getCategoryPath()); + Category[] children = parent.getCategories(); + for (Category category : children) { + CategoryPath path = category.getCategoryPath(); + categorySet.add(path); + + populateCategories(category); } - - categories = new ArrayList<>(set); - Collections.sort(categories); } List getList() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java index 0f2c6ac04a..634ef9bd49 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java @@ -674,6 +674,13 @@ public class DataTypeManagerHandler { return builtInDataTypesManager; } + public DataTypeManager getProgramDataTypeManager() { + if (programArchive != null) { + return programArchive.getDataTypeManager(); + } + return null; + } + public DataTypeIndexer getDataTypeIndexer() { return dataTypeIndexer; } @@ -1810,4 +1817,5 @@ public class DataTypeManagerHandler { } return null; } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/ArchiveRootNode.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/ArchiveRootNode.java index 3d0a4e4537..ede28c2b21 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/ArchiveRootNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/ArchiveRootNode.java @@ -34,8 +34,15 @@ public class ArchiveRootNode extends DataTypeTreeNode { private DtFilterState dtFilterState = new DtFilterState(); - ArchiveRootNode(DataTypeManagerHandler archiveManager) { + private boolean programDtmOnly; + + public ArchiveRootNode(DataTypeManagerHandler archiveManager) { + this(archiveManager, false); + } + + public ArchiveRootNode(DataTypeManagerHandler archiveManager, boolean programDtmOnly) { this.archiveManager = archiveManager; + this.programDtmOnly = programDtmOnly; init(); } @@ -93,21 +100,29 @@ public class ArchiveRootNode extends DataTypeTreeNode { } // a factory method to isolate non-OO inheritance checks - private static final GTreeNode createArchiveNode(Archive archive, DtFilterState dtFilterState) { + private final GTreeNode createArchiveNode(Archive archive, DtFilterState filterState) { + + if (programDtmOnly) { + if (archive instanceof ProgramArchive) { + return new ProgramArchiveNode((ProgramArchive) archive, filterState); + } + return null; + } + if (archive instanceof FileArchive) { - return new FileArchiveNode((FileArchive) archive, dtFilterState); + return new FileArchiveNode((FileArchive) archive, filterState); } else if (archive instanceof ProjectArchive) { - return new ProjectArchiveNode((ProjectArchive) archive, dtFilterState); + return new ProjectArchiveNode((ProjectArchive) archive, filterState); } else if (archive instanceof InvalidFileArchive) { return new InvalidArchiveNode((InvalidFileArchive) archive); } else if (archive instanceof ProgramArchive) { - return new ProgramArchiveNode((ProgramArchive) archive, dtFilterState); + return new ProgramArchiveNode((ProgramArchive) archive, filterState); } else if (archive instanceof BuiltInArchive) { - return new BuiltInArchiveNode((BuiltInArchive) archive, dtFilterState); + return new BuiltInArchiveNode((BuiltInArchive) archive, filterState); } return null; } @@ -178,7 +193,10 @@ public class ArchiveRootNode extends DataTypeTreeNode { public List generateChildren() { List list = new ArrayList<>(); for (Archive element : archiveManager.getAllArchives()) { - list.add(createArchiveNode(element, dtFilterState)); + GTreeNode node = createArchiveNode(element, dtFilterState); + if (node != null) { + list.add(node); + } } Collections.sort(list); return list; @@ -221,15 +239,21 @@ public class ArchiveRootNode extends DataTypeTreeNode { @Override public void archiveOpened(Archive archive) { - if (isLoaded()) { - GTreeNode node = createArchiveNode(archive, dtFilterState); - List allChildrenList = getChildren(); - int index = Collections.binarySearch(allChildrenList, node); - if (index < 0) { - index = -index - 1; - } - addNode(index, node); + if (!isLoaded()) { + return; } + + GTreeNode node = createArchiveNode(archive, dtFilterState); + if (node == null) { + return; + } + + List allChildrenList = getChildren(); + int index = Collections.binarySearch(allChildrenList, node); + if (index < 0) { + index = -index - 1; + } + addNode(index, node); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeChooserDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeChooserDialog.java index 4542ea9ef5..873a022744 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeChooserDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeChooserDialog.java @@ -31,12 +31,14 @@ import docking.DialogComponentProvider; import docking.Tool; import docking.widgets.filter.FilterOptions; import docking.widgets.filter.TextFilterStrategy; -import docking.widgets.label.GLabel; +import docking.widgets.label.GDLabel; import docking.widgets.tree.*; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; +import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler; import ghidra.app.plugin.core.datamgr.tree.*; import ghidra.app.util.datatype.DataTypeSelectionDialog; import ghidra.program.model.data.*; +import ghidra.util.HelpLocation; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; @@ -46,17 +48,20 @@ import ghidra.util.task.TaskMonitor; * {@link DataTypeSelectionDialog} utility widget. */ public class DataTypeChooserDialog extends DialogComponentProvider { + + private DataTypeManagerPlugin plugin; private DataTypeArchiveGTree tree; private DataType selectedDataType; private CategoryPath selectedCategoryPath; - private GLabel messageLabel; + private GDLabel messageLabel; private boolean isFilterEditable; private boolean categorySelectionMode; public DataTypeChooserDialog(DataTypeManagerPlugin plugin) { super("Data Type Chooser", true, true, true, false); + this.plugin = plugin; tree = new DataTypeArchiveGTree(plugin); @@ -98,6 +103,8 @@ public class DataTypeChooserDialog extends DialogComponentProvider { addOKButton(); addCancelButton(); setOkEnabled(false); + + setHelpLocation(new HelpLocation("DataTypeEditors", "browse")); } /** @@ -106,6 +113,29 @@ public class DataTypeChooserDialog extends DialogComponentProvider { */ public void setCategorySelectionMode(boolean categorySelectionMode) { this.categorySelectionMode = categorySelectionMode; + if (categorySelectionMode) { + setTitle("Category Chooser"); + messageLabel.setText("Choose a category:"); + } + else { + setTitle("Data Type Chooser"); + messageLabel.setText("Choose a data type:"); + } + } + + public void setShowProgramArchiveOnly(boolean programOnly) { + DataTypeManagerHandler handler = plugin.getDataTypeManagerHandler(); + if (programOnly) { + DataTypeManager programDtm = handler.getProgramDataTypeManager(); + if (programDtm != null) { + ArchiveRootNode root = new ArchiveRootNode(handler, true); + tree.setRootNode(root); + return; + } + } + + ArchiveRootNode root = new ArchiveRootNode(handler); + tree.setRootNode(root); } private boolean isValidNodeSelected() { @@ -152,7 +182,7 @@ public class DataTypeChooserDialog extends DialogComponentProvider { private JComponent createWorkPanel() { JPanel panel = new JPanel(new BorderLayout()); - messageLabel = new GLabel("Choose the data type you wish to use."); + messageLabel = new GDLabel("Choose the data type you wish to use."); messageLabel.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 2)); messageLabel.getAccessibleContext().setAccessibleName("Message"); panel.add(messageLabel, BorderLayout.NORTH); @@ -335,4 +365,5 @@ public class DataTypeChooserDialog extends DialogComponentProvider { } } } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java index e7603d7a6f..96c5581574 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.*; +import java.awt.Component; import java.awt.event.*; import java.util.EventObject; @@ -32,16 +32,15 @@ import ghidra.app.util.datatype.DataTypeSelectionEditor; import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataTypeManager; import ghidra.util.MessageType; +import ghidra.util.Swing; import ghidra.util.data.DataTypeParser; class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCellEditor, FocusableEditor { private DataTypeSelectionEditor editor; private DropDownSelectionTextField textField; - private JButton dataTypeChooserButton; private DataType dt; - private JPanel editorPanel; private DataTypeManagerService service; private DialogComponentProvider dialog; private DataTypeManager dtm; @@ -62,7 +61,7 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor editor.setCellEditorValue(dt); - return editorPanel; + return editor.getEditorComponent(); } private void init() { @@ -83,17 +82,8 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor } }); - // force a small button for the table's cell editor - dataTypeChooserButton = new JButton("...") { - @Override - public Dimension getPreferredSize() { - Dimension preferredSize = super.getPreferredSize(); - preferredSize.width = 15; - return preferredSize; - } - }; - - dataTypeChooserButton.addActionListener(e -> SwingUtilities.invokeLater(() -> { + JButton browseButton = editor.getBrowseButton(); + browseButton.addActionListener(e -> Swing.runLater(() -> { DataType dataType = service.getDataType((String) null); if (dataType != null) { editor.setCellEditorValue(dataType); @@ -104,18 +94,13 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor } })); - FocusAdapter focusListener = new FocusAdapter() { + textField.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { textField.selectAll(); textField.removeFocusListener(this); } - }; - textField.addFocusListener(focusListener); - - editorPanel = new JPanel(new BorderLayout()); - editorPanel.add(textField, BorderLayout.CENTER); - editorPanel.add(dataTypeChooserButton, BorderLayout.EAST); + }); } @Override @@ -136,7 +121,7 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor * be returned if getTableCellEditorComponent method has not yet been invoked. */ public JButton getChooserButton() { - return dataTypeChooserButton; + return editor.getBrowseButton(); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/CategoryPathSelectionEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/CategoryPathSelectionEditor.java index 228014a685..183822a561 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/CategoryPathSelectionEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/CategoryPathSelectionEditor.java @@ -15,11 +15,14 @@ */ package ghidra.app.util.datatype; -import java.awt.Component; +import java.awt.*; import java.awt.event.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import javax.swing.*; +import javax.swing.border.Border; import javax.swing.event.*; import javax.swing.tree.TreePath; @@ -30,7 +33,6 @@ import docking.widgets.list.GListCellRenderer; import ghidra.app.services.DataTypeManagerService; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.data.CategoryPath; -import ghidra.util.exception.AssertException; /** * An editor that is used to show the {@link DropDownSelectionTextField} for the entering of @@ -92,6 +94,8 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { private void init() { selectionField = createDropDownSelectionTextField( new CategoryPathDropDownSelectionDataModel(dataTypeManagerService)); + selectionField.setName("CategoryPath"); + selectionField.getAccessibleContext().setAccessibleName("Category"); selectionField.addCellEditorListener(new CellEditorListener() { @Override public void editingCanceled(ChangeEvent e) { @@ -113,16 +117,12 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { selectionField.requestFocus(); } }); - selectionField.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); - browseButton = new BrowseButton(); - browseButton.setToolTipText("Browse Existing Category Paths"); - browseButton.addActionListener(e -> showBrowser()); + JPanel browsePanel = buildBrowsePanel(); editorPanel = new JPanel(); editorPanel.setLayout(new BoxLayout(editorPanel, BoxLayout.X_AXIS)); editorPanel.add(selectionField); - editorPanel.add(Box.createHorizontalStrut(5)); - editorPanel.add(browseButton); + editorPanel.add(browsePanel); keyListener = new KeyAdapter() { @@ -144,6 +144,60 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { }; } + private JPanel buildBrowsePanel() { + + // We override the various sizes to make sure the button does not get too big or too small, + // which changes depending upon the theme being used. + JPanel browsePanel = new JPanel() { + + @Override + public Dimension getPreferredSize() { + int width = getBestWidth(); + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = Math.min(width, preferredSize.width); + return preferredSize; + } + + @Override + public Dimension getMinimumSize() { + int width = getBestWidth(); + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = Math.min(width, preferredSize.width); + return preferredSize; + } + + @Override + public Dimension getMaximumSize() { + int width = getBestWidth(); + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = Math.min(width, preferredSize.width); + return preferredSize; + } + + private int getBestWidth() { + Font f = getFont(); + FontMetrics fm = getFontMetrics(f); + int width = fm.stringWidth(" . . . "); + return width; + } + }; + + browsePanel.setLayout(new BorderLayout()); + browsePanel.setOpaque(false); + + // Space the button so that it pops out visually. This was chosen by trial-and-error and + // looks reasonable on all themes. + Border empty = BorderFactory.createEmptyBorder(2, 2, 1, 1); + browsePanel.setBorder(empty); + + browseButton = new BrowseButton(); + browseButton.setToolTipText("Browse Existing Category Paths"); + browseButton.addActionListener(e -> showBrowser()); + browsePanel.add(browseButton); + + return browsePanel; + } + /** * Retrieve the value in the cell. * @return categoryPath of the selected value from the drop-down @@ -179,8 +233,8 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { } /** - * Retrieve the dropdown text field that holds the category path collection. - * @return CategoryPath dropdown selection text field object + * Retrieve the drop-down text field that holds the category path collection. + * @return CategoryPath drop-down selection text field object */ public DropDownSelectionTextField getDropDownTextField() { return selectionField; @@ -333,13 +387,6 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { private List data; - private Comparator searchComparator = new CategoryPathComparator(); - - /** - * Creates a new instance. - * - * @param dataTypeService {@link DataTypeManagerService} - */ public CategoryPathDropDownSelectionDataModel(DataTypeManagerService dataTypeService) { data = dataTypeService.getSortedCategoryPathList(); } @@ -349,66 +396,32 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { return new CategoryPathDropDownRenderer(); } - /** - * Description of the CategoryPath is the display text of the path as a string. - - * @param categoryPath CategoryPath - * @return String representation of the Category Path - */ @Override public String getDescription(CategoryPath categoryPath) { - return getDisplayText(categoryPath); + return null; } - /** - * Retrieve the CategoryPath string representation. - * - * @param categoryPath CategoryPath - * @return String representation of the Category Path - */ @Override public String getDisplayText(CategoryPath categoryPath) { return categoryPath.getPath(); } - /** - * Support for the filtering mechanism on the collection of Category Paths in the Data Manager. - * - * @param searchText String entered text - * @return filtered list of Category Paths - */ @Override public List getMatchingData(String searchText) { if (searchText == null || searchText.length() == 0) { return Collections.emptyList(); } - char END_CHAR = '\uffff'; - String searchTextStart = searchText; - String searchTextEnd = searchText + END_CHAR; - - int startIndex = Collections.binarySearch(data, searchTextStart, searchComparator); - int endIndex = Collections.binarySearch(data, searchTextEnd, searchComparator); - - // the binary search returns a negative, incremented position if there is no match in the - // list for the given search - if (startIndex < 0) { - startIndex = -startIndex - 1; + List results = new ArrayList<>(); + for (CategoryPath path : data) { + String pathString = path.getPath(); + if (pathString.contains(searchText)) { + results.add(path); + } } - - if (endIndex < 0) { - endIndex = -endIndex - 1; - } - - return data.subList(startIndex, endIndex); + return results; } - /** - * Identify index of first matching CategoryPath from entered text string. - * @param dataCollection list of Category Paths - * @param text search string - * @return int index of first match - */ @Override public int getIndexOfFirstMatchingEntry(List dataCollection, String text) { int lastPreferredMatchIndex = -1; @@ -434,18 +447,6 @@ public class CategoryPathSelectionEditor extends AbstractCellEditor { return -1; // we only get here when the list is empty } - private class CategoryPathComparator implements Comparator { - @Override - public int compare(Object o1, Object o2) { - if (o1 instanceof CategoryPath && o2 instanceof String) { - CategoryPath path = (CategoryPath) o1; - return path.getName().compareToIgnoreCase(((String) o2)); - } - throw new AssertException( - "CategoryPathCompartor used to compare files against a String key!"); - } - } - private class CategoryPathDropDownRenderer extends GListCellRenderer { @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/DataTypeSelectionEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/DataTypeSelectionEditor.java index e210d274c1..5dff65e417 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/DataTypeSelectionEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/DataTypeSelectionEditor.java @@ -15,9 +15,11 @@ */ package ghidra.app.util.datatype; +import java.awt.*; import java.awt.event.*; import javax.swing.*; +import javax.swing.border.Border; import javax.swing.event.*; import javax.swing.tree.TreePath; @@ -141,15 +143,13 @@ public class DataTypeSelectionEditor extends AbstractCellEditor { selectionField.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); - browseButton = new BrowseButton(); - browseButton.setToolTipText("Browse the Data Manager"); - browseButton.addActionListener(e -> showDataTypeBrowser()); + JPanel browsePanel = buildBrowsePanel(); editorPanel = new JPanel(); + editorPanel.setOpaque(false); editorPanel.setLayout(new BoxLayout(editorPanel, BoxLayout.X_AXIS)); editorPanel.add(selectionField); - editorPanel.add(Box.createHorizontalStrut(5)); - editorPanel.add(browseButton); + editorPanel.add(browsePanel); keyListener = new KeyAdapter() { @@ -171,6 +171,61 @@ public class DataTypeSelectionEditor extends AbstractCellEditor { }; } + private JPanel buildBrowsePanel() { + + // We override the various sizes to make sure the button does not get too big or too small, + // which changes depending upon the theme being used. + JPanel browsePanel = new JPanel() { + + @Override + public Dimension getPreferredSize() { + int width = getBestWidth(); + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = Math.min(width, preferredSize.width); + return preferredSize; + } + + @Override + public Dimension getMinimumSize() { + int width = getBestWidth(); + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = Math.min(width, preferredSize.width); + return preferredSize; + } + + @Override + public Dimension getMaximumSize() { + int width = getBestWidth(); + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = Math.min(width, preferredSize.width); + return preferredSize; + } + + private int getBestWidth() { + Font f = getFont(); + FontMetrics fm = getFontMetrics(f); + int width = fm.stringWidth(" . . . "); + return width; + } + }; + + browsePanel.setLayout(new BorderLayout()); + browsePanel.setOpaque(false); + + // Space the button so that it pops out visually. This was chosen by trial-and-error and + // looks reasonable on all themes. + Border empty = BorderFactory.createEmptyBorder(2, 2, 1, 1); + browsePanel.setBorder(empty); + + browseButton = new BrowseButton(); + browseButton.setToolTipText("Browse the Data Manager"); + browseButton.addActionListener(e -> showDataTypeBrowser()); + + browsePanel.add(browseButton); + + return browsePanel; + } + @Override public Object getCellEditorValue() { return selectionField.getSelectedValue(); diff --git a/Ghidra/Features/Base/src/main/java/help/screenshot/AbstractScreenShotGenerator.java b/Ghidra/Features/Base/src/main/java/help/screenshot/AbstractScreenShotGenerator.java index 82801196a6..6090e8304b 100644 --- a/Ghidra/Features/Base/src/main/java/help/screenshot/AbstractScreenShotGenerator.java +++ b/Ghidra/Features/Base/src/main/java/help/screenshot/AbstractScreenShotGenerator.java @@ -1001,7 +1001,10 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn public void selectRow(final JTable table, final int rowIndex) { waitForTable(table); - runSwing(() -> table.setRowSelectionInterval(rowIndex, rowIndex)); + runSwing(() -> { + table.setRowSelectionInterval(rowIndex, rowIndex); + table.requestFocus(); + }); waitForTable(table); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java index 9af89a2356..3f9e98234b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java @@ -974,7 +974,7 @@ public class DropDownTextField extends JTextField implements GComponent { fireUserChoiceMade(selectedItem); } - class PreviewListener implements ListSelectionListener { + private class PreviewListener implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/button/BrowseButton.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/button/BrowseButton.java index 7b5f424b85..7d58d000dc 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/button/BrowseButton.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/button/BrowseButton.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -55,5 +55,7 @@ public class BrowseButton extends JButton { setIcon(ICON); setName(NAME); setToolTipText(TOOLTIP_TEXT); + + getAccessibleContext().setAccessibleName("Browse"); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataPluginScreenShots.java index aa733c0e8c..ff012ae0e0 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataPluginScreenShots.java @@ -19,6 +19,9 @@ import java.util.Set; import java.util.stream.Collectors; import javax.swing.JRadioButton; +import javax.swing.JTable; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; import org.junit.Test; @@ -66,7 +69,21 @@ public class DataPluginScreenShots extends GhidraScreenShotGenerator { GhidraTable table = (GhidraTable) getInstanceField("matchingStructuresTable", dialog); selectRow(table, 2); - captureDialog(500, 400); + shrinkCategoryColumn(table); + + captureDialog(600, 500); + } + + private void shrinkCategoryColumn(JTable table) { + + runSwing(() -> { + TableColumnModel columnModel = table.getColumnModel(); + int columnIndex = columnModel.getColumnIndex("Category"); + TableColumn column = columnModel.getColumn(columnIndex); + int size = 150; + column.setPreferredWidth(size); + column.setMaxWidth(size); + }); } @Test