Best Practice for laying out images for printing in a WYSIWYG Mac app? - macos

I'm in the concept phase of a Mac application that should let the user easily select and layout images for printing. It's a document-based app and a document can have multiple pages with lots of pictures in different sizes and rotations on it. The UI would kind of be like the UI of Pages.app.
Those pictures can possibly be large hi-res images. The user should also be able to print them in the best quality that the images offer.
I have re-watched some WWDC sessions about Quartz, 2D drawing optimization and NSView.
I know that there are a few different ways of accomplishing what I want to do, namely:
Use a custom view for a "page" and draw the images in drawRect: with Core Graphics/Quartz. Use CG transforms to rotate and scale images.
Also use a custom view for a "page", but use NSImageView-subviews to display the images. Use Core Animation and layer transforms to scale/rotate images.
What is the best practice for this? Drawing with Core Graphics or using NSViews? Why?
Thank you so much!
Johannes

Depends on how interactive these pages should be. If there is a lot of mouse interaction, e.g. dragging, selecting etc. I'd go with views. If you want fluid animations I'd even use plain CALayers with their content set to one image. This would also let you zPosition the images in case they overlap. A view based solution makes z-ordering hard.
The drawRect method should be fastest but you have hard times integrating user interaction and you must z-order manually.

This is a reply I got from opening one of my two Apple Technical Support Incidents:
Hi Johannes,
Thanks for contacting Apple DTS regarding your question about printing
and the different ways to construct your applications general UI (with
views).
There is a trend toward using layer-backed views in OS X (utilizing
Core Animation layers) which is motivated by the ability to easily
animate your application's user interface, with little work, when
needed. However in terms of printing, you would be better off to
implement drawRect for custom views so that the view contents can be
drawn at "full resolution" when rendered into the context for
printing.
If instead you use layer backed views at as those layers to
"renderInContext" the layer contents would be used to render, which
commonly will not be set to the full resolution of your source
documents/images. This is because layer backed views take additional
memory to store those bitmaps (cached layer contents), and because of
that, they are recommended to be sized appropriately for the screen
(which may not necessarily be sized appropriately for the printed
page).
Does this help guide your application architecture? Please let me
know.
So basically this means that using layer-backed views might result in sub-optimal printing quality. I've replied with some follow-up questions ("How setting wantsLayer = NO on the rootView right before printing help?") and will post the answers as soon as I get them.

All three approaches should work. Since you should be using scaled-down representations of large images anyway, I don't think there will be much difference. Do what you feel most comfortable doing.
My guess is just using layer-backed NSViews (one par draggable image) will probably work best for starters. If you find performance lacking, you can always micro-optimize. Note that you may have to make your views a tad larger than the images so you can draw the selection handles outside them.
This is all assuming that you will never want to do a more complex drawing.

Related

Jetpack Compose: most performant way to show a grid of many icons to select from

I'm allowing users to select an icon from the full list of FontAwesome icons (using a List<ImageVector>). I'm going to open a dialog, and show the icons as IconButtons arranged in the list. There are ~1600 icons.
I implemented it using a LazyVerticalGrid, with a fixed number of columns. It works, but there's some lag loading the icons, and lag when scrolling the icons.
I'm converting this from a React Native project where I did the same thing (with a larger set of icons, actually) and scrolling that was pretty snappy, so I'm assuming it's possible to do performantly on native. Perhaps ImageVectors are heavier than the SVGs I was using in React Native?
I'm planning to provide a search box in the dialog where users can filter the list down by doing a fuzzy search on icon names, so the grid will change over time.
What sort of patterns should I be looking at here? Is LazyVerticalGrid the way to go, or should I be using a different approach entirely?
On Laziness
For an overview of use cases and appliable patterns you might be interested in the Android Dev Docs' page on Lists and Grids, încluding the topics Large data-sets (Paging) and the Tips on using Lazy layout.
This might wake your interest on the Android Jetpack Paging Library androidx.paging, which is designed for loading and displaying pages from large datasets, basically uniting the concepts of Laziness and Caching.
Currently you're only using Laziness. As Bartek Lipinski commented, that should usually be fine when the graphics to display are static. However, when they have to be loaded asynchronously, Paging will probably improve your performance.
Some Rules of Thumb
Scrolling
Pattern
No
Column or Row will be enough
Some
Column or Row with modifiers verticalScroll and horizontalScroll
More, static content
LazyColumn or LazyRow, resp. for gridding LazyVerticalGrid or LazyHorizontalGrid
More to mass, dynamic content
LazyColumn or one of its relatives with LazyPagingItems, so using the Paging Library androidx.paging
Also, as the docs say, consider adding contentType
. However, as Bartek Lipinski remarked, one usually benefits of contentType when there are scrollable elements of various types -- not only SVGs as maybe in your case. Still, giving hints to the system doesn't hurt, at least.
On Vector Graphics
As discussed in the comments, esp. by Subfly and Bartek Lipinski, though Laziness should be the main thing here, another bottleneck could be the loading of vector graphics during runtime.
If the graphics used are of static nature, then consider the usage of vector graphic assets. Those are supported for SVG and PSD since Android 5.0 (API level 21). Take also a look on the recommendations and some aspects of support and restrictions on SVG.
Summary
The basic formula is Laziness + Vector Assets with focus on the first. One might spice that with contentType and Paging.

