I have 2 possible ways to display my FlowDocument:
FlowDocumentScrollViewer
Upside:
- This just presents me the data, with no attention to pages, so the user simply scrolls through everything. On printing I can add a header and a footer and the pages are decided there.
- When I resize my window, the content stays correctly at 100% zoom, as I want it to be.
Downside:
- With a lot of data it just crashes, it seems to render all controls at once, or something.
FlowDocumentPageViewer
Upside:
- With a lot of data it's still fast.
Downside:
- It decides pages for me, which are irrelevant.
- When I resize my window, the content zooms out to fit the window. Which makes the content unreadable very quickly. Possible fix to this is surrounding the control with a ScrollViewer, which works. But when you scroll down to view bottom page content, at the end it goes to the next page, and if you then scroll up too far it goes to previous page, very annoying.
What I eventually want is the FlowDocumentScrollViewer, but then with fast loading time.
Anyone with any ideas/tips on this matter? Much appreciated!
Use a FlowDocumentReader then the user can can go scroll or page at run time. This will not solve stability problems. I display some documents with 200,000 characters and it is stable for me. It load via Dispatcher so may want to look there.
Related
I'm trying to understand animation loops in WebGl, along with React.
Basically, does the browser repaint specific elements without repainting the whole screen? Does a a reflow always refresh the whole screen? What exactly is the difference between what happens when you manually refresh the window with a refresh button, verses what reflow or repaint? I know this technology has been around awhile, but I never really dove into it much before.
I'm just trying to to understand how a webGL code animates on a canvas element and how React changes elements on a screen, without the whole screen reloading. I've read about requestAnimationFrame, and about how React bundles and diffs virtual dom changes, reducing the number of requests for rerender, but my question is more about the entire window reloading, verses rerendering individual components only. Im building a site with gatsby/react and babylonjs, and just trying to wrap my head around the underlying concepts. Thanks.
What the browser does is somewhat undefined. You give it HTML elements, it somehow draws them on the screen. How it optimizes that process is undefined, all that's defined is what the results are kind of supposed to be like. I say "kind of" because even a simple element like <p>Hello world</p> will be rendered differently on different browsers and differently on the same browser on different OSes or in the same browser on the same OS but with different OS settings etc..
In general the browser builds a tree of nodes (the elements and their contents) called the DOM. It then walks that tree and builds whatever it needs to apply the CSS and then render those elements. Most browsers would try to cache data at various points in that process so that if something changes on the page they don't have to compute everything from scratch. Example might include they generate a glyph (The pixel for a letter), store those pixels somewhere, next time they need to draw the letter at the same size they can just use the pixels they already generated instead having to rasterize that letter from the font definition.
does the browser repaint specific elements without repainting the whole screen?
That's up to the browser.
Does a a reflow always refresh the whole screen?
That's up to the browser. If the browser has way to figure out it only has to compute a partial reflow of some branch of the tree then it might not have to refresh the whole screen.
What exactly is the difference between what happens when you manually refresh the window with a refresh button, verses what reflow or repaint?
Refreshing a window is like killing a program and re-running it from scratch. All the data has to be reloaded either from the network or from the cache, the text gets parsed into elements, etc..
Reflow is computing where all the elements belong, where words or elements wrap, what size they are.
Repaint is drawing the elements. You can repaint without reflow.
how a webGL code animates on a canvas element
A canvas is just a rectangle of pixels, similar to an <img>. The difference is you can get one of several APIs to affect those pixels ("2d", "webgl", "webgl2", "webgpu", ...)
When you change those pixels the browser knows that <canvas> element needs to be re-drawn. How it re-draws it is up to the browser but at does have to at least follow the rules of the spec so for example a <canvas> like pretty much all elements, has CSS applied (it could have border, a background image/color/pattern, rounded corners, etc....). Elements are composited on top of each other so you might have elements in front of the canvas, you might have elements behind the canvas.
Like I said above, what the browser does to draw the elements is undefined but you can certainly imagine that if it can figure out the only thing that changed is the canvas's content, and there are no elements in front of the canvas, and there is nothing behind the canvas, and the canvas is opaque, then it could, potentially, just re-draw the canvas area only.
That situation is rare though. For example, most three.js examples have text at the top positioned over the canvas (the title of the example). Many also have an FPS meter. Some have a drop down UI. All of that is drawn over the canvas so at a minimum, the new contents of the canvas have to be drawn into the window and then those other elements have to rendered on top of that.
Again, how that, happens is up to the browser. It could use software rendering to draw those elements pixel by pixel, or it's possible it has stored the contents of those elements in textures and draws them as quads on top using the GPU.
how React changes elements on a screen, without the whole screen reloading
I'm not sure what you mean by reloading. React keeps its own "virtual DOM". It then tries to apply the changes in the virtual DOM to the actual browser DOM. If there are no changes needed to some elements those elements will not be affected.
From the POV of the browser, nothing is different. All the browser sees is the DOM. If you make changes to the DOM (using React or anything else), then, once your current event exits, the browser will schedule a task to walk the DOM and re-draw the page (using optimizations to re-compute/re-draw less is up to the browser).
I have an IOS application designed for ipad. In one page, I display a report to the user and the report requires 5000 UILabels to be rendered on the screen inside a UIScrollView. This causes application to crash due to being out of memory. I know that UITableView has the functionality for loading content on demand. How can I make scroll view render only certain content and as the scrolling happens remove the content that got invisible and add the content that should be visible?
Is there any way you can reconfigure it to use a table view with custom rows, perhaps rows that consist of several labels? That model supports load on demand and resource reuse in a very natural way...
Perhaps you can be more specific on your screen layout?
You should re-cycle (i.e., reuse) the labels just like a table view recycles its table cells. This is sometimes referred to as "tiling" subviews. Tiling allows you to display more than will fit into memory.
I recommend watching WWDC 2012 Session 104. This session's tutorial creates a photo app that tiles image views in a UIScrollView. Although the photo app scrolls pages of content, rather than a grid of items, I think the video could be relevant to your app.
Here's a very brief overview of the tutorial applied to your specific case:
(1.) declare iVars that keep track of your labels:
NSMutableSet *recycledLabels;
NSMutableSet *visibleLabels;
(2.) implement a method that fetches a re-usable label:
- (UILabel *)dequeueRecycledLabel;
(3.) implement a method that does the tiling:
- (void)tileLabels; // this will add/remove labels from the scroll view
(4.) set your scroll view's delegate and call tileLabels in the scrollViewDidScroll: delegate method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self tileLabels];
}
The WWDC video will help you fill in the details, which I think are applicable to your case. However, you will have to do plenty of improvising in order to make it work for your specific case. This may not be easy; but its doable.
At the end of the video, tiling with CATileLayer is discussed. I'll be honest, I didn't understand that part. But I don't think it's applicable in your case because you're not displaying large images.
I finally implemented dynamic content loading. The method I implemented is scrollViewDidScroll.
Inside this method I determined the direction of scroll by the following
bool isUp = (currentOffset.y > lastScrollOffset);
Then I determined the visible content rectangle by the following.
CGRect visibleContentRect;
visibleContentRect.origin = scrollView.contentOffset;
visibleContentRect.size = scrollView.bounds.size;
Then I had an array of View Elements and each knew its place in the scroll view because of their frame being set. Long story short, each time scroll happened, I determined the views whose frame either intersected or contained by visible content frame. I added those views to the scroll view. I also determined the ones that disappeared and removed them from scroll view and I also set those views to nil and recreated them. Once [scrollView addSubview:view] method is called, then view gets more space in the memory because it gets visible. [view removeFromSuperView] method doesn't deallocate that space. That's why setting the view to nil and recreating it is necessary.
I have a RichEditControl with a given width and height. It's usually a one page document, but sometimes documents can get longer than that. When that happens, the RichEditControl adds a page to it underneath the current one, and a vertical scroll bar to navigate both.
Is there a way to make the document show only one page at a time, so I see Page 1 by default until I write enough to get a page jump, and then I only see page 2 in screen?
This would probably require some sort of pagination, which I imagine is not built-in, so my derived question is:
Since there is no ability to re-size control based on content size (source), would it be better to just count the number of pages, and make the RichEditControl height a multiple of that number? Since this is all inside a bigger ScrollViewer, I'm trying to avoid more inner scroll bars.
I am new in WPF if there is something wrong please co-operate.Here i require some idea from experts.
I am working on one application in which i have to show some content on WPF form after filling the fields present on the form.On the same form i also have a print option.
Check this image.This is my form here part in the red block is generated at runtime.When i click on the print button it only show the visible part on the paper and skip the remaining part.
Problem :
How i can move the remaining part of the form which is under scroll to next page when i click on print.
For example in the given image we can see only 2 bulls eye completely and next 2 partially.How i can shift this remaining part to next page only when i click on print.
The answer is quite easy : don't rely on your window to do the printing, but build the visual you want then print it.
For instance, you must have a function that creates dynamically the circles and so on, then adds them to a Panel. What you might do is to print the Panel.
Or if you prefer, you might build Dynamically a new window, where you put all the Data you want printed as you want, then print the window. The advantage of this method is that it is more flexible for the content (if you want a header/footer) and also you can watch the content easily for debug. Note that even if the Window content is dynamic, you can have a base window for printing that avoids you to do too much xaml with code (expl : you might have TextBox bound to a PrintTitle property that you setup in the constructor of the Print Window...).
Notice that visual that were not rendered on screen will not print. Be sure, to avoid the common issues, to have a look at this article from this great site, switch on the code, here :
http://www.switchonthecode.com/tutorials/printing-in-wpf
Edit (reply to the question in comment):
1) If you have fixed number of bulls eyes, just make one Window for that number and Print it, this is waaaay easier.
2) To put Visuals in pages instead of rows, you'll have to rely on page Width/Height. What matters is the size of your control vs size of page. In the example, they build (in OnRender) Controls having LineHeight, LineWidth as size. Do the same : Try to put as many line of control as you can such as
(Control Height + margin )*NumberOfControlPerPage < Page Height.
Then you have to change OnRender to render controls instead of Rows made with rectangle+text. Pack your controls two by two in Horizontal StackPanels Then pack those StackPanel into a vertical StackPanel, then render. You have to keep track for each page which control was rendered last, then resume rendering at the following control.
Please follow this link.This is the basic which i got after searching in web world.Using this basic detail you can do any thing with print in WPF
I've been trying to get a section of my TabBarController to go fullscreen for a while but still can't figure out this 1 last piece.
So I'm able to put the UIViewController behind UINavigationBar using the code below.
self.navigationController.navigationBar.translucent = YES;
self.wantsFullScreenLayout = YES;
Also able to hide the UINavigationBar & TabBarController using the code below.
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.tabBarController.tabBar setHidden:YES];
However, my UIViewController's height still wouldn't extend behind where the TabBarController is before I hide it. So it looks as though there is a blank space below.
Image attached.
I tried changing self.tabBarController.view.frame and bound. Still doesn't do it. Seems like something is preventing it to cover that bottom portion.
How can I achieve that?
Thank you,
Tee
UITabBarController is not designed to allow its subview to go "behind" the tab bar, probably because a tab bar cannot be translucent. And although [self.tabBarController.tabBar setHidden:YES] does hide the tab bar, it doesn't tell the UITabBarController to lay out your view in the space that is normally occupied by the tab bar. In fact, there is no really supported way to do this.
OTOH, it is easy enough to reposition the tab bar manually if you are willing to risk things breaking in a future version of iOS. The UITabBarController's view has two subviews: one is the tab bar, and the other is the content view (which contains the view from the currently active view controller). Just resize the content view to occupy the space; you could even animate the tab bar moving off the bottom of the screen if you'd like.