From 7306483079118bd7a707fab9dc9fc148b78c0b30 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Fri, 6 Sep 2024 12:09:05 -0300 Subject: [PATCH 01/14] Update Example --- .../ricaun.Revit.UI.Example.csproj | 14 ++++++++++++-- ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj b/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj index cb6fb12..17d6cdb 100644 --- a/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj +++ b/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj @@ -13,10 +13,20 @@ - net48;net8.0-windows + net46;net47;net48;net8.0-windows - + + + 2017 + + + + + 2019 + + + 2021 diff --git a/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj b/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj index 107558b..d309f72 100644 --- a/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj +++ b/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj @@ -41,7 +41,7 @@ - + From e3c49bc0081b3d9459aa1bf19c6ad79a73160af4 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Mon, 11 Nov 2024 16:01:28 -0300 Subject: [PATCH 02/14] Support `tiff` files for icon. --- CHANGELOG.md | 9 +++++ Directory.Build.props | 2 +- .../Resources/Cube-Grey-Dark.tiff | Bin 0 -> 4826 bytes .../Resources/Cube-Grey-Light.tiff | Bin 0 -> 5310 bytes ricaun.Revit.UI.Example/Revit/AppTheme.cs | 31 ++++++++++++++++++ .../ricaun.Revit.UI.Example.csproj | 4 +++ ricaun.Revit.UI/BitmapExtension.cs | 7 ++-- 7 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 ricaun.Revit.UI.Example/Resources/Cube-Grey-Dark.tiff create mode 100644 ricaun.Revit.UI.Example/Resources/Cube-Grey-Light.tiff diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d4046d..29cfb22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.7.1] / 2024-11-11 +### Features +- Support `tiff` files for icon. +### Updated +- Update `GetBitmapFrame` to round `width` that is changed by `dpi`. +### Example +- Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. + ## [0.7.0] / 2024-07-06 - 2024-07-25 ### Features - Auto set image based on the theme of the Ribbon using `light` and `dark` image pattern. @@ -360,6 +368,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - First Release [vNext]: ../../compare/1.0.0...HEAD +[0.7.1]: ../../compare/0.7.0...0.7.1 [0.7.0]: ../../compare/0.6.2...0.7.0 [0.6.2]: ../../compare/0.6.1...0.6.2 [0.6.1]: ../../compare/0.6.0...0.6.1 diff --git a/Directory.Build.props b/Directory.Build.props index 5596472..b243076 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.0 + 0.7.1-alpha \ No newline at end of file diff --git a/ricaun.Revit.UI.Example/Resources/Cube-Grey-Dark.tiff b/ricaun.Revit.UI.Example/Resources/Cube-Grey-Dark.tiff new file mode 100644 index 0000000000000000000000000000000000000000..12bc09f33c8ae79ac6bee5668be4c90111dabbdd GIT binary patch literal 4826 zcma)930M=?8l6B;q#$5%MI|V8!?M&BX-KqC6k8FfpHHYnD}|?sNO`in6b7}33pI+= z1%=ouE?7+wDTEkeRW_FdtdIgB5vjz5Btjr#NHX``p-koViwb;q?#azR|J*s}Klk3O zSTP6Lh9F4FDb)klF&Q+6PdBc5yyoM@oA*&|HoB(R+#FG@uX^m|um*n(mSqYz{k477xph_{Aq#2~hS*l{qP7#}-0 zPTVtYNS^V7I2w*mqF4>&@q)>m2k~NvClB6BJY&|7{GmheQ~0Iz;J-GBf;_cE5VD87 zHF?|IqB&J}fBAE4aD8I#wtU~-(ZT~Z0jJiFaa`*E%grF{kZjO!in+;WY*4KWO8^ zgB@vH26d0URlsqsdFCg;w%>7k3r#{mpSlBVOy!9Yr0eVX}uhNW5VUJNPd>TQfdja(z$z&Wx4Rvl+Xml^MUHW}o-~dHGz( z@-zs-FXewL@oBBY^1)tgJ-C2P0kv2o+H1JOYFC>s$>?aIp^K&R)2_YF!PjV}qfZRA zqS9!`6t(fMDo1g%K&n3$styB+(=E(r+gyYRIYB^W3Xbbp3(1P||=~eJA8Iv_O;E1mQ^oos=@)Ep6oel2!wlWOj zUQvQ)p>b3TvUk+P9P z&o&Ltnq-^6B-=;fR{E}WYc*uT9NR=5(l6N%lWZ5joFv=lARZ3e1*2ZGP42Q}583_0 z*Jd}IG#EA75#Rpp<@qPT{W=X{(u`K_0R)Lv^^rQ?g{t_+hd$n?1T(W~|>m-K&J#^G)& zYV$nDm^SCF(zR-^8C9aFV~<%SD__Pp^9@+nDU(OimGrf~fg(=+NrhBg$II>cHF)!7 zmn6()eTY*sOVBl|-(nKwS)_Rd-?ZZW%jVq*UV$o@Q*h{t_i~7W8(>aS!GA+M90j+$ z_gX=6wYQyPn-zvN9NKj1l-cS8yUzGYO z%WMIUy$3uM|RXBHR(nIlWuggeY=*#x;7WayiH3YW~Gdzn* z@u1mY_vz)?A?2t>?lV&+N(Q$Xm=tRQvNFwwfG-l2^(!ki^2b~Q&Q_u78ubFecM(bZ zmFeop4z59OXhhXg^;(?I5^+t+NM(8_mn}3jpz0l(K%6fXX-rCaXQh(M78nGmI!+S- zWUY!aJS=E|a&GOIWnTPvlQz9au9Yx=k+^V;$Kpm#-!UVMcnNR28%$g3FE7tKjo9cg zU;5*JpOvj@`}laqk%z^C_675vsaY~5ZZcpR1)MkD4LcMJetru88t~9^(kJilB_82p zW9e6q~a&XH?*7y}N9K^Gmo0PdKPXX44V z48Ti}0GX(X4mv;{X5^S+6m{&hV& zK}^>3WQd1T&wn_+uIJC72ORAX);wx(B-W)j|IV0r8;Sd-XuR9%YQLDhX& z5vr!E#{!u_wiYC6cChpkp(3r3ffZoHpgaZ+rg7mQNNZwXboD%(uSrDvxrRt=Cg5w5 z0pN67tnRR`BPJDM2NzO=d8YLMEqgLGWfEnzGDW~yx!p10-g6`_E%)2zblTb{J0 z9Wr%lP{nv%IM(mNGtmC!nv54293Qs|bs`nbE9opVL>Qs~}ddA1RqR0f3 zjx=1d`FtJRcsvt-IF@qQpNPrhA-mjkl2KfaDKWpVO?!2O4;jj~I2=XNEqsEUnu;1M#di&pWx0HhG!s_BQ`Vu%TEdE?Mq z7=YeVU`Yu`<~rzbjFCvNi0dA0xKBe!Ocd6@=T z+P=LBe%Eh)u0qeV@mL^e)3VNY&=KU-&aD~(n76wV9(a*F z7-PRKcbhv9lkR)~@o?M;Q~Z6>c7u-Q!{+CJAm78*3EL0Qy+6R1OxS{9 QTL&8twohOqPvB(#KXDA6+5i9m literal 0 HcmV?d00001 diff --git a/ricaun.Revit.UI.Example/Resources/Cube-Grey-Light.tiff b/ricaun.Revit.UI.Example/Resources/Cube-Grey-Light.tiff new file mode 100644 index 0000000000000000000000000000000000000000..c99ad07e0e8aeb12814a2f037c07a92e64a1ac0a GIT binary patch literal 5310 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 literal 0 HcmV?d00001 diff --git a/ricaun.Revit.UI.Example/Revit/AppTheme.cs b/ricaun.Revit.UI.Example/Revit/AppTheme.cs index e1aeb80..d8aa158 100644 --- a/ricaun.Revit.UI.Example/Revit/AppTheme.cs +++ b/ricaun.Revit.UI.Example/Revit/AppTheme.cs @@ -61,6 +61,37 @@ public Result OnStartup(UIControlledApplication application) ribbonPanel.AddSeparator(); + + { + var buttonTiff = ribbonPanel.CreatePushButton("Grey") + .SetLargeImage("Resources/Cube-Grey-Light.tiff"); + //if (buttonTiff.LargeImage is System.Windows.Media.Imaging.BitmapSource largeImage) + //{ + // System.Console.WriteLine($"{largeImage.GetType().Name} | {largeImage.Width:0}x{largeImage.Height:0} ({largeImage.PixelWidth}x{largeImage.PixelHeight}) {largeImage.DpiX:0}:{largeImage.DpiY:0}"); + //} + //if (buttonTiff.Image is System.Windows.Media.Imaging.BitmapSource smallImage) + //{ + // System.Console.WriteLine($"{smallImage.GetType().Name} | {smallImage.Width:0}x{smallImage.Height:0} ({smallImage.PixelWidth}x{smallImage.PixelHeight}) {smallImage.DpiX:0}:{smallImage.DpiY:0}"); + //} + } + + ribbonPanel.RowStackedItems( + ribbonPanel.CreatePushButton("Grey") + .SetLargeImage("Resources/Cube-Grey-Light.tiff"), + ribbonPanel.CreatePushButton("Grey") + .SetLargeImage("Resources/Cube-Grey-Light.tiff"), + ribbonPanel.CreatePushButton("Grey") + .SetLargeImage("Resources/Cube-Grey-Light.tiff") + ); + ribbonPanel.RowLargeStackedItems( + ribbonPanel.CreatePushButton("Grey") + .SetLargeImage("Resources/Cube-Grey-Light.tiff"), + ribbonPanel.CreatePushButton("Grey") + .SetLargeImage("Resources/Cube-Grey-Light.tiff") + ); + + ribbonPanel.AddSeparator(); + ribbonPanel.FlowStackedItems( ribbonPanel.CreatePushButton("1").SetLargeImage(LIGHT_RED), ribbonPanel.CreatePushButton("2").SetLargeImage(DARK_RED), diff --git a/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj b/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj index 17d6cdb..855d528 100644 --- a/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj +++ b/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj @@ -96,6 +96,8 @@ + + @@ -126,6 +128,8 @@ + + diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index 78f1f69..59c7515 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -97,8 +97,9 @@ TImageSource ScaleDownIfWidthIsGreater(TImageSource imageSource, int width) if (width <= 0) return imageSource; - if (imageSource.Width > width) - imageSource = imageSource.Scale(width / imageSource.Width) as TImageSource; + var imageRoundWidth = Math.Round(imageSource.Width); + if (imageRoundWidth > width) + imageSource = imageSource.Scale(width / imageRoundWidth) as TImageSource; return imageSource; } @@ -110,7 +111,7 @@ BitmapFrame GetBitmapFrameByWidth(BitmapFrame bitmapFrame, int width) var frames = bitmapFrame.Decoder.Frames; var frame = frames .OrderBy(e => e.Width) - .FirstOrDefault(e => e.Width >= width); + .FirstOrDefault(e => Math.Round(e.Width) >= width); return frame; } From 188399d26fb37c31364384aaa5f36d1e1b218b2e Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Mon, 11 Nov 2024 18:12:23 -0300 Subject: [PATCH 03/14] Add `GetBitmapFrameByDpiAndWidth` to get optimal frame by `dpi` and `width` --- CHANGELOG.md | 1 + ricaun.Revit.UI/BitmapExtension.cs | 38 ++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29cfb22..0379056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Support `tiff` files for icon. ### Updated - Update `GetBitmapFrame` to round `width` that is changed by `dpi`. +- Add `GetBitmapFrameByDpiAndWidth` to get optimal frame by `dpi` and `width`. ### Example - Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index 59c7515..d604e6f 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -82,6 +82,30 @@ public static ImageSource Scale(this ImageSource imageSource, double scale) return imageSource; } + /// + /// + /// + /// + /// + /// + internal static BitmapFrame GetBitmapFrameByDpiAndWidth(this BitmapDecoder bitmapDecoder, int width = 0) + { + double systemDpi = 96; + +#if NET47_OR_GREATER || NET + var imageScaleInfo = VisualTreeHelper.GetDpi(new System.Windows.Controls.Image()); + systemDpi = imageScaleInfo.PixelsPerInchX; +#endif + + var frames = bitmapDecoder.Frames; + var frame = frames + .OrderBy(e => e.DpiX >= systemDpi ? -systemDpi / e.DpiX : systemDpi / e.DpiX) + .ThenBy(e => e.Width) + .FirstOrDefault(e => Math.Round(e.Width) >= width); + + return frame; + } + /// /// GetBitmapFrame with Width Equal or Scale /// @@ -106,21 +130,11 @@ TImageSource ScaleDownIfWidthIsGreater(TImageSource imageSource, int width) if (imageSource is BitmapFrame bitmapFrame) { - BitmapFrame GetBitmapFrameByWidth(BitmapFrame bitmapFrame, int width) - { - var frames = bitmapFrame.Decoder.Frames; - var frame = frames - .OrderBy(e => e.Width) - .FirstOrDefault(e => Math.Round(e.Width) >= width); - - return frame; - } - if (bitmapFrame.IsDownloading) { bitmapFrame.DownloadCompleted += (s, e) => { - if (GetBitmapFrameByWidth(bitmapFrame, width) is TImageSource frame) + if (bitmapFrame.Decoder.GetBitmapFrameByDpiAndWidth(width) is TImageSource frame) imageSource = frame; imageSource = ScaleDownIfWidthIsGreater(imageSource, width); @@ -129,7 +143,7 @@ BitmapFrame GetBitmapFrameByWidth(BitmapFrame bitmapFrame, int width) }; } - if (GetBitmapFrameByWidth(bitmapFrame, width) is TImageSource frame) + if (bitmapFrame.Decoder.GetBitmapFrameByDpiAndWidth(width) is TImageSource frame) imageSource = frame; } From c665598e6fa2269c804c23500cf6aa9d70834fee Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Mon, 11 Nov 2024 18:14:13 -0300 Subject: [PATCH 04/14] Update doc --- ricaun.Revit.UI/BitmapExtension.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index d604e6f..d85500f 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -83,11 +83,11 @@ public static ImageSource Scale(this ImageSource imageSource, double scale) } /// - /// + /// Get the bitmap frame from the based on the DPI and width. /// - /// - /// - /// + /// The bitmap decoder. + /// The desired width of the bitmap frame. When set to zero, the smallest width frame is returned. + /// The bitmap frame with the specified width or the smallest width frame. internal static BitmapFrame GetBitmapFrameByDpiAndWidth(this BitmapDecoder bitmapDecoder, int width = 0) { double systemDpi = 96; @@ -109,11 +109,11 @@ internal static BitmapFrame GetBitmapFrameByDpiAndWidth(this BitmapDecoder bitma /// /// GetBitmapFrame with Width Equal or Scale /// - /// - /// - /// - /// - /// When is zero, return the smallest width frame. + /// The image source. + /// The desired width of the bitmap frame. When set to zero, the smallest width frame is returned. + /// An optional action to be executed when the download of the bitmap frame is completed. + /// The bitmap frame with the specified width or the scaled bitmap frame. + /// When is zero, the smallest width frame is returned. public static TImageSource GetBitmapFrame(this TImageSource imageSource, int width = 0, Action downloadCompleted = null) where TImageSource : ImageSource { TImageSource ScaleDownIfWidthIsGreater(TImageSource imageSource, int width) From 45a6d3512448e86b32e9b20e7bc218467956e959 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Mon, 11 Nov 2024 18:22:03 -0300 Subject: [PATCH 05/14] Add `GetSystemDpi` --- CHANGELOG.md | 3 ++- ricaun.Revit.UI/BitmapExtension.cs | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0379056..fee80a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Support `tiff` files for icon. ### Updated - Update `GetBitmapFrame` to round `width` that is changed by `dpi`. -- Add `GetBitmapFrameByDpiAndWidth` to get optimal frame by `dpi` and `width`. +- Add `GetBitmapFrameByWidthAndDpi` to get optimal frame by `dpi` and `width`. +- Add `GetSystemDpi` to get the system `dpi` on the fly. ### Example - Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index d85500f..55f5656 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -83,19 +83,28 @@ public static ImageSource Scale(this ImageSource imageSource, double scale) } /// - /// Get the bitmap frame from the based on the DPI and width. + /// Get the system DPI based on the using a new . /// - /// The bitmap decoder. - /// The desired width of the bitmap frame. When set to zero, the smallest width frame is returned. - /// The bitmap frame with the specified width or the smallest width frame. - internal static BitmapFrame GetBitmapFrameByDpiAndWidth(this BitmapDecoder bitmapDecoder, int width = 0) + internal static double GetSystemDpi() { double systemDpi = 96; - #if NET47_OR_GREATER || NET var imageScaleInfo = VisualTreeHelper.GetDpi(new System.Windows.Controls.Image()); systemDpi = imageScaleInfo.PixelsPerInchX; #endif + return systemDpi; + } + + /// + /// Get the bitmap frame from the based on the DPI and width. + /// + /// The bitmap decoder. + /// The desired width of the bitmap frame. When set to zero, the smallest width frame is returned. + /// The optimal dpi for the frame. + /// The bitmap frame with the specified width or the smallest width frame. + internal static BitmapFrame GetBitmapFrameByWidthAndDpi(this BitmapDecoder bitmapDecoder, int width = 0, int dpi = 0) + { + double systemDpi = dpi > 0 ? dpi : GetSystemDpi(); var frames = bitmapDecoder.Frames; var frame = frames @@ -134,7 +143,7 @@ TImageSource ScaleDownIfWidthIsGreater(TImageSource imageSource, int width) { bitmapFrame.DownloadCompleted += (s, e) => { - if (bitmapFrame.Decoder.GetBitmapFrameByDpiAndWidth(width) is TImageSource frame) + if (bitmapFrame.Decoder.GetBitmapFrameByWidthAndDpi(width) is TImageSource frame) imageSource = frame; imageSource = ScaleDownIfWidthIsGreater(imageSource, width); @@ -143,7 +152,7 @@ TImageSource ScaleDownIfWidthIsGreater(TImageSource imageSource, int width) }; } - if (bitmapFrame.Decoder.GetBitmapFrameByDpiAndWidth(width) is TImageSource frame) + if (bitmapFrame.Decoder.GetBitmapFrameByWidthAndDpi(width) is TImageSource frame) imageSource = frame; } From 03e548126d742882fd9600998eb9a1fb2a20ea9c Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Mon, 11 Nov 2024 18:22:16 -0300 Subject: [PATCH 06/14] Version alpha.1 --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index b243076..3c1a252 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-alpha + 0.7.1-alpha.1 \ No newline at end of file From 585d09bc10b959efbcdac0acf8d257ea89729db8 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Sat, 16 Nov 2024 19:57:59 -0300 Subject: [PATCH 07/14] Update `GetBitmapFrameByWidthAndDpi` to round `dpi` frame value. --- CHANGELOG.md | 2 ++ Directory.Build.props | 2 +- ricaun.Revit.UI.Example/Revit/AppTheme.cs | 16 +++++++-------- ricaun.Revit.UI/BitmapExtension.cs | 24 +++++++++++++++++++---- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fee80a8..b31d3fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Update `GetBitmapFrame` to round `width` that is changed by `dpi`. - Add `GetBitmapFrameByWidthAndDpi` to get optimal frame by `dpi` and `width`. - Add `GetSystemDpi` to get the system `dpi` on the fly. +- Add `SystemDpi` to store the system `dpi` value. +- Update `GetBitmapFrameByWidthAndDpi` to round `dpi` frame value. ### Example - Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. diff --git a/Directory.Build.props b/Directory.Build.props index 3c1a252..55a80d0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-alpha.1 + 0.7.1-alpha.2 \ No newline at end of file diff --git a/ricaun.Revit.UI.Example/Revit/AppTheme.cs b/ricaun.Revit.UI.Example/Revit/AppTheme.cs index d8aa158..7a4a9a1 100644 --- a/ricaun.Revit.UI.Example/Revit/AppTheme.cs +++ b/ricaun.Revit.UI.Example/Revit/AppTheme.cs @@ -65,14 +65,14 @@ public Result OnStartup(UIControlledApplication application) { var buttonTiff = ribbonPanel.CreatePushButton("Grey") .SetLargeImage("Resources/Cube-Grey-Light.tiff"); - //if (buttonTiff.LargeImage is System.Windows.Media.Imaging.BitmapSource largeImage) - //{ - // System.Console.WriteLine($"{largeImage.GetType().Name} | {largeImage.Width:0}x{largeImage.Height:0} ({largeImage.PixelWidth}x{largeImage.PixelHeight}) {largeImage.DpiX:0}:{largeImage.DpiY:0}"); - //} - //if (buttonTiff.Image is System.Windows.Media.Imaging.BitmapSource smallImage) - //{ - // System.Console.WriteLine($"{smallImage.GetType().Name} | {smallImage.Width:0}x{smallImage.Height:0} ({smallImage.PixelWidth}x{smallImage.PixelHeight}) {smallImage.DpiX:0}:{smallImage.DpiY:0}"); - //} + if (buttonTiff.LargeImage is System.Windows.Media.Imaging.BitmapSource largeImage) + { + System.Console.WriteLine($"{largeImage.GetType().Name} | {largeImage.Width:0}x{largeImage.Height:0} ({largeImage.PixelWidth}x{largeImage.PixelHeight}) {largeImage.DpiX:0}:{largeImage.DpiY:0}"); + } + if (buttonTiff.Image is System.Windows.Media.Imaging.BitmapSource smallImage) + { + System.Console.WriteLine($"{smallImage.GetType().Name} | {smallImage.Width:0}x{smallImage.Height:0} ({smallImage.PixelWidth}x{smallImage.PixelHeight}) {smallImage.DpiX:0}:{smallImage.DpiY:0}"); + } } ribbonPanel.RowStackedItems( diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index 55f5656..0cf2976 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -88,12 +88,22 @@ public static ImageSource Scale(this ImageSource imageSource, double scale) internal static double GetSystemDpi() { double systemDpi = 96; + try + { #if NET47_OR_GREATER || NET - var imageScaleInfo = VisualTreeHelper.GetDpi(new System.Windows.Controls.Image()); - systemDpi = imageScaleInfo.PixelsPerInchX; + var imageScaleInfo = VisualTreeHelper.GetDpi(new System.Windows.Controls.Image()); + systemDpi = imageScaleInfo.PixelsPerInchX; +#else + using (var g = System.Drawing.Graphics.FromHwnd(IntPtr.Zero)) + { + systemDpi = g.DpiX; + } #endif + } + catch { } return systemDpi; } + internal readonly static double SystemDpi = GetSystemDpi(); /// /// Get the bitmap frame from the based on the DPI and width. @@ -104,11 +114,17 @@ internal static double GetSystemDpi() /// The bitmap frame with the specified width or the smallest width frame. internal static BitmapFrame GetBitmapFrameByWidthAndDpi(this BitmapDecoder bitmapDecoder, int width = 0, int dpi = 0) { - double systemDpi = dpi > 0 ? dpi : GetSystemDpi(); + double systemDpi = dpi > 0 ? dpi : SystemDpi; + + double OrderDpiX(BitmapFrame frame) + { + var dpiX = Math.Round(frame.DpiX); + return dpiX >= systemDpi ? -systemDpi / dpiX : systemDpi / dpiX; + } var frames = bitmapDecoder.Frames; var frame = frames - .OrderBy(e => e.DpiX >= systemDpi ? -systemDpi / e.DpiX : systemDpi / e.DpiX) + .OrderBy(OrderDpiX) .ThenBy(e => e.Width) .FirstOrDefault(e => Math.Round(e.Width) >= width); From 71ceab26ccdcc213501e423779a037407c8e0bf0 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 00:02:52 -0300 Subject: [PATCH 08/14] Add `ResourceTiffTests` with `Cube.tiff` with multiple dpi and scales --- CHANGELOG.md | 3 + Directory.Build.props | 2 +- .../Resources/Images/Cube.tiff | Bin 0 -> 5310 bytes ...amesTests.cs => ResourceIcoFramesTests.cs} | 2 +- .../Resources/ResourceTiffTests.cs | 85 ++++++++++++++++++ .../ricaun.Revit.UI.Tests.csproj | 7 +- ricaun.Revit.UI/BitmapExtension.cs | 10 ++- 7 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 ricaun.Revit.UI.Tests/Resources/Images/Cube.tiff rename ricaun.Revit.UI.Tests/Resources/{ResourcesFramesTests.cs => ResourceIcoFramesTests.cs} (96%) create mode 100644 ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index b31d3fa..961b5c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add `GetSystemDpi` to get the system `dpi` on the fly. - Add `SystemDpi` to store the system `dpi` value. - Update `GetBitmapFrameByWidthAndDpi` to round `dpi` frame value. +- Update `Width` to `Math.Round` to improve order by `Width`. ### Example - Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. +### Tests +- Add `ResourceTiffTests` with `Cube.tiff` with multiple dpi and scales. ## [0.7.0] / 2024-07-06 - 2024-07-25 ### Features diff --git a/Directory.Build.props b/Directory.Build.props index 55a80d0..37ccfc5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-alpha.2 + 0.7.1-alpha.3 \ No newline at end of file diff --git a/ricaun.Revit.UI.Tests/Resources/Images/Cube.tiff b/ricaun.Revit.UI.Tests/Resources/Images/Cube.tiff new file mode 100644 index 0000000000000000000000000000000000000000..c99ad07e0e8aeb12814a2f037c07a92e64a1ac0a GIT binary patch literal 5310 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 literal 0 HcmV?d00001 diff --git a/ricaun.Revit.UI.Tests/Resources/ResourcesFramesTests.cs b/ricaun.Revit.UI.Tests/Resources/ResourceIcoFramesTests.cs similarity index 96% rename from ricaun.Revit.UI.Tests/Resources/ResourcesFramesTests.cs rename to ricaun.Revit.UI.Tests/Resources/ResourceIcoFramesTests.cs index a6917b5..f933c14 100644 --- a/ricaun.Revit.UI.Tests/Resources/ResourcesFramesTests.cs +++ b/ricaun.Revit.UI.Tests/Resources/ResourceIcoFramesTests.cs @@ -3,7 +3,7 @@ namespace ricaun.Revit.UI.Tests.Resources { - public class ResourcesFramesTests + public class ResourceIcoFramesTests { const string ResourceNameIcoFrames = "Resources/Images/Revit21Frames.ico"; diff --git a/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs b/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs new file mode 100644 index 0000000..b5dcc29 --- /dev/null +++ b/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs @@ -0,0 +1,85 @@ +using NUnit.Framework; +using System; + +namespace ricaun.Revit.UI.Tests.Resources +{ + public class ResourceTiffTests + { + /// + /// Tiff file with multiple scales, 1.0x, 1.5x, 2.0x, 3.0x, 4.0x for 16x16 and 32x32, 10 frames. + /// + /// + /// Tiff file based in the https://github.com/ricaun-io/Autodesk.Icon.Example?tab=readme-ov-file#autodesk-high-resolution-icons + /// + const string ResourceNameTiff = "Resources/Images/Cube.tiff"; + + System.Windows.Media.Imaging.BitmapFrame BitmapFrame; + [OneTimeSetUp] + public void Setup() + { + BitmapFrame = ResourceNameTiff.GetBitmapSource() as System.Windows.Media.Imaging.BitmapFrame; + } + + [Test] + public void GetBitmapSource_NotNull() + { + Console.WriteLine(ResourceNameTiff.GetBitmapSource()); + Assert.IsNotNull(ResourceNameTiff.GetBitmapSource()); + Assert.IsNotNull(("/" + ResourceNameTiff).GetBitmapSource()); + } + + [TestCase(32, 384)] + public void GetBitmapSource_Default_WidthAndDpi(int width, int dpi) + { + var source = ResourceNameTiff.GetBitmapSource(); + Assert.AreEqual(width, Math.Round(source.Width)); + Assert.AreEqual(dpi, Math.Round(source.DpiX)); + } + + [TestCase(10)] + public void BitmapFrame_CountFrames(int count) + { + Assert.IsNotNull(BitmapFrame); + var decoder = BitmapFrame.Decoder; + Assert.AreEqual(count, decoder.Frames.Count); + } + + [TestCase(16, 96)] // 1.0 + [TestCase(16, 144)] // 1.5 + [TestCase(16, 192)] // 2.0 + [TestCase(16, 288)] // 3.0 + [TestCase(16, 384)] // 4.0 + [TestCase(32, 96)] // 1.0 + [TestCase(32, 144)] // 1.5 + [TestCase(32, 192)] // 2.0 + [TestCase(32, 288)] // 3.0 + [TestCase(32, 384)] // 4.0 + public void BitmapFrame_ByWidthAndDpi(int width, int dpi) + { + Assert.IsNotNull(BitmapFrame); + var decoder = BitmapFrame.Decoder; + var frame = decoder.GetBitmapFrameByWidthAndDpi(width, dpi) as System.Windows.Media.Imaging.BitmapFrame; + Assert.IsNotNull(frame); + Assert.AreEqual(width, Math.Round(frame.Width)); + Assert.AreEqual(dpi, Math.Round(frame.DpiX)); + } + + [TestCase(16, 168, 192)] // 1.75 + [TestCase(32, 168, 192)] // 1.75 + [TestCase(16, 240, 288)] // 2.5 + [TestCase(32, 240, 288)] // 2.5 + [TestCase(16, 336, 384)] // 3.5 + [TestCase(32, 336, 384)] // 3.5 + [TestCase(16, 480, 384)] // 5.0 + [TestCase(32, 480, 384)] // 5.0 + public void BitmapFrame_ByWidthAndDpi_Expected(int width, int dpi, int dpiExpected) + { + Assert.IsNotNull(BitmapFrame); + var decoder = BitmapFrame.Decoder; + var frame = decoder.GetBitmapFrameByWidthAndDpi(width, dpi) as System.Windows.Media.Imaging.BitmapFrame; + Assert.IsNotNull(frame); + Assert.AreEqual(width, Math.Round(frame.Width)); + Assert.AreEqual(dpiExpected, Math.Round(frame.DpiX)); + } + } +} \ No newline at end of file diff --git a/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj b/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj index d309f72..57ee646 100644 --- a/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj +++ b/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj @@ -34,11 +34,7 @@ - - - - - + @@ -69,6 +65,7 @@ + diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index 0cf2976..d5d88cb 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -17,7 +17,7 @@ internal static BitmapFrame UriToBitmapFrame(string uriString) { var uri = new Uri(uriString, UriKind.RelativeOrAbsolute); var decoder = BitmapDecoder.Create(uri, BitmapCreateOptions.None, BitmapCacheOption.Default); - return decoder.Frames.OrderBy(e => e.Width).LastOrDefault(); + return decoder.Frames.OrderBy(e => Math.Round(e.Width)).LastOrDefault(); } /// @@ -82,9 +82,15 @@ public static ImageSource Scale(this ImageSource imageSource, double scale) return imageSource; } +#if NET47_OR_GREATER || NET /// /// Get the system DPI based on the using a new . /// +#else + /// + /// Get the system DPI based on the using a new from . + /// +#endif internal static double GetSystemDpi() { double systemDpi = 96; @@ -125,7 +131,7 @@ double OrderDpiX(BitmapFrame frame) var frames = bitmapDecoder.Frames; var frame = frames .OrderBy(OrderDpiX) - .ThenBy(e => e.Width) + .ThenBy(e => Math.Round(e.Width)) .FirstOrDefault(e => Math.Round(e.Width) >= width); return frame; From 5879f1895e8432f32633b59fe5a3f9ec63dda5d4 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 00:37:42 -0300 Subject: [PATCH 09/14] Update `GetBitmapFrameByWidthAndDpi` to public. --- CHANGELOG.md | 1 + Directory.Build.props | 2 +- ricaun.Revit.UI/BitmapExtension.cs | 10 +++++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 961b5c9..4128c16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add `SystemDpi` to store the system `dpi` value. - Update `GetBitmapFrameByWidthAndDpi` to round `dpi` frame value. - Update `Width` to `Math.Round` to improve order by `Width`. +- Update `GetBitmapFrameByWidthAndDpi` to public. ### Example - Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. ### Tests diff --git a/Directory.Build.props b/Directory.Build.props index 37ccfc5..776e1de 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-alpha.3 + 0.7.1-alpha.4 \ No newline at end of file diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index d5d88cb..757497c 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -109,16 +109,20 @@ internal static double GetSystemDpi() catch { } return systemDpi; } - internal readonly static double SystemDpi = GetSystemDpi(); + + /// + /// System Dpi + /// + public readonly static double SystemDpi = GetSystemDpi(); /// /// Get the bitmap frame from the based on the DPI and width. /// /// The bitmap decoder. /// The desired width of the bitmap frame. When set to zero, the smallest width frame is returned. - /// The optimal dpi for the frame. + /// The optimal dpi for the frame. When set to zero, is used. /// The bitmap frame with the specified width or the smallest width frame. - internal static BitmapFrame GetBitmapFrameByWidthAndDpi(this BitmapDecoder bitmapDecoder, int width = 0, int dpi = 0) + public static BitmapFrame GetBitmapFrameByWidthAndDpi(this BitmapDecoder bitmapDecoder, int width, int dpi = 0) { double systemDpi = dpi > 0 ? dpi : SystemDpi; From c41eb021f26d8747d79ef7126e004e711e8f519c Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 00:43:49 -0300 Subject: [PATCH 10/14] Remove `Ribbon Description Extension` readme --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 3ed96c9..541b236 100644 --- a/README.md +++ b/README.md @@ -389,9 +389,6 @@ Autodesk.Windows.RibbonPanel awRibbonPanel; awRibbonPanel.SetDialogLauncher(ribbonCommandItem); ``` -### Ribbon Description Extension -... Todo - ## Release * [Latest release](https://github.com/ricaun-io/ricaun.Revit.UI/releases/latest) From 8f50d6e6169cf511e9370022aa7f7c3a14912b89 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 08:03:15 -0300 Subject: [PATCH 11/14] Update `UriToBitmapFrame` to use `GetBitmapFrameByWidthAndDpi` with `int.MaxValue` --- CHANGELOG.md | 2 ++ Directory.Build.props | 2 +- .../Resources/ResourceTiffTests.cs | 25 ++++++++++++++++--- ricaun.Revit.UI/BitmapExtension.cs | 12 ++++++--- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4128c16..2f498c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Update `GetBitmapFrameByWidthAndDpi` to round `dpi` frame value. - Update `Width` to `Math.Round` to improve order by `Width`. - Update `GetBitmapFrameByWidthAndDpi` to public. +- Update `GetBitmapFrameByWidthAndDpi` to return last `Width`. +- Update `UriToBitmapFrame` to use `GetBitmapFrameByWidthAndDpi` with `int.MaxValue`. ### Example - Add `Cube-Grey-Light.tiff` and `Cube-Grey-Dark.tiff` in `AppTheme`. ### Tests diff --git a/Directory.Build.props b/Directory.Build.props index 776e1de..72ef80b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-alpha.4 + 0.7.1-alpha.5 \ No newline at end of file diff --git a/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs b/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs index b5dcc29..8198cfe 100644 --- a/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs +++ b/ricaun.Revit.UI.Tests/Resources/ResourceTiffTests.cs @@ -28,12 +28,14 @@ public void GetBitmapSource_NotNull() Assert.IsNotNull(("/" + ResourceNameTiff).GetBitmapSource()); } - [TestCase(32, 384)] - public void GetBitmapSource_Default_WidthAndDpi(int width, int dpi) + [TestCase(32)] + public void GetBitmapSource_Default_Width(int width) { var source = ResourceNameTiff.GetBitmapSource(); Assert.AreEqual(width, Math.Round(source.Width)); - Assert.AreEqual(dpi, Math.Round(source.DpiX)); + var systemDpi = BitmapExtension.SystemDpi; + if (systemDpi != Math.Round(source.DpiX)) + Assert.Ignore($"SystemDpi:{systemDpi} != {Math.Round(source.DpiX)}"); } [TestCase(10)] @@ -72,7 +74,7 @@ public void BitmapFrame_ByWidthAndDpi(int width, int dpi) [TestCase(32, 336, 384)] // 3.5 [TestCase(16, 480, 384)] // 5.0 [TestCase(32, 480, 384)] // 5.0 - public void BitmapFrame_ByWidthAndDpi_Expected(int width, int dpi, int dpiExpected) + public void BitmapFrame_ByWidthAndDpi_DpiExpected(int width, int dpi, int dpiExpected) { Assert.IsNotNull(BitmapFrame); var decoder = BitmapFrame.Decoder; @@ -81,5 +83,20 @@ public void BitmapFrame_ByWidthAndDpi_Expected(int width, int dpi, int dpiExpect Assert.AreEqual(width, Math.Round(frame.Width)); Assert.AreEqual(dpiExpected, Math.Round(frame.DpiX)); } + + [TestCase(64, 96, 32)] // 1.0 + [TestCase(64, 144, 32)] // 1.5 + [TestCase(64, 192, 32)] // 2.0 + [TestCase(64, 288, 32)] // 3.0 + [TestCase(64, 384, 32)] // 4.0 + public void BitmapFrame_ByWidthAndDpi_WidthExpected(int width, int dpi, int widthExpected) + { + Assert.IsNotNull(BitmapFrame); + var decoder = BitmapFrame.Decoder; + var frame = decoder.GetBitmapFrameByWidthAndDpi(width, dpi) as System.Windows.Media.Imaging.BitmapFrame; + Assert.IsNotNull(frame); + Assert.AreEqual(widthExpected, Math.Round(frame.Width)); + Assert.AreEqual(dpi, Math.Round(frame.DpiX)); + } } } \ No newline at end of file diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs index 757497c..e0d7818 100644 --- a/ricaun.Revit.UI/BitmapExtension.cs +++ b/ricaun.Revit.UI/BitmapExtension.cs @@ -17,7 +17,7 @@ internal static BitmapFrame UriToBitmapFrame(string uriString) { var uri = new Uri(uriString, UriKind.RelativeOrAbsolute); var decoder = BitmapDecoder.Create(uri, BitmapCreateOptions.None, BitmapCacheOption.Default); - return decoder.Frames.OrderBy(e => Math.Round(e.Width)).LastOrDefault(); + return decoder.GetBitmapFrameByWidthAndDpi(int.MaxValue); } /// @@ -133,11 +133,15 @@ double OrderDpiX(BitmapFrame frame) } var frames = bitmapDecoder.Frames; - var frame = frames + var framesOrder = frames .OrderBy(OrderDpiX) - .ThenBy(e => Math.Round(e.Width)) - .FirstOrDefault(e => Math.Round(e.Width) >= width); + .ThenBy(e => Math.Round(e.Width)); + var widthMax = (int)Math.Round(framesOrder.LastOrDefault().Width); + if (width > widthMax) + width = widthMax; + + var frame = framesOrder.FirstOrDefault(e => Math.Round(e.Width) >= width); return frame; } From 71bb7f7b1845ba44c0792c4b049d038bde131c68 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 14:10:17 -0300 Subject: [PATCH 12/14] prerelease rc --- CHANGELOG.md | 2 +- Directory.Build.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f498c6..87c8026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [0.7.1] / 2024-11-11 +## [0.7.1] / 2024-11-11 - 2024-11-19 ### Features - Support `tiff` files for icon. ### Updated diff --git a/Directory.Build.props b/Directory.Build.props index 72ef80b..3e3b5f3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-alpha.5 + 0.7.1-rc \ No newline at end of file From 625682ac219db61111e3096eb2a1869864276d58 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 17:14:39 -0300 Subject: [PATCH 13/14] Release 0.7.1 --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 3e3b5f3..787fd63 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.7.1-rc + 0.7.1 \ No newline at end of file From 2a1b12cb3d37973efa0bf1163c424bb8207bcbf7 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Tue, 19 Nov 2024 17:21:08 -0300 Subject: [PATCH 14/14] Remove Example Console --- ricaun.Revit.UI.Example/Revit/AppTheme.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ricaun.Revit.UI.Example/Revit/AppTheme.cs b/ricaun.Revit.UI.Example/Revit/AppTheme.cs index 7a4a9a1..d8aa158 100644 --- a/ricaun.Revit.UI.Example/Revit/AppTheme.cs +++ b/ricaun.Revit.UI.Example/Revit/AppTheme.cs @@ -65,14 +65,14 @@ public Result OnStartup(UIControlledApplication application) { var buttonTiff = ribbonPanel.CreatePushButton("Grey") .SetLargeImage("Resources/Cube-Grey-Light.tiff"); - if (buttonTiff.LargeImage is System.Windows.Media.Imaging.BitmapSource largeImage) - { - System.Console.WriteLine($"{largeImage.GetType().Name} | {largeImage.Width:0}x{largeImage.Height:0} ({largeImage.PixelWidth}x{largeImage.PixelHeight}) {largeImage.DpiX:0}:{largeImage.DpiY:0}"); - } - if (buttonTiff.Image is System.Windows.Media.Imaging.BitmapSource smallImage) - { - System.Console.WriteLine($"{smallImage.GetType().Name} | {smallImage.Width:0}x{smallImage.Height:0} ({smallImage.PixelWidth}x{smallImage.PixelHeight}) {smallImage.DpiX:0}:{smallImage.DpiY:0}"); - } + //if (buttonTiff.LargeImage is System.Windows.Media.Imaging.BitmapSource largeImage) + //{ + // System.Console.WriteLine($"{largeImage.GetType().Name} | {largeImage.Width:0}x{largeImage.Height:0} ({largeImage.PixelWidth}x{largeImage.PixelHeight}) {largeImage.DpiX:0}:{largeImage.DpiY:0}"); + //} + //if (buttonTiff.Image is System.Windows.Media.Imaging.BitmapSource smallImage) + //{ + // System.Console.WriteLine($"{smallImage.GetType().Name} | {smallImage.Width:0}x{smallImage.Height:0} ({smallImage.PixelWidth}x{smallImage.PixelHeight}) {smallImage.DpiX:0}:{smallImage.DpiY:0}"); + //} } ribbonPanel.RowStackedItems(