Automatically re-sizing the JavaFX 2 HTMLEditor control - user-interface

I'm trying to make an editable control using the HTMLEditor ( I'd like a rich-text pane like Swing's JEditorPane or JTextPane but it seems I need to wait a couple of years for that ). I want to have the user type in text and the control grows to suit. I have tried catching an event when the scroll-bar appears and increasing the size until it disappears but I can't work out how to wait until the JavaFX thread has actually re-sized the control on its parent.
There's probably a better way to do it than that... any ideas? Any ideas how to reduce it if text is removed?
TIA Mike Watts

For the edit control, use a WebView with contenteditable set to true like this example or a customized HTMLEditor.
Interact with it using the Java/JavaScript bridge similar to this editor. You can script the WebView using JQuery. Run a Timeline which polls the edit control's text dimensions using a JQuery dimension query script and adjust the control size appropriately.

[side note: I've added this as an answer even though it is just the details from jewelsea's - I couldn't format the code when replying as a comment].
This is what has worked to a certain extent:
in the html of the WebView component, added a tag <div id='measured'> around all of the text blocks
added a handler to the WebView using setOnKeyPressed and that calls checkHeight()
private int lastOffsetHeight;
private void checkHeight() {
int newHeight = (Integer)webview.getEngine().executeScript(
"document.getElementById(\"measured\").offsetHeight;") + 14;
if (newHeight != lastOffsetHeight) {
lastOffsetHeight = newHeight;
webview.setPrefHeight(newHeight);
}
}
This is not too bad, main problem is that if all of the text is deleted then the WebView component deletes the div. As jewelsea mentioned, JQuery might be a better solution but I'll update this if I ever fix the problem of including the library ;-)

Related

Unity UI not working properly ONLY on Windows

I have been working on figuring out what is going on with my game's UI for at least two days now, and no progress.
Note that this is a mobile game, but I was asked to build for Windows for visualization and presentation purpose.
So the problem is that when I run my game on the Unity Editor, Android, iOS and Mac platforms the UI works just perfect, but then when I run the game on Windows the UI still works fine UNTIL I load a specific scene.
This specific scene is a loading screen (between main menu and a level) when the level finished async loading, a method called MoveObjects is called in a script in the loading screen, to move some objects that where spawned in the loading screen scene into the level scene (this is not the issue though, since I already try without this method and the problem on the UI persist).
Once the logic of this MoveObjects method is done, a start button is enabled in the loading screen, for the player to click and start playing (I did try moving the start button to the level scene, since maybe it not been a child of the currently active scene could be the issue, but the problem still persist). Is at this point that the UI is partially broken, what I mean with this is, that I can see buttons (and some other UI elements like a scrollbar) changing color/state when the mouse moves over them, but I cannot click on them anymore (the button wont even change to the pressed state).
Also note that I tried creating a development build to see if there was any errors in the console, and I notice that this problem is also affecting the old UI system, so I was not able to interact with the development console anymore.
Also also, note that if I grab and drag the scrollbar before this issue appear, and I keep holding down on the scrollbar until this happens, the mouse gets stuck on the scrollbar, meaning that I cannot interact with the UI anymore, but the scrollbar will still move with the mouse.
I already check that this things are not the source of the problem:
Missing EventSystem, GraphicRaycaster or InputModule.
Another UI element blocking the rest of the UI.
Canvas is Screen Space - Overlay so there is no need for a camera reference.
I only have one EventSystem.
Time.timeScale is 1.
I am not sure what else I could try, so if anyone has any suggestions, I would appreciate it. Thanks.
P.S: I am sorry to say that I cannot share any code or visual material or examples due to the confidentiality.
A major source for a non-working UI for me has always been another (invisible) UI object blocking the raycast (a transparent Image, or a large Text object with raycast on).
Here's a snippet I put together based on info found elsewhere, I often use it to track objects that are masking the raycast in complex UI situations. Place the component on a text object, make sure it's at least few lines tall, as the results will be displayed one under another.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
public class DebugShowUnderCursor : MonoBehaviour
{
Text text;
EventSystem eventSystem;
List<RaycastResult> list;
void Start()
{
eventSystem = EventSystem.current;
text = GetComponent<Text>();
text.raycastTarget=false;
}
public List<RaycastResult> RaycastMouse(){
PointerEventData pointerData = new PointerEventData (EventSystem.current) { pointerId = -1, };
pointerData.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerData, results);
return results;
}
void Update()
{
list= RaycastMouse();
string objects="";
foreach ( RaycastResult result in list)
objects+=result.gameObject.name+"\n";
text.text = objects;
}
}

