Vaadin's SplitLayout.setSplitterPosition(80) only works the first time; subsequent calls do not seem to respond - vaadin

In Vaadin 12, I have created a button which, when clicked, sets the split layout position to some non-zero, non-100 value, as shown below:
btnHelp.addClickListener(event -> {
log.info("info pressed");
MainApp.sp.setSplitterPosition(80);
MainApp.iFrameHelp = new Html( "<iframe src=\"https://docs.readthedocs.io/en/latest/intro/getting-started-with-sphinx.html/intro/getting-started-with-sphinx.html\"></iframe>");
//btnHelp.setIcon(new Icon(VaadinIcon.INFO_CIRCLE));
});
This works great. However, if I pretend to be a user and, via the Chrome browser, I adjust the split layout (by dragging the vertical layout) such that I "close" (or just reduce the size of) the second vertical "panel", and THEN I click on the button again, it does NOT seem to obey the command to reset the splitter position to 80. It only seems to obey the command on the first call. Is this a bug? If so, is there a workaround? (Or, should I do this differently?)

This is a side effect of https://github.com/vaadin/vaadin-split-layout-flow/issues/50. What happens is basically that the server-side still believes that the split position is set to 80 which makes it ignore the setSplitterPosition(80) call.
You can work around this by using low-level APIs to set the position in a way that bypasses the server's dirty checking logic:
MainApp.sp.getPrimaryComponent().getElement().executeJavaScript(
"this.style.flexBasis='80%'");
MainApp.sp.getSecondaryComponent().getElement().executeJavaScript(
"this.style.flexBasis='20%'");

Related

Unable use a TextField at the bottom of the screen in a LazyColumn

I have this code
setContent {
val items = mutableListOf<Int>().apply {
(1..100).forEach { add(it) }
}
LazyColumn {
items(items) { item ->
TextField("$item", {})
}
}
}
With android:windowSoftInputMode="adjustResize" in my AndroidManifest.xml.
If I click on a TextField at the top of the list, I can enter text fine.
If I click on a TextField near the bottom of the screen, the keyboard appears momentarily, then disappears quickly after, and prevents me from entering text.
How can I enter text when the TextField is at the bottom of the screen? Thanks!
Your keyboard disappears after having appeared for a brief, shiny moment. Here's the reason:
You tap the TextField, it calls it's built-in focus requestor, and requests the focus from the OS by calling appropriate (or inappropriate, who's to say) internal methods, as a result of which, the keyboard pops out (again, built-in mechanism.) and you can type all the more you want... AS LONG AS THE FIELD IS VISIBLE; or in Compose terms, long as the Composable holding the requestor, is in composition.
It should be clear, that once the Composable that owns the focus requestor goes off the screen, it is destroyed (well not every time, there are only certain specific cases when it is destroyed..., but yours is one of them), and when the Composable is destroyed, the focus requestor is destroyed. No focus requestor, no focus owner - the keyboard vanishes.
Now this is really important because you are using a LazyColumn, a lazy Composable, infamous for its merciless slaughtering of the Composables that are no longer visible to the user. HENCE, as long as it is the top (or other "visible") textfield that is in concern, it stays and works as expected. However, the bottom textfield, as the keyboard pops up, goes so much out of the visible bounds, that it gets slaughtered (recycled is the technical term, but what fun is that?), taking away the purpose of the keyboard.
Now, the lazy column, like any criminal, left a clue behind, and didn't notice it, which lead us to catch him red-handed. It is quite interesting, really, to see the column in action.
Now, workarounds include using a column, instead of a lazy column; creating your own lazy column using a custom lazy Composable, and manually handling the heap size for the Composable so the final field doesn't go out of composition.
That's it, you're cured.
Just leaving another answer, since OP didn't verify other purpose of him specifying adjustResize,if whether removing or changing it will be fine, but another solution aside from the mentioned comment about different API version is specifying adjustPan, which worked in my case, either
via AndroidManifest
android:windowSoftInputMode="adjustPan"
or programmatically
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
Same code base but with adjustPan
This issue is fixed in the current alpha version 1.4.0-alpha05
https://issuetracker.google.com/issues/179203700

Prevent automatic show and focus of the 1st window when the 2nd window gets hidden