Rendering CALayer multiple times

I've been trying to figure out the best way to show an existing CALayer in a secondary window to allow real-time full-screen output on a secondary monitor. Additionally I would like to have the ability to show real-time thumbnails in my application of the original CALayer, it seems like I should be able to find a setup that could fulfill both requirements.
So far my research resulted in the following options:
CALayer.render(in: CGContext) Using the original layer and redrawing it to additional views this way and setting up a timer or a CVDisplayLink to redraw it every frame.
Rendering the CALayer to a NSBitmap every frame. And using that bitmap in NSImageView across the application.
Using a CAMetalLayer and rendering the texture multiple times using a MTKView. I'm not really familiar with Metal, this seems like a fairly elegant solution, but I'm not sure if it is required to go all the way down to Metal myself.
Using a CARemoteLayerServer with a CARemoteLayerServer.
This seems like an overly complicated setup for in-process sharing of a CALayer and it feels like this approach is more suitable if I'd need to share the layer cross-process.
Using CAReplicatorLayer. Instead of using the replicator layer to create a grid of copies I tried to use it to create just one copy, but it seems like you cant add a CALayer to multiple "parent layers".
All in all I've found some workable solutions, but as I'm quite a novice working with Core Animation I'm not sure which direction is the least resource-heavy and I might still be missing an easier solution.
Has anyone tried something similar?

WP7: IsolatedStorage vs. WriteableBitmap

I have a scenario that I need some good solid advice on. The question is really about speed of WriteableBitmap vs. images in IsolatedStorage on the Windows Phone.
I have an app that displays a UserControl (#1) which is a little graphically heavy. When the user swipes it, it transitions in a push-left type of transition to bring in a new UserControl (#2) which is also a little graphically heavy. If the user swipes the other way, control #1 is brought in in the same type of push-transition, this time from the right.
What I do today is take a snapshot of #1, load #2 off screen and take a snapshot of it, put both side-by-side in a Canvas control and animate that control either left or right. One of the reasons I don't just use the controls and animate them is they may have animation that starts when they are loaded - my current technique allows me to capture a screen shot of pre-animation and post-animation, depending on which direction they go in.
What I'm wondering, however, if it would be better/faster to just do the above the first time and send the writeablebitmap to IsolatedStorage with Extenstions.SaveJPEG and just use that instead in subsequent tranistion animations.
Would load/render/WriteableBitmap each time generally be faster or load jpeg from IsolatedStorage be faster each time? I see that the Transitions control in the SDK doesn't really do either of these, so I'm open to suggestions that are different that also might improve performance.
I expect this to be very depended on the hardware and application. So it is pretty hard to give an answer based on this input. It doesn't look to hard to test (on actual hardware and with the actual application) so my advice is to build both and test.
The applications I have been working with use both approaches and to be honest I haven't noticed much difference.
Also you might try and enable bitmap caching on the controls. This will give you a writeable bitmap implementation that is very fast.

Cocoa Scalable Interface for Digital Signage Display

I'm working on a Cocoa application which will be used for a digital-signage/kiosk style display. I've never done anything like this with Cocoa before, but I'm trying to figure out what the best approach is for building the user interface for it.
My main issue is that I need a way to have the user interface scaled up or down depending on the resolution of the display. When I say scaled, I mean that I want everything including white space to maintain the same sizing ratio. The aspect ratio of the interface needs to remain the same (16x9), but it should always fill the entire width of the display its on.
Sorry if I'm not being descriptive enough.
What are some thoughts?
If I follow you correctly, you want all buttons and views, etc. to get larger, the bigger the screen is (which has nothing to do with the dimensions of your views). If that's the case, there's no automatic way to do this.
With Quartz Debugger (part of Xcode Tools), you can set the scaling factor (see "resolution independence"), but this would need to be manually adjusted per system. What's more is I'm not sure if this tinge is persistent across reboots. I leave that for you to investigate.
As far as I know, though, there's no way to adjust this programmatically as resolution independence is still not an exposed consumer feature of OS X.
If anyone is interested, I seem to have found a solution under this post: http://cocoawithlove.com/2009/02/asteroids-style-game-in-coreanimation.html

Any suggestions for best practices to follow when creating UI prototypes using sketchFlow for multiple screen sizes?

am looking to prototype the UI for an windows application. The app will be deployed on several display devices with different (physical) screen sizes and aspect ratios. Would like to be able to generate scenarios optimized on one display and quickly check if the layout is OK on different screen sizes, orientations. That is, I'd like to prototype one set of scenarios and "automatically" generate the same scenarios on different screens. Have superficial knowledge of MS Sketchflow. Have seen some best practices at http://www.wpftutorial.net/LayoutProperties.html#best . Am wondering if folk can advise on best practices to follow in sketchflow.
Bye
To quickly be able to check how things will look, I have 2 possible suggestions:
Use the states panel to create a state group/states that change the size of the layout container (such as layoutroot) you are working with. Then in the sketchflow player, you can select the state from the navigation menu and see how it looks.
Use a ChangePropertyAction behavior from the asset panel attached to a button. You can set the height or width to the size you want. If you use 2, you can set both the height and width. This would give you the ability to control the layout size and see how it is rendered.
Hope that helps, let me know if you need more info.
Keep a consistent theme between the pages, kind of goes without saying.

Resources