From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15697 invoked by alias); 5 Aug 2018 22:10:44 -0000 Mailing-List: contact cygwin-apps-help@cygwin.com; run by ezmlm Precedence: bulk Sender: cygwin-apps-owner@cygwin.com List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Mail-Followup-To: cygwin-apps@cygwin.com Received: (qmail 15603 invoked by uid 89); 5 Aug 2018 22:10:43 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY,KAM_SHORT,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=W, z, F, a9 X-HELO: rgout03.bt.lon5.cpcloud.co.uk Received: from rgout0301.bt.lon5.cpcloud.co.uk (HELO rgout03.bt.lon5.cpcloud.co.uk) (65.20.0.207) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 05 Aug 2018 22:10:39 +0000 X-OWM-Source-IP: 86.151.121.200 (GB) X-OWM-Env-Sender: jonturney@btinternet.com X-VadeSecure-score: verdict=clean score=0/300, class=clean X-SNCR-VADESECURE: CLEAN Received: from localhost.localdomain (86.151.121.200) by rgout03.bt.lon5.cpcloud.co.uk (9.0.019.26-1) (authenticated as jonturney@btinternet.com) id 5B4CE16C01FB5CEB; Sun, 5 Aug 2018 23:10:38 +0100 From: Jon Turney To: cygwin-apps@cygwin.com Cc: Jon Turney Subject: [PATCH setup 09/13] Use an icon to represent expanded/collapsed state Date: Sun, 05 Aug 2018 22:10:00 -0000 Message-Id: <20180805220851.270212-10-jon.turney@dronecode.org.uk> In-Reply-To: <20180805220851.270212-1-jon.turney@dronecode.org.uk> References: <20180805220851.270212-1-jon.turney@dronecode.org.uk> X-SW-Source: 2018-08/txt/msg00016.txt.bz2 Use a listview icon to represent expanded/collapsed state, rather than puttting '[+]'/'[-]' in front of the category name Just use the item icon directly to represent expanded/collapsed state, rather than using a state icon as otherwise we have empty space where the item icon would be, when it's size is being used for indenting. The icons were made by tracing the previously used .bmp in Inkscape to produce a .svg, then converting that to an icon with ImageMagick using 'convert -filter point -background transparent -define icon:auto-resize' --- ListView.cc | 18 ++++++- ListView.h | 3 ++ Makefile.am | 4 +- PickCategoryLine.cc | 8 ++- PickCategoryLine.h | 1 + PickPackageLine.h | 1 + res.rc | 2 + resource.h | 2 + tree-minus.ico | Bin 0 -> 299654 bytes tree-minus.svg | 118 +++++++++++++++++++++++++++++++++++++++++ tree-plus.ico | Bin 0 -> 299671 bytes tree-plus.svg | 126 ++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 280 insertions(+), 3 deletions(-) create mode 100644 tree-minus.ico create mode 100755 tree-minus.svg create mode 100644 tree-plus.ico create mode 100644 tree-plus.svg diff --git a/ListView.cc b/ListView.cc index a555caa..0c451d1 100644 --- a/ListView.cc +++ b/ListView.cc @@ -13,6 +13,7 @@ #include "ListView.h" #include "LogSingleton.h" +#include "resource.h" #include @@ -54,6 +55,15 @@ ListView::init(HWND parent, int id, HeaderList headers) // populate with columns initColumns(headers); + + // create a small icon imagelist and assign to listview control + // (the order of images matches ListViewLine::State enum) + HIMAGELIST hImgList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR32, 2, 0); + ImageList_AddIcon(hImgList, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_TREE_PLUS))); + ImageList_AddIcon(hImgList, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_TREE_MINUS))); + ListView_SetImageList(hWndListView, hImgList, LVSIL_SMALL); } void @@ -179,10 +189,11 @@ ListView::setContents(ListViewContents *_contents) for (i = 0; i < contents->size(); i++) { LVITEM lvi; - lvi.mask = LVIF_TEXT; + lvi.mask = LVIF_TEXT | LVIF_IMAGE; lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = LPSTR_TEXTCALLBACK; + lvi.iImage = I_IMAGECALLBACK; ListView_InsertItem(hWndListView, &lvi); } @@ -247,6 +258,11 @@ ListView::OnNotify (NMHDR *pNmHdr, LRESULT *pResult) static StringCache s; s = (*contents)[iRow]->get_text(iCol); pNmLvDispInfo->item.pszText = s; + + if (pNmLvDispInfo->item.iSubItem == 0) + { + pNmLvDispInfo->item.iImage = (int)((*contents)[pNmLvDispInfo->item.iItem]->get_state()); + } } return true; diff --git a/ListView.h b/ListView.h index b14777c..f5aa1d9 100644 --- a/ListView.h +++ b/ListView.h @@ -27,8 +27,11 @@ class ListViewLine { public: + enum class State { collapsed, expanded, nothing=-1 }; + virtual ~ListViewLine() {}; virtual const std::string get_text(int col) const = 0; + virtual State get_state() const = 0; virtual ActionList *get_actions(int col) const = 0; virtual int do_action(int col, int id) = 0; }; diff --git a/Makefile.am b/Makefile.am index b58c9b7..7c1f993 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,7 +46,9 @@ EXTRA_DIST = \ cygwin-setup.ico \ cygwin-terminal.ico \ setup.exe.manifest \ - setup64.exe.manifest + setup64.exe.manifest \ + tree-minus.ico \ + tree-plus.ico # iniparse.hh is generated from iniparse.yy via bison -d, so it needs to be # included here for proper tracking (but not iniparse.cc, since automake diff --git a/PickCategoryLine.cc b/PickCategoryLine.cc index 736e3c6..21795b2 100644 --- a/PickCategoryLine.cc +++ b/PickCategoryLine.cc @@ -26,7 +26,7 @@ PickCategoryLine::get_text (int col_num) const if (col_num == pkgname_col) { std::ostringstream s; - s << (cat_tree->collapsed() ? "[+] " : "[-] ") << cat_tree->category().first; + s << cat_tree->category().first; if (pkgcount) s << " (" << pkgcount << ")"; return s.str(); @@ -70,3 +70,9 @@ PickCategoryLine::get_actions(int col) const return al; } + +ListViewLine::State +PickCategoryLine::get_state() const +{ + return cat_tree->collapsed() ? State::collapsed : State::expanded; +} diff --git a/PickCategoryLine.h b/PickCategoryLine.h index ec160f9..6b54c3f 100644 --- a/PickCategoryLine.h +++ b/PickCategoryLine.h @@ -34,6 +34,7 @@ public: } const std::string get_text(int col) const; + State get_state() const; ActionList *get_actions(int col) const; int do_action(int col, int action_id); diff --git a/PickPackageLine.h b/PickPackageLine.h index 7d96d44..dacad28 100644 --- a/PickPackageLine.h +++ b/PickPackageLine.h @@ -30,6 +30,7 @@ public: { }; const std::string get_text(int col) const; + State get_state() const { return State::nothing; } ActionList *get_actions(int col_num) const; int do_action(int col, int action_id); private: diff --git a/res.rc b/res.rc index 27f0378..10f20ba 100644 --- a/res.rc +++ b/res.rc @@ -519,6 +519,8 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "setup.exe.manifest" IDI_CYGWIN_SETUP ICON DISCARDABLE "cygwin-setup.ico" IDI_CYGWIN ICON DISCARDABLE "cygwin.ico" IDI_CYGWIN_TERMINAL ICON DISCARDABLE "cygwin-terminal.ico" +IDI_TREE_PLUS ICON DISCARDABLE "tree-plus.ico" +IDI_TREE_MINUS ICON DISCARDABLE "tree-minus.ico" ///////////////////////////////////////////////////////////////////////////// // diff --git a/resource.h b/resource.h index 2f1036b..852bdc0 100644 --- a/resource.h +++ b/resource.h @@ -76,6 +76,8 @@ #define IDI_CYGWIN_SETUP 401 #define IDI_CYGWIN 402 #define IDI_CYGWIN_TERMINAL 403 +#define IDI_TREE_PLUS 404 +#define IDI_TREE_MINUS 405 // controls diff --git a/tree-minus.ico b/tree-minus.ico new file mode 100644 index 0000000000000000000000000000000000000000..46fd3b117b0fcaffc9c12331e4ccdd1fed9f61e1 GIT binary patch literal 299654 zcmeI*PlzQ~702=0Gp#0p`2#L8hLH3kV&iH+P*<5wjA#~y5VCO*Y&SZf3qxE8f;Le? zbRjN8M50R(1eg9HinuCAJUYfk^F>h!Jmtyo>J z?w@n-{oGTpU%JOh2pi#!5RZ+p6)v0#;TP5G{r%Pb_G72Q3su?P-ogEC8{xIbPlesx z)%`Dj6vEjjPKTYHgZc+U_|2QA!^MjS^&bx5Zy(zX+uN)A%XfwF%;z`5*49D&`4HZC zYBOB8u)2Tt_7Hyj-OX^mDv$HIycxnhKiCZ4d-RddoVnw!IMFi?fA*orVr@KctLnqs z-`st@y1DxBLk~RujlaD9*FT(j>EikDz<2)j;y)gJ`rhs5zWC*j{%-qM|9koSf2vlJ zJ?{VSPwv@$;*Y2Ae&e-Iy!G6-?*G#5TaSb%Pd)p=o#(>eH_v}$?~@xZA1%86(|dNm z^4`lYJ^#$BpZasY=}mfTML+xY7xrJdws`xuXJ7o!{`)hNJQ(JU>#v@^`@QGi{rbm~ z%h4uul;$wjKd;{Twa=ZqcJ-@Wzr#i=<<$1P@b5GC{r-L1Pd$D4=dsDdpMK<_Uq86} zbd^?NzdHA-bcp$~Ja$fnD`&&%8Ew* zlmBI9?69*X|H=PhGpej;lrHTk@a$A2y@PibnpE|7B(Du(Kuq$^T(9s;p?_ zKlxu)#tu7MYyJ;AI??d=%>n%J_Z9FRo&3k&SHO34@*jU+0pHQdfBby~d`Bn$@%I(* z9i9Bg-&eqQbn+j6Ujg6I$$$KP1$;**|MB+~@Ex7}$KO}LcXaX}e_sLL(aC@OeFc0+ zC;##H74RLM{Kwx{z;|@=AAer~-_gl`{Cx#{M<@UB_Z9FRo&3k&SHO34@*jU+0pHQd zfBby~d`Bn$@%I(*9i9Bg-&eqQbn+j6Ujg6I$$$KP1$;**|MB+~@Ex7}$KO}LcXaX} ze_sLL(aC@OeFc0+C;##H74RLM{Kwx{z;|@=AAer~-_gl`{Cx#{M<@UB_Z9FRo&3k& zSHO34@*jU+0pHQb&VOtC(%V~i)4E=3eA?#)#`d?yFTH(UyIX5rZ#M!Zion?Z*7&8j zx9){?z1H}&&kKz0Z;fAi`@D9y*1Fzq1WFWvvHh*_OK)%83+sBV@oAqI7~9_(zx4Kb z?QX4gz1;|uC<0^qTjQ7B-ntjo^;+Z8J})q~zcqg8?ep5*TI+hd5hzgv#`d?yFTK5W zFRbge#;1K=U~GSD{L!mrq6m!bZ;fAid+T0U*K3VW`@F!|{?_=Vx6f;L zYpv_;MxaCyz+chR`{J(~DiQEk^z^>?>xN1M{1rXDFaElr5&?fjPw$JrZm2}SU(wV1 z;;$Pj5%5>^^uGA(hDrqd6+OK#{<@(O0e?kL?~A`~s6@bD(bN0luNx{6@K^NozWD2g zN(B5BJ-sjfx}g#Qe??F4i@$EDM8IFs)BEDD8!8d-SM>D0`0IvB1pE~}y)XW{p%MXq zMNjXGziy~Rz+chR`{J(~DiQEk^z^>?>xN1M{1rXDFaElr5&?fjPw$JrZm2}SU(wV1 z;;$Pj5%5>^^uGA(hDrqd6+OK#{<@(O0e?kL?~A`~s6@bD(bN0luNx{6@K^NozWD2g zN(B5BJ-sjfx}g#Qe??F4i@$EDM8IFs)BEDD8!8d-SM>D0`0IvB1pE~}y)XW{p%MXq zMNjXGziy~Rz+chR`{J(~DiQEk^z^>?>xN1M{1rXDFaElr5&?fjPw$JrZm2}C`qMrH zPXlGI>Dv|X+)Ku`KTF*mq(l)Q2kklNX{PKoeY*mld&$`LXRo`1lqdq^pgjjY&6K^S zZ&$!`FB#kZ>~(jL5=DR;O% zWNiDh*WE!%6ajM3o`ard%3jmAE8w}8jBS7Rx;sb-0tg_000IagfB*srAb*ee zYQ>p0xFy7b8?pE4y^l6?KiGfvpBzZ%0MCEgW*zc|{b&E@oCE9d3@dA#^WMj`DK_iS zcis1&_0LiggSSpU2Q$p8E^Fz?;ZuRZ3*+z;|Up9AdwyamXA@;{dY^UnVK z-t+x$?z_+a=bnA?pZuS@0QsMP4`l!6EkOR0|G6BPclPJ^p3gsX-+lH!_w1AZx&*i|pvp>K0eEymH?z8{7XP^8h|K~11{^#EV+5dS9kpEi#_xX9( z_hoP2{QCNrUazjdufKPF-~RN?udjdU_3HZj`g_;+?N8tQ`udk%udctZzjuA#{`AeS zuYc+F>iYZod)N2vPv89d`j=j>uD`FpcYWXf^v$oYf9dt=`uqBO*Z1vD-~9UemtL=~ zzpuY{ec%4{&9AS2>GiB%`}qg^U$y}GPyXj}pzQ4KpM7rav2N}M>*x8;=`^A^bMeXN`N!TNds%jE$1KW~BD-t+!9@4b(!WB>C8bI$G9eB_0EyG??3B9009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0-A?FAMb z?gBTG@L(pB-`C@ET?&NB9hN)3I2?EC`_+OE$LBr@Oy*HP@GJKC_Z6*D0`0IvB1pE~}y)XW{p%MXqMNjXGziy~Rz+chR`&#`|?Z+-p ztu!@ms{KhTx6VJ+e(ds;TWZ`?`;%5~oqwwR*ySm=)VQhkC#~E%|5W?2%TsQtaZ~M2 zTDf)psrF-+r`%HGrrMvha_jt4?Z+-pxuwQUwLfX)%-?rM@W)>fAb%7+y)XW{p%MXq zMNjXGziy~Rz+chR`{J(~DiQEk^z^>?>xN1M{1rXDFaElr5&?fjPw$JrZm2}SU(wV1 z;;$Pj5%5>^^uBZTPpzwza(!o~iBO8Cb)M7c>7!WJRZ4qZW||14cv|NQE@p3~?t3IYfqfB*srAbK(uz|7H%5e@6wHHbcBV8vSVQ#rRVn?KQQ>Z`Z5$eev7%W8b&e(;lx~uip2? zZ`Y4~-(F99ymq~M-xt4KKlXilJ!6m8j?ef<-viq|W8dSCe=`Th&bM~_=GgJ|)Cc2} z|IHjA|E3ja+VlKRYad6$|ER&#J8;tc+w+smdYy{jEVsUH&aK(ESw7V3RQzVS^>uS@&A!d@pb5P>ub%U*UYo0~`!vgx*Efq-m)+{MIey)zS*E-uo}yR%t8&#nov_&HzsumAb|bAx8>jA9&#S)11%_j+Gtn>pj%lkpcdGNo@0rf?d!~wm0|ARb{drftTE=X)RmZLS zH)C2}(_j1f41V+StM{|-T0diTyZYXGZTGM5`>ypkb-ViBdZquo@|XR$3Do(oUTvcu zwpPcj`yWQ+6#@t#Pzfx5u5z<4AzZ57I4&(x|6DwMX%WxVKXw0`#cq_vpHp0@&WqJ~ zm>W+a;RR_NuGZ_$J~|q=XC7$t8`=AYVwTbX~o-qbY}d+o~OFRAPE+6O|oe*N%#>(0a1u{_q- IZR_j*0p@PTA^-pY literal 0 HcmV?d00001 diff --git a/tree-minus.svg b/tree-minus.svg new file mode 100755 index 0000000..124918b --- /dev/null +++ b/tree-minus.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/tree-plus.ico b/tree-plus.ico new file mode 100644 index 0000000000000000000000000000000000000000..8ee3d5fed295f1b79639845c67a86c5145cfa5c8 GIT binary patch literal 299671 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 literal 0 HcmV?d00001 diff --git a/tree-plus.svg b/tree-plus.svg new file mode 100644 index 0000000..4d2eb3f --- /dev/null +++ b/tree-plus.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + -- 2.17.0