let firstWin = new BrowserWindow()
let secondWin = new BrowserWindow()
secondWin.hide()
Let's assume there are three active windows. Two of them belong to my application (firstWin and secondWin). The third one is Chrome (or any other application). firstWin is at the bottom of the hierarchy, Chrome in the middle and secondWin on top.
secondWin
Chrome
firstWin
When I call secondWin.hide(), firstWin automatically pops up and gets focused. The result is then:
firstWin
Chrome
Is there any way to prevent that? I would like firstWin to not pop up but stay at the bottom of the window hierarchy when I hide secondWin.
I believe you should be able to listen to a window's focus and/or show events (see https://www.electronjs.org/docs/api/browser-window)
You could then make "a decision" to immediately call hide() on that window. (I suppose there is a chance of it flashing on screen briefly.)
(How to make that decision is a bit tricky; I suppose you could record the time you called secondWin.hide() and use the number of seconds since then to decide... not ideal!)
As another approach, just before calling secondWin.hide() you could look at the current state of firstWin, and if that is minimized or hidden, you could instead call app.hide() (see https://www.electronjs.org/docs/api/app#apphide-macos).
(Unless you always want all windows hidden when one window is hidden, this isn't going to scale very nicely beyond 2 windows, unfortunately.)
The solution that I went with for now is to set the opacity of the window to zero and deactivate mouse events. That would be
secondWin.setOpacity(0);
secondWin.setIgnoreMouseEvents(true);
instead of
secondWin.hide()
You then reverse the settings whenever you want the window to become visible again. It's a bit hacky but works for now. Let's see if anyone finds a better solution. Ideally there would be an event like window-about-to-be-shown, which you can plug into and call event.preventDefault() on.
It's been a while since the last answer but here is how I solved this issue:
setting
firstWin.setFocusable(false)
just before calling
secondWin.hide()
will prevent the first window from getting focused.
After that, you can restore the focusable state again calling
firstWin.setFocusable(true)

How to use TFramedScrollBox correctly with Touchscrolling, if there are Buttons inside?

I have derived a TFramedScrollBox to implement in my component a class which constructs me on a given dimension (x and y) buttons onto the FramedScrollBox. This works fine. Touchscrolling on this object works fine, if the property Touch.Pan is set to true. Then i even can scroll over the buttons and by "touching" or "tapping" the buttons the click event happens right after the touch. This derived component, my component, is used all over the application, because it need to be.
The Problem(s)
The given app is running in fullscreen mode on win 8 systems which is currently necessary for our business. In the above explained situation is not possible to tap the buttons fast after the others, because some click events don't rises. And the logic behind is not necessary. That is one problem... If I switch the form to none fullscreenmode then a touch on different buttons rises the click event immediatly as wished. Now i have discovered that if the above mentioned property Pan is set to false, then even on fullsceenmode every touch click rises the event but now the scrollbox don't scrolls by touch gesture...
Now comes my question in the title...
Ps. if wished i can send a simple sample...

TwebBrowser Zoom/Gesture is not working for firemonkey/iOs in XE4 when open a pdf file

I want to display PDF within iOS application, so far the only way I find is open it in TwebBrowser.
A.It is displaying in "fit to page width" zoom as default
B.There is no "zoom" function
WebBrowser1.Navigate(file://mypdf.pdf')
How to
I want to change the zoom after open the file (My solution encounter q#2)
Make the zoom work (My solution encounter q#3)
Make the gesture as work just like web page
For #1:
I chagne WebBrowser1.height/width in run-time, it will auto scale(zoom?) as "Fit to width".
Yes it works, and vertical scroll bar works with a flaw - it will not bounce back on edge -> you can scroll all the way down..
Neither the horizontal scroll, not reacting at all....
*This is because the pdf is A4, not sure what will happen for a landscape style
For #2:
Beside using button clicks to zoom, I add a gestureManager.
Then add Form1.ongesture just like the "iOS Interactive Gestures - Image Zoom" example.
Yes it works, but same thing - no vertical bounce, no horizontal scroll.
*ScrollBox does not work, it will not work with any thing has a build-in vert/hori scroll bars
For #3
:
I go even further, write control for up/down/left/right
Change WebBrowser1.Position.X/Y and WebBrowser1.height/width to make it looks like "scrolling"
Yes it works... but two custom gesture controls are making it really hard to control
(EventInfo.Distance and EventInfo.X/Y, those 2 controls are kinda overlaping to eachother if you run in iPhone)
The wosrt part is, the WebBrowser1 will be on top of ANY compenment, regardless parent/child structure .
The second worst part is the limitation of margin is hard to code, somehow it can always scroll over the limit.....
I "feel" if changing the zoom on/after open, and make it open with both vert/hori scrool bars visible.
Then the horizontal bar should work -> i only need to deal with zoom -> pretty close to prefect.
Of course the best way is to make it work like a web page, like
WebBrowser1.Navigate('http://www.embarcadero.com/') -> both scrollbars works, zoom work.
but...maybe need service pack N for this?
I appreciate for any ideas or code answers.
This damned monkey is on fire and its always hard to find an answer from it.
An article was posted today on The Hacker's Corner called Getting TWebBrowser on iOS to zoom. It suggests a one-line fix to the FMX.WebBrowser.iOS.pas unit. Does this help?
It was a bug, and fixed in the XE4 update.

System tray progress indicator not visible only on panorama page

I'm using Jeff Wilcox's solution for a global progress indicator. All hooked up simple and is working great except for a panorama page I have. The problem is that the Progress Indicator is not visible at all and it's only on this one page.
All of my calls that go through my data service are using the same wrapper that sets IsLoading = true so I've verified this is working. I've also added a Thread.Sleep in there to make sure the call wasn't just returning too quickly before setting IsLoading = false.
Is there anything different about a panorama control that would hide it? I was setting the background to an image, but I pulled that and made sure the main layout grid background was set to transparent just in case.
Is there anything else that should be set in xaml to make sure this is visible?
*Please note this is not the old PerformanceProgressBar control
Yes, there is something in the XAML, and you might kick yourself if you don't have it set (happened to me several times) check this property:
<phone:PhoneApplicationPage
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:SystemTray.IsVisible="True">
Also make sure that your progress bar actually has room to display. Progress bar takes 32 pixels off the top, so generally speaking you want your content to occupy only 768 pixels in height.
I believe that by default when you create a Panorama page using visual studio, the height is set to 800, and SystemTray.IsVisible is set to false.

Resources