![]() |
Disabling Vector |
Post Reply ![]() |
Author | |
navap ![]() Groupie ![]() ![]() Joined: 11 June 2019 Location: India Status: Offline Points: 12 |
![]() ![]() ![]() ![]() ![]() Posted: 17 September 2021 at 9:01am |
I am trying to use xaml icons in command bar for my application.Previously I have used bitmap images for my ribbon bar , now I am trying to replace them with xaml icons. I have followed the codejock sample "CommandBarIcons" . I have following queries
1. How do I disable this vector icon ? I have tried using below method , but I am not able to disable the icon. Is there any other call which I am missing ? XTPImageManager()->SetVectorIcon(_T("RT_XAML"), IDR_XAML_ICON_DISABLED_SAVEALL, ID_FILE_SAVEALL, XTP_DPI_X(16), xtpImageDisabled); 2. Also is there any method which automatically disables the icon , like in bitmap image (which doesn't require any gray-image). |
|
Thanks,
Navap |
|
![]() |
|
astoyan ![]() Admin Group ![]() ![]() Joined: 24 August 2013 Status: Offline Points: 284 |
![]() ![]() ![]() ![]() ![]() |
Setting an icon with xtpImageDisabled only adds that image into the image collection and tells it that it's associated with a disabled state of a control where it will be used in, but it does not make it to use the disabled icon right away. Whenever a command bar button is in disabled state its paint manager will try to obtain and draw an xtpImageDisabled icon.
And there is no method to make a disabled icon automatically.
|
|
![]() |
|
markr ![]() Senior Member ![]() Joined: 01 August 2004 Status: Offline Points: 442 |
![]() ![]() ![]() ![]() ![]() |
My approach to solving this was to hack together some code that loads the XAML icon from resources and replaces any colors it uses with a light shade of gray. It is then stored in the image list for use by the "disabled" state.
Yeah, it's ugly - but preferable to creating and storing all the disabled vector variants separately.
|
|
![]() |
|
navap ![]() Groupie ![]() ![]() Joined: 11 June 2019 Location: India Status: Offline Points: 12 |
![]() ![]() ![]() ![]() ![]() |
Thanks for the response . I am able to enable/disable the icon when command bar button state is changed . However my concern is that I have to maintain 4 sets of icons (normal-large, normal-small, disabled-large, disabled-small) if I have to go with vector icons, previously i.e. while using bmp icons it was only 2 sets of icons (large and small).
I am trying to understand if there any better way to handle this. Loading file and changing its attributes programmatically is the best logic I could come across.
|
|
Thanks,
Navap |
|
![]() |
|
dbrookes ![]() Groupie ![]() Joined: 30 August 2019 Location: Australia Status: Offline Points: 69 |
![]() ![]() ![]() ![]() ![]() |
I do a similar thing to markr, except at pre-compile time. I have a powershell script that runs over the XAML XML and grayscales any colours to create disabled variants of icons. All my icons are stored in a tar gz archive that I load and create vector icon handles at runtime. I don't store icons in a resource DLL. I guess it depends how many icons your dealing with whats worth it for you. If you haven't got a large number of icons its probably fine to grab the XAML from your resource DLL and to generate disabled variants at runtime.
|
|
![]() |
|
markr ![]() Senior Member ![]() Joined: 01 August 2004 Status: Offline Points: 442 |
![]() ![]() ![]() ![]() ![]() |
> If you haven't got a large number of icons its probably fine to grab the XAML...
More icons = better software
![]() |
|
![]() |
|
Pesci7 ![]() Groupie ![]() ![]() Joined: 27 January 2021 Location: Italy Status: Offline Points: 16 |
![]() ![]() ![]() ![]() ![]() |
Is it better lo load icons from an external file instead of from resources? Actually I had to add a splash screen on startup because of initial icons loading. Any advice? Thanks
|
|
Product: Xtreme ToolkitPro (22.1.0)
Platform: Windows 11 (x64) Language: Visual Studio 2022 (C++) |
|
![]() |
|
dbrookes ![]() Groupie ![]() Joined: 30 August 2019 Location: Australia Status: Offline Points: 69 |
![]() ![]() ![]() ![]() ![]() |
There are benefits but also downsides. A benefit being avoiding
have to add resource ids and so on for each icon, icon size and icon
state. It is more work to setup loading from an external source. You
have to map those to command ids at some point. We do have a resource
DLL of course full of all the usual stuff, just not our icons. I doubt
there is a big performance difference one way or the other. If I had to
guess resources would be faster. Recently I found for this use case that
.tar.gz is a fair bit faster than .zip with similar compression so
switched to that. As for vector icon
loading it self. I too found that the performance of that can be a
problem. We added around 4 seconds to our loading time when we moved to
using vector icons. Not to mention around ~400mb more initial memory
usage. We do have quite a lot of icons so are probably an outlier.
Around 1200 icons total, each with a small and large, and with a normal
and disabled state. So that makes around 5000 icon handles to load.
Loading all that markup takes a lot of time. You can save a little bit of time by minifying your XAML at pre-compile time but that'll only get you so far. One thing I tested out was loading these on a worker thread but this stuff is just generally not thread safe. This is a bad idea. Here is a patch someone might find interesting... CXTPImageManagerVectorImageHandles actually already keep a copy of the XAML in their serialization data buffer. Piggy
backing off of this we can delay building the markup UI element until
we first try and draw the vector icon rather than immediately. If
you have a ribbon like we do this means icons are built as they become
visible when switching tabs. Building a tab worth of icons is quick
enough its not noticeable. Similarly the disabled icon for things won't
be built until they are needed. This took our loading time from 4
seconds to around 27ms and took our initial memory usage way down. That
memory usage grows over time as icons are built on demand. This delayed markup building
idea can be used for markup list boxes as well by the way if you have a
very large number of items to deal with. This only works for fixed
height owner draw though since we can't measure the markup if it isn't
built for variable height owner draw. The former is better for
performance usually anyway.
|
|
![]() |
|
Pesci7 ![]() Groupie ![]() ![]() Joined: 27 January 2021 Location: Italy Status: Offline Points: 16 |
![]() ![]() ![]() ![]() ![]() |
Should I change SetVectorIcon, SetVectorDisabledIcon, ... methods to call CreateDelayedMarkupHandle instead of CreateMarkupHandle to use this patch? |
|
Product: Xtreme ToolkitPro (22.1.0)
Platform: Windows 11 (x64) Language: Visual Studio 2022 (C++) |
|
![]() |
|
dbrookes ![]() Groupie ![]() Joined: 30 August 2019 Location: Australia Status: Offline Points: 69 |
![]() ![]() ![]() ![]() ![]() |
I think so... haven't tried that to be honest since I don't load from resources. I call CreateDelayedMarkupHandle myself and then call the image manager SetVectorIcon with that handle.
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
Hi dbrookes, I'm looking into XAML icons. I have code that loads icons on demand from either individual files on disk or via resource DLLs. I use the LoadBitmapFromFile method. All I found in CJ was SetVectorIcon APIs that just load via a resource. You mentioned loading XAML icons yourself. Did you find an API to use to load XAML from files? Oh, and I liked your comment about delayed loading. We have our own ribbon class so it might be handy to load icons when a tab is activated and not just load all them when we start up. Though we build ribbons for other reasons than for being displayed such as for some customization code and for a 3D controller that likes to obtain our command images as it can add commands to its own UI (some of them have fancy screens). But, I can "force load" images if need be. I'll keep your comment in mind if I start to see a slowdown.
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
Hi dbrookes, Regarding my last question: XTPCreateReadOnlyFileStream perhaps? Looks promising.
|
|
![]() |
|
markr ![]() Senior Member ![]() Joined: 01 August 2004 Status: Offline Points: 442 |
![]() ![]() ![]() ![]() ![]() |
Hi rdhd,
I load XAML icons "on demand" (during containing window construction) from program resources and haven't observed much of a delay at all. My approach is to parse the icon XAML and replace all instances of "fill" and "stroke" attributes with dimmed versions of the target colors. For the dimming, I first convert the color to grayscale and then "lighten" it by 50%. The resulting disabled XAML images are then cached in an XTP image manager instance. Just wanted to share what's been working well for me in case it helps. - Mark
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
Hi markr, I was thinking that if we add support for xaml icons, I would want to load from files or resources. Not because of a performance issue but because it can be more dynamic. Image creation people can just drop a file on disk and cause a load or reload to occur in our app and they can view the results right away. No coding needed, no build or waiting for a build to deploy. I do this for BMP and PNG now and the image creator just has to go to our options dialog and change color theme (I support images on a per color theme basis too). I discover the ID of the resource by using a naming convention that has the ID included in the name. Filenames have the ID and when adding a resource using Visual Studio, one just goes to the properties window and selects the auto-generated ID and types something like (quotes included) "image12345_16". The "16" is irrelevant to my code as I just care what is between "image" and "_". Filenames follow the same pattern - image12345_16.png, image12345_32.png ... I also auto-scale images using WIC for cases where a user is running at a high DPI like 200% on a 4k monitor. If any scaled image looks bad, our team just creates, say a 64x64 version of an image and drops it on disk (image12345_64.png), or adds it to the resource DLL and forces the reload. I haven't tried using XTPCreateReadOnlyFileStream yet to see if that's the way to load a XAML icon from disk but it appears that it should work. As for dimming, I don't supposed you tried setting an opacity to some low value like 0.3? I've been playing around with that and it shows promise. Images "fade" out quite well - so far. Ok, so I only have one simple image taken from the CommandBarIcons sample so its very simple ...
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
I have it - CXTPImageManager::OleLoadVectorIcon. The "Ole" threw me when I was searching their files. Looks like this is the highest level call I can make analogous to the API I use to load an image from file and give it to the image manager.
|
|
![]() |
|
dbrookes ![]() Groupie ![]() Joined: 30 August 2019 Location: Australia Status: Offline Points: 69 |
![]() ![]() ![]() ![]() ![]() |
Hi rdhd. The way I do it is have an archive of all of the .xaml files. I used to use .zip but found .tar.gz with libarchive to be much faster for this. I open this archive once on startup and read all of the .xaml out of it into strings. I then use CXTPImageManagerVectorImageHandle CreateMarkupHandle, actually I use my patched CreateDelayedMarkupHandle function I mentioned above. By the way that likely only helps if you have a very large number of icons to load. I'm loading around 1200, but each have small and large, normal and disabled. So its actually around 5000 icons being loaded. I think using the IStream version of these should work fine if you want to read directly from a file stream. If you want to pre-process the .xaml though to do something like creating disabled variants it may be better to read the file into memory first, do what you want and then pass the string to CreateMarkupHandle. I mentioned above I think, but I generate disabled icons at pre-compile time with a powershell script. For grayscaling I use the following function.
Shouldn't be too hard to do the same thing in C++. For light themes I use a brightness factor of 0.5, for dark themes I use a brightness factor of 1.25. By the way. The names of my icons are actually the id names of the command. e.g. ID_FILE_NEW.xaml. I have a pre-compile awk script that parses CommandsRes.h into a header file that contains the id name strings and id number paired together. That way we can map the file name to the id of the command at runtime. Regards, Daniel.
|
|
![]() |
|
markr ![]() Senior Member ![]() Joined: 01 August 2004 Status: Offline Points: 442 |
![]() ![]() ![]() ![]() ![]() |
> I don't supposed you tried setting an opacity to some low value like 0.3.
I did, and found the results unsatisfactory. I use a grayscale conversion function very similar to what Daniel shared in this thread, then also adjust the brightness a bit. Opacity doesn't alter the colors, so it never actually looks "disabled" to me.
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
Yep. Opacity will fade them out but the hue remains. Just wondered if that was enough to indicate disabled. Of course some images can be grayscale themselves too. If we end up supporting XAML, I'll be tempted to just change the CJ markup code if possible. I usually use the NTSC color to grayscale conversion method so its quite easy and fast. Better than SECAM which we always joked meant "Something essentially contradictory to the American method).
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
Hi dbrookes,
I was reading your post as I am trying to figure out how this xaml stuff works. Out UI team wants to create a single vector icon for each ribbon control or backstage button (ignoring disabled for now) that will work for any user DPI setting. So I ask why are you creating two sizes? I think our UI team is aiming to create 32x32 (pixel) sizes only. At least when I set the image size I am passing in 32 as the width. They are actually clamoring for SVG as our company has many products that use SVG and apparently their experience with SVG has led them to believe a single vector image should be sufficient. We are the only Windows desktop product in the company that uses CodeJock and they keep asking why we don't support SVG. As an aside, so far, the UI team have not provided a single Silverlight xaml image that displays in CJ V 22.0. I can open them in Internet Explorer with no problem. They are currently trying Inkscape's latest version and using the save as Silverlight option. I have managed to get CJ to actually create a test image but only after I deleted the xaml <LinearGradientBrush.GradientStops> and <GradientStopCollection> the UI team is fond of. Either that stuff is not part of Silverlight or CJ just doesn't support those elements. CJ cannot create the runtime classes at which point CJ just gives up. Even after doing that and getting parse to succeed and an image icon to be available, I have stepped thru lots of code and see CJ using GDI+ to draw but nothing shows up. I installed inkscape on my box and created the simplest image I could. I set the canvas size to 32x32 and placed an ellipse. After stepping thru the CJ parsing code, I found I had to delete <Canvas.Resources/> because it was empty and CJ didn't just ignore that, it gave up. I have asked the UI team to try an Adobe Illustrator add-in that I saw mentioned on the forums here so they can save their images as Silverlight xaml and hopefully it will work. I would note that I have no real ideal how to use Inkscape so I just hacked a bit to see what I could see. My ellipse did finally display though it is quite a bit smaller than I expected. I'm guessing "px" does not stand for "pixel" but getting something to display is a start. I can see this attempt to use xaml turning into a debugging nightmare :( Also, when searching around for Silverlight, I saw Microsoft saying it is at "end of life". All documenation I have scanned so far is related to WPF. I was searching for LinearGradientBrush and its MappingMode (CJ choked on the mapping mode too) and GradientStops to see if they are valid entities. I have asked the UI team to see if they can create gradients with no mapping mode and no <GradientStops> element. Is this CodeJock compatible xaml creation as difficult to come to grips with as it appears so far? Our UI team has tried a number of times over the last year or two to give me xaml files that work in CJ. The only images I have gotten to work as we expect is xaml icons I have found in CJ itself. Well, and today, my tiny ellipse!
|
|
![]() |
|
dbrookes ![]() Groupie ![]() Joined: 30 August 2019 Location: Australia Status: Offline Points: 69 |
![]() ![]() ![]() ![]() ![]() |
Hi rdhd. The reason for doing 16px and 32px vector icons is for style mainly. If you have a 1px stroke at 16px, but you rasterize that at 32px, that stroke will come out 2px thick. Our icon style is similar to Office and Axialis 2019 (Axialis' XAML tends to work good in XTP by the way). So we want 1px strokes at 16px and at 32px. And we also have slightly different proportions and padding for small 16px vector icons versus large 32px vector icons. If it works for you, you can maybe get away with a single size. You may have to use <Viewbox> tags to get the XAML to rasterize at variable sizes. But that can ruin your pixel alignment and make your icons look blurry. That being said so will non-integer DPI scaling. I'd be careful with it. Give this article from Axialis a look: I have had similar issues with XTP XAML as what your having. When we first started to do vector icons InkScape was the first thing we tried. It does spit out stuff that XTP doesn't like. The XAML support in XTP is only a subset of whatever XAML elements Silverlight, WPF and so on have available. So you got to be a bit careful and stick with the basics. The MarkupPad utility is useful for testing this stuff. Here is what I know isn't supported:
Additionally I know that the following are interpreted as integers instead of floating point:
But these are rarely too much of an issue, especially if you are pixel aligned. We are still using the XAML export plugin for Adobe Illustrator and exporting with "XAML for Silverlight". And that works most of the time for us. There are a few weird things with that plugin. Like having to put a transparent rectangle that covers the entire canvas to ensure the output XAML canvas size is the entire canvas (otherwise it clamps down to the content). But it mostly gets the job done. But gradients are not something that tends to work I think. We had one or two icons trying to do it we had to rework to not include a gradient. Another idea I was contemplating trying, but never got around to trying, was having a pre-compile step that goes over the icon SVG or XAML vector icon resources and rasterizes them with an external library, like maybe nanosvg for svg or .NET for xaml, to appropriately sized bitmaps. Alternatively this could be done at runtime for the current DPI awareness and then cached. Then you can load those perfectly sized bitmaps right into the XTP image manager and side-step the XTP XAML entirely. But who knows if this is a good idea or not in practice. Hope that helps :)
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
Hi dbrookes,
As usualy your post is quite detailed and immensely useful. I tried ShapeConverter yesterday and found that GeometryDrawing and other elements you mentioned that I had not yet encountered and tried were indeed DOA in CodeJock. I have asked our UI team to read your reply as you have added a lot of good tips on how to approach using CodeJock xaml. I sure hope CodeJock is actively working on improving xaml support. Too bad they have focused on Silverlight which is quite "old" and, as Microsoft has indicated, passe.
|
|
![]() |
|
rdhd ![]() Senior Member ![]() ![]() Joined: 13 August 2007 Location: United States Status: Offline Points: 867 |
![]() ![]() ![]() ![]() ![]() |
We have decided to move on with trying to use XAML in Codejock. Instead, we are using SVG via Direct2D which has APIs that lets one render SVG to a bitmap. D2D supports more SVG than CJ supports XAML. The main limitation we have found is referenced styles. So, we just embed the style into each SVG element. So far our results are pretty good and there are a lot more tools that create SVG than create Silverlight XAML which is a Microsoft format created long, long ago in an OS far, far away. I think I saw a Microsoft note saying Silverlight XAML is end of life and its time to move on. When we load our SVG images, we know what the size of the images we want and we render to a bitmap. We render and then give the image manager the bitmap. This also means that the normal CodeJock code that automatically creates the disabled image works. Also, we use HTML tooltips and the Microsoft low level control that renders HTML supports SVG. We reference our SVG image for a command in the title/caption area of our tooltips. The D2D functionality does depend on the version of Windows. One has to support NTDDI_WIN10_RS2. So, if you have to support Win10 build 1703, this SVG solution probably isn't an option. We have not flipped a switch yet to compile everything under RS2. We just push and pop a pragma in the one file that uses the D2D SVG APIs we use to render our images. Microsoft will be phasing Win 10 out. I think around this time next year. So, the version, at leas for us, will be a non-issue once we update all our projects. Also, I presume that Microsoft will continue to enhance their D2D support of SVG as it is an open standard. See, ID2DRendterTarget and ID2D1DeviceRContext5. It was not much code for our display guru to implement SVG using Windows Imaging Component and D2D. |
|
![]() |
Post Reply ![]() |
|
Tweet
|
Forum Jump | Forum Permissions ![]() You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |