Make KenBurnsView fit and fill given area - android-kenburnsview

My App uses KenBurnsView (wonderful piece of code, thanks!), and it works well with ScaleType.FIT_CENTE mode, but some users just prefer to see the whole, non cropped image instead (non moving in that case), which works pretty well with standard ImageView, but fails miserably with KenBurns:
if (XenoAmp.getWpsCover()) {
final KenBurnsView caly = (KenBurnsView) widok.findViewById(R.id.tlo);
if (XenoAmp.getCoverFill()) {
caly.setScaleType(ScaleType.FIT_CENTER);
} else {
caly.setScaleType(ScaleType.CENTER_INSIDE);
caly.pause();
}
}
What happens with Ken is: he stays small and sticks to upper left corner of parent view. How can I fix that without replacing it with standard ImageView?

You can take two different approaches:
Use a standard ImageViewtogether with KenBurnsView and switch visibilities according to what your users want to see.
Write your own TransitionGenerator that doesn't do any transition at all. You can find some information about how to do it here: Define zoom/pan start position with KenBurnsView
IMO, the former approach is much simpler and makes more sense.

Related

Win32 segmented, double buffered console

Why do I even bother with this? Well, it's a pretty handy debug tool for large programs.
The concept is the following: I would like to split the console area into two parts:
- the upper part double buffered (I already know how to do this)
- the lower part functioning as a regular standard output (as in: scrolls, responds to scroll control, etc.)
An example image:
What I would like to achieve is to keep the persistent part always on top, while the scrollable part indeed scrolls, and responds to the scroll control on the right.
I have some knowledge of the required functions (CreateConsoleScreenBuffer, SetConsoleActiveScreenBuffer, SetConsoleCursorPosition, etc.), but I'm struggling with the implementation.
I know it is possible, because I saw it in other programs. Therefore I would like to ask for suggestions on how to do this right.

Smooth animation of three shapes in SciLab

This answer provides a nice way to make smooth animations in SciLab. I now have to write a simulation of a body attached to two strings (and therefore its movement regarding some additional forces).
The code in the link works well to render movement of a single point and, unfortunately, I didn't manage to make an animation of a point + two lines using this method. If someone is curious, I tried this code to do it:
frametime=(tk-t0)/Nt//defining the waitnig time
plot(Y(1,1),Y(2,1),"o")//plotting the point
plot([0;Y(1,1)],[0;Y(2,1)],style=1)
plot([D;Y(1,1)],[0;Y(2,1)],style=1)//plotting the two initial lines
h1_compound = gce();
h_point=h1_compound.children
h_point.mark_size = 20;
h_point.mark_background = 2;
h_line1=h_compound.children
h_line2=h_compound.children
//h_axes = gca();
//h_axes.data_bounds = [0,-1;10,1];
realtimeinit(frametime);
for i=1:Nt//my vectors have Nt points
realtime(i);//wait "frametime" seconds before drawing the new position
h_point.data=[Y(1,i),Y(2,i)];
h_line1.data=[[0;Y(1,i)],[0;Y(2,i)]]
h_line2.data=[[D;Y(1,i)],[0;Y(2,i)]]
end
The question is: is there any way to make an animation of three shapes without making axes blink (as it is with the window refreshment) or other wierd stuff?
Since you didn't create a MCVE I can't reproduce your exact problem. But you may try to add drawlater(); before, and drawnow(); after your data modification to see if it does help with blinking or not.
Or you may get much better looking result by saving your plots in every round with xs2gif and assemble the animation with another gifmaker progam (there are free online sites to do this, however with some limitations). If you need to present your result, you should do this step anyway.

Why might the scaling of SetWindowExtEx be just wrong?

I am trying to scale images/text etc using MM_ANISTROPIC and what I've done is the following (by the way if the syntax is a little weird, it's originally from delphi so treat the following as pseudocode)
I would expect the following code to produce a rectangle that is 70% of the width of the PaintBox and 30% of the height, yet it doesn't, instead it it noticeably too small.
SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,100,100,0);
SetViewportExtEx(hdc,70,30,0);
Rectangle(hdc, 0,0,PaintBox.width-1,PaintBox.Height-1);
if, on the other hand I change the code so that the SetWindowExtEx has 91 instead of 100 as its parameters (as shown below) then it works, which makes no sense to me at all...
SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,91,91,0);
SetViewportExtEx(hdc,70,30,0);
Rectangle(hdc, 0,0,PaintBox.width-1,PaintBox.Height-1);
My sanity test case was to add the following pseudocode
SetMapMode(hdc,MM_TEXT);
DrawLine(hdc,Round(PaintBox.width*0.7),0,Round(PaintBox.width*0.7),PaintBox.Height-1);
DrawLine(hdc,0,Round(PaintBox.height*0.3),PaintBox.width-1,Round(PaintBox.height*0.3));
I would have expected this to overwrite the lower / bottom edges of my original Rectangle but it does not unless I uses that 91,91 SetWindowExtEx.
Can anyone duplicate this?
FURTHER EDIT: Here is my exact original code I had given pseudo code before to make the question more accessible to non-delphi users but one of my commenters wanted full code to see if my contention that it was a delphi quirk was true or not.
The entire project consisted of a VCL form with a rectangular paintbox dropped on it centered so there was space all around it, and its onPaint event was set to the code below resulting in this image::
procedure TForm11.PaintBox2Paint(Sender: TObject);
var
hdc:THandle;
res:TPoint;
procedure SetupMapMode;
begin
SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,100,100,0);
SetViewportExtEx(hdc,70,30,0);
// These lines are required when we're painting to a TPaintBox but can't be used
// if we're paiting to a TPanel and they were NOT in my original question but only
// got added as part of the answer
// SetViewportOrgEx(hdc,PaintBox2.Left,PaintBox2.Top,#ZeroPoint);
// SetWindowOrgEx(hdc,0,0,#ZeroPoint);
end;
begin
//draw a rectangle to frame the Paintbox Surface
PaintBox2.Canvas.Pen.Style:=psSolid;
PaintBox2.Canvas.Pen.width:=2;
PaintBox2.Canvas.Pen.Color:=clGreen;
PaintBox2.Canvas.Brush.Style:=bsClear;
PaintBox2.Canvas.Rectangle(0,0,PaintBox2.Width-1,PaintBox2.Height-1);
PaintBox2.Canvas.Brush.Style:=bsSolid;
//initialize convenience variable
hdc:=PaintBox2.Canvas.Handle;
SetTextAlign(hdc,TA_LEFT);
//as doing things to the PaintBox2.Canvas via Delphi's interface tends to reset
//everything, I'm ensuring the map mode gets set **immediately** before
//each drawing call
SetupMapMode;
/// Draw Text at the bottom of the PaintBox2.Canvas (though as it's mapped it
/// SHOULD be 1/3 of the way down and much smaller instead)
TextOut(hdc,200,PaintBox2.Height-PaintBox2.Canvas.TextHeight('Ap'),'Hello, World!',13);
PaintBox2.Canvas.Pen.Color:=clblue;
PaintBox2.Canvas.Brush.Style:=bsClear;
//ensure it's set before doing the rectangle
SetupMapMode;
// Redraw the same rectangle as before but in the mapped mode
Rectangle(hdc, 0,0,PaintBox2.Width-1,PaintBox2.Height-1);
PaintBox2.Canvas.Brush.Style:=bsSolid;
//reset the map mode to normal
SetMapMode(hdc,MM_Text);
//draw text at the "same" position as before but unmapped...
TextOut(hdc,200,PaintBox2.Height-PaintBox2.Canvas.TextHeight('Ap'),'Goodbye, World!',15);
//Draw lines exactly at 70% of the way across and 30% of the way down
//if this works as expected they should overwrite the right and bottom
//borders of the rectangle drawn in the mapped mode
PaintBox2.Canvas.Pen.Color:=RGB(0,255,255);
PaintBox2.Canvas.MoveTo(Round(PaintBox2.Width*0.7),0);
PaintBox2.Canvas.LineTo(Round(PaintBox2.Width*0.7),PaintBox2.Height);
PaintBox2.Canvas.MoveTo(0,Round(PaintBox2.Height*0.3));
PaintBox2.Canvas.LineTo(PaintBox2.Width,Round(PaintBox2.Height*0.3));
end;
Okay, I don't know WHY the following is necessary -- it may be a Delphi quirk, the fact that I'm using a TPaintBox with is a TGraphicControl rather than a Component, or if I'm missing out on some fundamental concept on how this whole mapping mode works, BUT if I add the following code:
ZeroPoint:=TPoint.Zero;
SetViewportOrgEx(hdc,PaintBox1.Left,PaintBox1.Top,#ZeroPoint);
SetWindowOrgEx(hdc,0,0,#ZeroPoint);
Then it all displays as expected. Anyone have any explanations as to why this is necessary?
EDIT: Okay, I've got a PARTIAL explanation. It has to do with the control I was painting on being a TPaintBox, which is a TGraphic control rather than a TWinControl. To wit:
TGraphicControl is the base class for all lightweight controls.
TGraphicControl supports simple lightweight controls that do not need the ability to accept keyboard input or contain other controls. Since lightweight controls do not wrap Windows screen objects, they are faster and user fewer resources than controls based on TWinControl.
As such, although they APPEAR to have a separate canvas, I have this sneaking feeling that they are really sharing the form's canvas which is why, when I switched to a TWinControl descendant, which DOES own its own Windows DC, then the display worked as expected without setting the ViewpointOrg.
So it was a Delphi quirk after all...!

Mobile webapp performance issues

I’m building a mobile web application, and even though I’m still in a prototyping kind of the process, I’m having a hard time fixing certain performance problems.
The application itself (works all smooth in desktop browsers, but significantly sluggish in Mobile Safari): Hancards webapp prototype. You may login as mifeng:wangwang or create a new user.
The overall clumsy performance could be tolerable though, except for one thing: the browser simply crashes (!) when you open a set page, tap ‘view’ (enlarge all cards) and then try to go back to the previous page.
The code that gets executed when ‘view’ is tapped is this (very sluggish by itself as well; any way to improve it?):
if ($(this).hasClass('big')) {
$('.card').unwrap().removeClass('big flippable').addClass('small');
$(this).removeClass('big');
}
else {
$('.card').wrap('<div class="bigCardWrap" />').removeClass('small').addClass('big flippable');
$(this).addClass('big');
}
And another thing, a pretty weird bug. Very often the ‘word of the day‘ block won’t display the text node for the last element (<div class="meaning">), even though it’s in the code. The text will not show unless you ‘shake’ the DOM anyhow (unticking and ticking back one of the associated CSS properties can also achieve that). This happens in both desktop and mobile Safari browsers.
The code that writes it in there is this:
// While we are here, also display the Word of the day
$.post('ajax.php', {action: 'stuff:showWotd'}, function(data) {
// Decode the received data
var msg = decodeResponse(data);
// Insert the values
$('.wotd .hanzi').text(msg.content[0]['hanzi']);
$('.wotd .pinyin').text(msg.content[0]['pinyin']);
$('.wotd .meaning').text(msg.content[0]['meaning']);
});
I don’t expect you to advice me on how to fix the performance of the whole application (I will probably have to revise the overall scope of the project instead of trying to find workarounds), but I at least would like to see how to solve these two problems. Thank you!
The only performance issue I see in the script is the wrap/unwrap calls - adding and removing elements from the DOM tends to be fairly slow, and you can probably get the same effect by always having a wrapper element and changing its class rather than adding or removing it.
However, the performance issues you are seeing are most likely in your css:
3D transforms can be much faster than 2D due to hardware acceleration. It looks like you already have this, though you do need to be careful about which elements it is applied to
Shadows have real performance issues, especially when animated. Removing them will probably fix most of the slowness.
Rearranging background images can help - A single background image under transparent pages is faster than having a background image for each page.

Localizing a modern xib-based Mac application

Ours is an open-source Mac application localized by volunteers. These volunteers will do their work on special localization builds of the software (with unstripped nibs), then send us the changes to integrate into the original xib and strings files.
The problem is that, while there is a way to integrate string changes without blowing away previous size changes, I can't see a way to integrate new string and size changes (as when we add or replace views).
The only way to do both that I can see is for localizers to work directly with the original xibs and send us diffs. That means they have to download the entire source code, not just a localizable version of the release, work in Xcode as well as IB, and either run the diff command themselves (per xib) or install and use Mercurial.
Is there any better way for a xib-based application?
UPDATE January 2014: Apple’s ‘autolayout’ code combined with their ‘Base’ localization stuff took most my ideas and improved on them. I recommend against using my old tools that I talk about in this answer. But, also, man was I right!
I strongly strongly STRONGLY recommend against frame changes in localizations. I know this runs counter to Apple's advice, but there are SO MANY problems with allowing frame changes - you end up with a billion edge cases.
Imagine you have 10 XIBs in your app, and you support 12 languages. You've got 120 different layouts to support, now. You just can't do this.
Change the strings, leave the views where they are. Make 'em bigger in ALL languages, if you need to. It sounds like this shouldn't work but it does. (I won three Apple Design Awards with an app that's localized in 10 or so languages this way.)
Specifics:
For radio and checkboxes, just let them extend far to the right, beyond the last English character. That also provides a nice big landing area for imprecise mousers.
For buttons, they should be wide anyhow, because it never looks good to have text cramped in the middle of the buttons.
For titles on tableview columns, you should autosize when you load 'em up, if needed.
For explanatory text, you should have some extra space to the right, and maybe an extra line. It just makes the English version of the XIB seem less cluttered. Sure, the Germans are going to see a slightly tighter XIB, but, hey, they're Germans -- they're probably used to that. There's probably even a German word for it. "Deutscheninterfakkenclutterlongen."
If a text field is centered, just add equal space on both sides. There's no reason not to.
I've combined this with scripts that suck all the strings out of my XIBs and put them in .strings files, and then dynamically put the strings back at run-time, so anyone can localize my app without any special tools. Just drop in a bunch of .strings files and run it!
Blog post including full source: [Lost in Translations]¹.
I confess that I'm not all that familiar with the process of localizing Mac apps. But I did run across a script that's part of the Three20 iPhone library that seems like it might be useful: diffstrings.py is a Python script that "compares your primary locale with all your other locales to help you determine which new strings need to be translated. It outputs XML files which can be translated, and then merged back into your strings files."
EDIT: As a companion to Wil Shipley's answer to this question, I'll add a link to a blog post he just wrote that goes into more detail about localization, and provides some of the tools that he's built to ease the process.
Where I used to work, we had this issue as well. Our app was getting translated into 10 different languages.
At first, we tried doing what Wil suggested, which is to make everything super wide and fit in every language. Unfortunately, "online backup" might be pretty short in English, but in other languages (especially Spanish), it's really long ("copia de seguridad" just means "backup"). Widening our UI made everything look pretty terrible.
One day, I was playing around with some Core Animation stuff and discovered the CAConstraint class. CAConstraint is basically a way to define a layout relationship between two CALayers. You give one layer a name (like "layerA") and then say "layerB is constrained [in such-and-such a way] to a sibling layer called layerA". Then, whenever the layer named layerA is repositioned or resized, layerB automatically moves as well. It's really neat, and it's just what we were looking for.
After a couple of days of work, I came up with what is now CHLayoutManager. It's basically a re-make of CAConstraint and friends, but for NSViews. Here's a simple example of how it works:
CHLayoutConstraint * centerHorizontal = [CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMidX relativeTo:#"superview" attribute:CHLayoutConstraintAttributeMidX];
CHLayoutConstraint * centerVertical = [CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMidY relativeTo:#"superview" attribute:CHLayoutConstraintAttributeMidY];
[aView addConstraint:centerHorizontal];
[aView addConstraint:centerVertical];
This will keep aView centered in its superview, regardless of how the superview is resized. Here's another:
[button1 setLayoutName:#"button1"];
[button2 addConstraint:[CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMinX relativeTo:#"button1" attribute:CHLayoutConstraintAttributeMaxX]];
[button2 addConstraint:[CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMaxY relativeTo:#"button1" attribute:CHLayoutConstraintAttributeMaxY]];
[button2 addConstraint:[CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeWidth relativeTo:#"button1" attribute:CHLayoutConstraintAttributeWidth]];
This will keep button2 anchored to the right edge of button1, as well as keeping button2's Y position and width the same as button1's.
Internally, CHLayoutManager uses an NSValueTransformer to calculate the new positioning information. Some of the CHLayoutConstraint initializers accept an NSValueTransformer, so you can create arbitrarily complex layout manipulations.
We used this for constraining and laying out the entire UI, and then doing all of the localization in code (and subsequently calling -sizeToFit, with some modifications). Our UI would just flow into its final layout. It turned out to be extremely convenient. We'd just package up our .strings files, send them off to the translators, and then drop them in to place when we got them back, and our app would instantly be localized for that language.
CHLayoutManager isn't perfect. It doesn't resolve conflicts, but simply applies constraints in the order they're added. So you can constrain (for example) the MinX of a view 42 different ways, but only the last one will be used. Also, if you constrain the MinX and the MaxX, they'll also be applied in the order they're added and will not end up stretching or shrinking the width. In other words, constraining one attribute of a view will not affect the other attributes. It's compatible with 10.5+ (GC and non). However, due to some changes in Lion, it's unlikely that I'll address the shortcomings.
Despite these shortcomings, it's an extremely flexible framework, and (IMO) some pretty nifty code. (Plus, I swizzle -[NSView dealloc]! Yay!)
Update
Now that AppKit has this same functionality (via NSLayoutConstraint), I recommend using that system instead of CHLayoutManager. It is far more robust.
Bear in mind that XIB files are merely XML files in an obscure format, so you can translate those easily enough, provided that you can find what strings there are there to translate in the first place. For example, here's the snippet that creates a button called Jenson:
<object class="NSButtonCell" key="NSCell" id="41219959">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents">Jenson</string>
...
</object>
So you can get that string translated and then substitute occurrences of it in the XIB with your translated value. In order to verify it's working as expected, you could change the language to use random keys instead (like BUTTON_TITLE) which will make it easier to spot when one's missing.
However, the positions/sizes of the items are fixed, so you can have titles that overflow the space given in a different language. That's one of the reasons why Macs have separate XIB files for every language, to allow adjustments to be made on a language-by-language basis, however difficult it is to maintain.

Resources