Change the colour of WinJS.UI.BackButton (Win 8.1 back button)

I'm getting started with Windows 8 App development using WinJS. I'm using the Light UI theme but I have set up a darker area on the left of the page (where the black back button is) and the issue is: you can't see the button.
I've trawled through the MSDN pages and the most I could find is how to style a button which doesn't actually explain how to change the colour of an actual asset.
http://msdn.microsoft.com/en-us/library/windows/apps/jj835822.aspx
I've also tried adding: win-ui-light and win-ui-dark classes to the button with no success.
I wondered if someone could point me in the right direction?
Many thanks for your time
Chris
First of all you have to delete the link tag that contain UI css by default and add it to document head , Dynamically.see below code :
var uistyle;
// call when your app load or resume.
function onappopen(){
uistyle = document.createElement('link');
uistyle.href = "//Microsoft.WinJS.2.0/css/ui-dark.css";
uistyle.rel = "stylesheet";
uistyle.id = "UIstyle";
document.head.appendChild(uistyle);}
// call when you want to change UI Style.
function UIstyle(UIbool){
if(UIbool=='light'){ uistyle.href = "//Microsoft.WinJS.2.0/css/ui-light.css";}
else {uistyle.href = "//Microsoft.WinJS.2.0/css/ui-dark.css";}}
Like: UIstyle('light'); for light UI in Windows 8 or "UIstyle()" for dark;
I used the DOM Explorer to find the buttons default values and overwrite them. It was the child element that needed to be overwritten: .win-back

DataBinding in Windows Phone is blocking UI threading

I am trying to do the standard - bind a list of data (including images) received from REST API calls in a very quick and smooth manner - a paradox in itself. I have 2 service calls that each take about 2 seconds to complete so I can async/await those, but based on the data returned, I then build other lists (observableCollection) in memory and bind them back to ListBox's in the page.
Problems:
This actual binding seems to lock up the UI thread, how can I asynchronously load my page - listBox by listBox (or even item by item) in a lazy fashion? I'd like to put a placeholder image in place and when finally bound, the placeholder is replaced by the bound image. Any ideas? Frameworks? Tools?
When binding the actual images, the other data in my DataTemplate, actually jumps around the screen while the Image is rendered. It looks terrible... I'd like to be able to, at the very least, bind the image first and then the other controls in the dataTemplate after? Anything that would make it appear a bit smoother would help.
Thanks in advance.
I suspect your problem in (2) will be solved with the placeholder image (assuming that it is the same size as the downloaded images).
I suspect that your "lock up" problem in (1) is that you are calling Wait or Result on a Task returned by an async method. In many cases, this results in a deadlock, as I explain in a recent MSDN article and on my blog.
I think what you really want is a way to start a Task and get a data-binding notification when it completes. I've developed a set of types (TaskCompletionNotifier) that helps out in this situation. Check out the end of my blog post on async properties for a sample. You may also be interested in my blog post on async constructors.
(1) If the list of items is large, binding them all at once will cause some stalling on the UI thread. One fix is to add the items a few at a time and pause so that the UI thread can get a new frame to the compositor before continuing.
public async void AddObjects(List<object> objects)
{
for(int i = 0; i < objects.Count; i++)
{
_myObservableCollection.Add(objects[i]);
if(i % 10 == 0) await Task.Delay(100);
}
}
(2) You should set a fixed width and height on the images in the DataTemplate, so that it does not change as the image is actually downloaded. Alternately, if you can fetch the width and height from your service in the API calls, bind the image width/height to those values before it gets downloaded.

Getting Windows Phone 7 WebBrowser Component VerticalOffset

I want to persist the user's location in the document he or she is browsing, then bring them back to that spot when they return from tombstoning or between sessions.
My first approach was to wrap the browser component in a scrollviewer, but it turns out it handles its own scrolling and the scrollviewer never changes its verticaloffset.
My guess is that the browser component must have a scrollviewer or something like it embedded in it. I need to get the verticaloffset and scroll to an offset.
Any guesses how to get there?
My next approach would be a painful mish-mash of javascript and c# to figure out where they are...
Because of the way the WebBrowser control is built you'll need to track scrolling in Javascript then pass the location to managed code to handle storage of that value.
On resuming you'll need to have the managed code pass the scroll position to a Javascript function to reset the scroll position.
That's the theory but I haven't looked at the funcitonality around javascript scrolling events in the WebBrowser yet. That's the only place I can see possible problems.
Would be good to hear how you get on.
I've accepted Matt's answer, but I want to put in some details here. I'm also going to blog about how I did it once I'm completely done.
Since the WebBrowser component is essentially a black-box, you don't have as much control as I would like. Having said that, it is possible to get and set the vertical offset.
Javascript lets you ask for the value, but different browsers use different variations on HOW to ask. For THIS case I only have one browser to worry about.
First I make a couple of simple javascript functions:
function getVerticalOffset() {
return document.body.scrollTop;
}
function setVerticalOffset(offset) {
document.body.scrollTop = offset;
}
Next I call into the WebBrowser using the InvokeScript method on the browser object.
I'll post an update here with a link to my blog when I get the full write-up done.
I have been writing an eBook reader and had a similar question. Code for setting a scroll position has been easy enough to find.
Code for setting vertical scroll position:
string script = string.Format("window.scrollBy(0,{0});", "put your numeric value here");
wb_view.InvokeScript("eval", script);
Google didn't help much in finding solution for getting the value of current scroll position. Lacking any knowledge in javascript it took me almost two hours to get it right.
Code for getting the vertical scroll position:
var vScroll = wb_view.InvokeScript("eval",
"var vscroll = window.pageYOffset; vscroll.toString();");

UI Automation FrameWork for iPhone

I am exploring the newly exposed framework UI Automation in iphoneOS 4.0. Has anybody tested their application using this framework. I will appreciate any help.
I am trying to test a sample application that just contains a textfield and a button. I have written a script as
UIALogger.logStart("Starting Test");
var view = UIATarget.localTarget().frontMostApp().mainWindow().elements()[0];
var textfields = view.textFields();
if (textfields.length != 1) {
UIALogger.logFail("Wrong number of text fields");
} else {
UIALogger.logPass("Right number of text fields");
}
textfields[0].setValue("anurag");
view.buttons()[0].tap();
The problem is that the value of textfield is not getting set and no button is tapped. When I run the instruments only the view(with textfield and button) appears and then notting is happening.
There is a message in instruments "Something else has happened".
If your main window contains a button and a text field (in this order in the hierarchy) then your first line of code will return you the UIAButton element, so the next line is incorrect, because you're trying to call textFields() on a button.
The first part should look like this:
var view = UIATarget.localTarget().frontMostApp().mainWindow();
var textfields = view.textFields();
if (textfields.length != 1) {
UIALogger.logFail("Wrong number of text fields");
} else {
UIALogger.logPass("Right number of text fields");
}
And in that case I think there are two ways of testing the tap and text field. Like this:
textfields[0].setValue("anurag");
view.buttons()[0].tap();
or like this:
view.elements()[1].setValue("anurag");
view.elements()[0].tap();
And personally I prefer getting objects by using Accessibility Label instead of index. For more information look for a UIAElement Class Reference and take a look here:
UI Automation Reference Collection
All this stuff is gonna work only if the application is made with that accessibility thing (its own accessibility protocol: by tagging all its UI controls in Interface Builder with names, by setting the Accessability label to a unique value for the view). Or if you work with iPhone standard controls.
If the application doesn't contain anything like that, you won't be able to do much with UI Automation and will see only a 320x480 empty canvas.
You can check this link for some more details.
For example, I work on a OpenGL application that was not built with any accessibility tag and I cannot see anything through UI Automation besides a 320x480 empty form.

Resources