How to listen for a keyboard event in dart programming - dart

I'm new to google dart and been trying to learn it for a day now. I'm pretty novice to programming in general and I'm trying to read the documentation; however, I feel a bit overwhelmed.
I would like to know the most proper method of creating a interaction for spacebar here key. When one would push spacebar, it would toggle between function void startwatch() , void resetwatch()
I believe this is the correct documentation page also documentation for keyboardEventController
void main() {
}
void startwatch() {
mywatch.start();
var oneSecond = new Duration(milliseconds:1);
var timer = new Timer.repeating(oneSecond, updateTime);
}
void resetwatch() {
mywatch.reset();
counter = '00:00:00';
}
Any further information needed I'll try to respond immediately. Thnk you so much for your help.

To listen to keyboard events and toggle between startwatch() and resetwatch():
void main() {
var started = false;
window.onKeyUp.listen((KeyboardEvent e) {
print('pressed a key');
if (e.keyCode == KeyCode.SPACE) {
print('pressed space');
if (started) {
resetwatch();
} else {
startwatch();
}
started = !started; // A quick way to switch between true and false.
}
});
}
window is an instance of Window class. It's automatically provided for you.
There's also a handy class called KeyEvent, which attempts to eliminate cross-browser inconsistencies. These inconsistencies are usually related to special keys.

Related

ARCORE: remove a specific renderable by clicking on this renderable

I'm working on a project using Sceneform from ARCore. I develop it base on HelloSceneform example provided by ARCore.
What I wanna do is adding a renderable object by a hit and then delete it when I click on the specific renderable on the screen.
I've tried method AnchorNode.setOnTapListener as following, but it didn't work(no response):
anchorNode.setOnTapListener(new Node.OnTapListener() {
#Override
public void onTap(HitTestResult hitTestResult, MotionEvent motionEvent) {
if(anchorNode.getAnchor()!=null){
arFragment.getArSceneView().getScene().removeChild(anchorNode);
anchorNode.getAnchor().detach();
anchorNode.setParent(null);
}
}
});
I also tried the following method, which causes unexpected close:
Scene scene = arFragment.getArSceneView().getScene();
scene.addOnPeekTouchListener(new Scene.OnPeekTouchListener() {
#Override
public void onPeekTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
Node node = hitTestResult.getNode();
node.setParent(null);
}
});
Is there any method could achieve this feature?
The code below should detect the touch and delete the node.
If you want to have a separate button to delete a selected node you can add a regular button and listener and just use the 'touch' event to select the node you want to delete.
private void handleOnTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
Log.d(TAG,"handleOnTouch");
// First call ArFragment's listener to handle TransformableNodes.
arFragment.onPeekTouch(hitTestResult, motionEvent);
//We are only interested in the ACTION_UP events - anything else just return
if (motionEvent.getAction() != MotionEvent.ACTION_UP) {
return;
}
// Check for touching a Sceneform node
if (hitTestResult.getNode() != null) {
Log.d(TAG,"handleOnTouch hitTestResult.getNode() != null");
Node hitNode = hitTestResult.getNode();
if (hitNode.getRenderable() == andyRenderable) {
Toast.makeText(LineViewMainActivity.this, "We've hit Andy!!", Toast.LENGTH_SHORT).show();
arFragment.getArSceneView().getScene().removeChild(hitNode);
AnchorNode hitNodeAnchor = (AnchorNode) hitNode;
if (hitNodeAnchor != null) {
hitNode.getAnchor().detach();
}
hitNode.setParent(null);
hitNode = null;
}
}
}
The above is extracted from various parts of a VR test application and combined here for a concise example - the full working application source is available here: https://github.com/mickod/LineView
Update - Kotlin version (tested April 2020):
private fun removeAnchorNode(nodeToRemove: AnchorNode) {
//Remove an Anchor node
arFragment.getArSceneView().getScene().removeChild(nodeToRemove);
nodeToRemove.getAnchor()?.detach();
nodeToRemove.setParent(null);
nodeToRemove.renderable = null
}
I know i am late but it may be helpful for someone.
Node you want to remove, first of you have to select that Transferable node by click or touch that node.
TransfarableNode.setOnTapListener this bulit in method serve purpose for us.
After that get node from HitTestResult and than detach node.
Here is the code you can use for selecting and removing node.
transformableNode.setParent(anchorNode );
transformableNode.setRenderable(model_nodeRenderable);
transformableNode.select();
transformableNode.setOnTapListener((HitTestResult hitTestResult, MotionEvent Event) ->
{
Node nodeToRemove = hitTestResult.getNode();
anchorNode.removeChild(nodeToRemove );
});

rxjava and terminating streams

I'm new to reactive programming using rxjava and after going through the simpler examples I'm now trying to figure out how to work with continuous streams. The problem I have with the example below is that the program doesn't terminate after I've taken the 3 elements. My assumption is that I somehow need to unsubscribe to my observable but I don't fully grasp how to terminate the while loop and make the program exit.
I've come across the following post RxJava -- Terminating Infinite Streams but I still can't figure out what I'm missing.
class MyTwitterDataProvider {
/*
This example is written in Groovy
Instance variables and constructor omitted
*/
public Observable<String> getTweets() {
BufferedReader reader = new BufferedReader(new InputStreamReader(getTwitterStream()))
Observable.create({ observer ->
executor.execute(new Runnable() {
def void run() {
String newLine
while ((newLine = reader.readLine()) != null) {
System.out.println("printing tweet: $newLine")
observer.onNext(newLine)
}
observer.onCompleted()
}
})
})
}
def InputStream getTwitterStream() {
// code omitted
}
public static void main (String [] args) {
MyTwitterDataProvider provider = new MyTwitterDataProvider()
Observable<String> myTweetsObservable = provider.getTweets().take(3)
Subscription myTweetSubscription = myTweetsObservable.subscribe({tweet-> println("client prints: $tweet")})
// myTweetSubscription.unsubscribe()
}
}
You must add a check in your loop to see if the observer is still subscribed:
while ((newLine = reader.readLine()) != null && !observer.isUnsubsribed()) {
System.out.println("printing tweet: $newLine")
observer.onNext(newLine)
}

Distinguish between onClick and onDoubleClick on same element to perform different actions in Dart

I want to do the ill-advised and place both an onClick and onDoubleClick on the same element with each type of event resulting in a different action. Specifically on an image, click to advance to the next image, double-click to toggle fullscreen.
Naturally I get two clicks followed by a double-click (though I understand that some browsers only fire one click before the double-click).
I had thought to make it easy on myself and place each event into a buffer (List) - or rather to add the event.type string to a list, then, after a suitable elapse of time, say 250 or 300 milliseconds examine the last item in the buffer and if doubleclick then go fullscreen else advance the length of the list.
I have found that the list only ever has one item, and I have not worked out how to get the timer to work..
Amongst my attempts was this one:
void catchClickEvents(Event e) {
var eventTypes = new List<String>();
eventTypes.add(e.type);
Duration duration = const Duration(milliseconds: 300);
var timeout = new Timer(duration, () => processEvents(eventTypes));
}
void processEvents(List eTypes) {
// just to see what is going on...
print(eTypes);
}
this results in this output printed to the console:
[click]
[click]
[dblclick]
rather than
[click, click, dblclick]
If I slow it down there is a clear delay before those three event types are printed together
So...
The bigger question is
'What is the darty way to distiguish between single and double-click and perform a different action for each?'
The other questions are:
How do I fill a buffer with successive events (and later clear it down) - or even how do I use Dart's Stream of events as a buffer...
What is the real way timeout before examining the contents of the buffer?
(and I guess the final question is 'should I abandon the effort and settle for a conventional set of buttons with glyph-icons?'!)
I'm not sure if IE still has the event sequence explained here (no 2nd click event)
https://stackoverflow.com/a/5511527/217408
If yes you can use a slightly deviated variant of Roberts solution:
library app_element;
import 'dart:html' as dom;
import 'dart:async' as async;
Duration dblClickDelay = new Duration(milliseconds: 500);
async.Timer clickTimer;
void clickHandler(dom.MouseEvent e, [bool forReal = false]) {
if(clickTimer == null) {
clickTimer = new async.Timer(dblClickDelay, () {
clickHandler(e, true);
clickTimer = null;
});
} else if(forReal){
print('click');
}
}
void dblClickHandler(dom.MouseEvent e) {
if(clickTimer != null) {
clickTimer.cancel();
clickTimer = null;
}
print('doubleClick');
}
void main() {
dom.querySelector('button')
..onClick.listen(clickHandler)
..onDoubleClick.listen(dblClickHandler);
}
or just use Roberts solution with the mouseUp event instead of the click event.
The problem is that your variable is not global.
var eventTypes = new List<String>();
void catchClickEvents(Event e) {
eventTypes.add(e.type);
Duration duration = const Duration(milliseconds: 300);
var timeout = new Timer(duration, () => processEvents(eventTypes));
}
void processEvents(List eTypes) {
print(eTypes);
}
There also is e.detail that should return the number of the click. You can use that, if you don't need the Internet Explorer. The problem with your list is that it grows and never gets cleared.
Let's take into account what we know: You get click events and at somepoint you have doubleclicks.
You could use a click counter here. (Or use e.detail) to skip the second click event. So you only have click and dblclick.
Now when you get a click event, you create a new timer like you did before and run the click action. If you get the dblclick event you simply run you action. This could like this:
DivElement div = querySelector('#div');
Timer timeout = null;
div.onClick.listen((MouseEvent e) {
if(e.detail >= 2) {
e.preventDefault();
} else {
if(timeout != null) {
timeout.cancel();
}
timeout = new Timer(new Duration(milliseconds: 150), () => print('click'));
}
});
div.onDoubleClick.listen((MouseEvent e) {
if(timeout != null) {
timeout.cancel();
timeout = null;
}
print('dblclick');
});
This is the example code that works for me. If you can't rely on e.detail just us a counter and reset it after some ms after a click event.
I hope this helps you.
Regards, Robert
Your page should react on user inputs as fast as possible. If you wait to confirm double click - your onClick will become much less responsive. You can hide the problem by changing visual state of the element(for example, playing animation) after first click but it can confuse user. And it gets even worse with handheld. Also if element has to react only on onClick event, you can "cheat" and listen to onmousedown instead - it will make your UI much more responsive.
On top of all this, double click, from client to client, may have noticeably different trigger time interval and it isn't intuitive, for user, that you can double click something. You will have to bloat your interface with unnecessary hints.
edit: Added my solution. It should be fairly extensible and future proof.
import 'dart:html';
import 'dart:async';
import 'dart:math';
//enum. Kinda... https://code.google.com/p/dart/issues/detail?id=88
class UIAction {
static const NEXT = const UIAction._(0);
static const FULLSCREEN = const UIAction._(1);
static const ERROR = const UIAction._(2);
final int value;
const UIAction._(this.value);
}
/**
*[UIEventToUIAction] transforms UIEvents into corresponding UIActions.
*/
class UIEventToUIAction implements StreamTransformer<UIEvent, UIAction> {
/**
* I use "guesstimate" value for [doubleClickInterval] but you can calculate
* comfortable value for the user from his/her previous activity.
*/
final Duration doubleClickInterval = const Duration(milliseconds: 400);
final StreamController<UIAction> st = new StreamController();
Stream<UIAction> bind(Stream<UIEvent> originalStream) {
int t1 = 0,
t2 = 0;
bool isOdd = true;
Duration deltaTime;
originalStream.timeout(doubleClickInterval, onTimeout: (_) {
if ((deltaTime != null) && (deltaTime >= doubleClickInterval)) {
st.add(UIAction.NEXT);
}
}).forEach((UIEvent uiEvent) {
isOdd ? t1 = uiEvent.timeStamp : t2 = uiEvent.timeStamp;
deltaTime = new Duration(milliseconds: (t1 - t2).abs());
if (deltaTime < doubleClickInterval) st.add(UIAction.FULLSCREEN);
isOdd = !isOdd;
});
return st.stream;
}
}
void main() {
//Eagerly perform time consuming tasks to decrease the input latency.
Future NextImageLoaded;
Future LargeImageLoaded;
element.onMouseDown.forEach((_) {
NextImageLoaded = asyncActionStub(
"load next image. Returns completed future if already loaded");
LargeImageLoaded = asyncActionStub(
"load large version of active image to show in fullscreen mode."
"Returns completed future if already loaded");
});
Stream<UIEvent> userInputs = element.onClick as Stream<UIEvent>;
userInputs.transform(new UIEventToUIAction()).forEach((action) {
switch (action) {
case UIAction.FULLSCREEN:
LargeImageLoaded.then( (_) =>asyncActionStub("fullscreen mode") )
.then((_) => print("'full screen' finished"));
break;
case UIAction.NEXT:
NextImageLoaded.then( (_) =>asyncActionStub("next image") )
.then((_) => print("'next image' finished"));
break;
default:
asyncActionStub("???");
}
});
}
final DivElement element = querySelector("#element");
final Random rng = new Random();
final Set performed = new Set();
/**
*[asyncActionStub] Pretends to asynchronously do something usefull.
* Also pretends to use cache.
*/
Future asyncActionStub(String msg) {
if (performed.contains(msg)) {
return new Future.delayed(const Duration(milliseconds: 0));
}
print(msg);
return new Future.delayed(
new Duration(milliseconds: rng.nextInt(300)),
() => performed.add(msg));
}

Groovy/Grails promises/futures. There is no .resolve(1,2,3) method. Strange?

I am developing in a Grails application. What I want to do is to lock the request/response, create a promise, and let someone else resolve it, that is somewhere else in the code, and then flush the response.
What I find really strange is that the Promise promise = task {} interface has no method that resembles resolve or similar.
I need to lock the response until someone resolves the promise, which is a global/static property set in development mode.
Promise interface:
http://grails.org/doc/latest/api/grails/async/Promise.html
I have looked at the GPars doc and can't find anything there that resembles a resolve method.
How can I create a promise, that locks the response or request, and then flushes the response when someone resolves it?
You can call get() on the promise which will block until whatever the task is doing completes, but I imagine what that is not what you want. What you want seems to be equivalent to a GPars DataflowVariable:
http://gpars.org/1.0.0/javadoc/groovyx/gpars/dataflow/DataflowVariable.html
Which allows using the left shift operator to resolve the value from another thread. Currently there is no way to use the left shift operator via Grails directly, but since Grails' promise API is just a layer over GPars this can probably be accomplished by using the GPars API directly with something like:
import org.grails.async.factory.gpars.*
import groovyx.gpars.dataflow.*
import static grails.async.Promise.*
def myAction() {
def dataflowVar = new DataflowVariable()
task {
// do some calculation and resolve data flow variable
def expensiveData = ...
dataflowVar << expensiveData
}
return new GParsPromise(dataflowVar)
}
It took me quite some time to get around this and have a working answer.
I must say that it appears as if Grails is quite a long way of making this work properly.
task { }
will always execute immediatly, so the call is not put on hold until dispatch() or whatever is invoked which is a problem.
Try this to see:
public def test() {
def dataflowVar = new groovyx.gpars.dataflow.DataflowVariable()
task {
// do some calculation and resolve data flow variable
println '1111111111111111111111111111111111111111111111111111'
//dataflowVar << expensiveData
}
return new org.grails.async.factory.gpars.GparsPromise(dataflowVar);
}
If you are wondering what this is for, it is to make the lesscss refresh automatically in grails, which is a problem when you are using import statements in less. When the file is touched, the lesscss compiler will trigger a recompilation, and only when it is done should it respond to the client.
On the client side I have some javascript that keeps replacing the last using the refresh action here:
In my controller:
/**
* Refreshes link resources. refresh?uri=/resource/in/web-app/such/as/empty.less
*/
public def refresh() {
return LessRefresh.stackRequest(request, params.uri);
}
A class written for this:
import grails.util.Environment
import grails.util.Holders
import javax.servlet.AsyncContext
import javax.servlet.AsyncEvent
import javax.servlet.AsyncListener
import javax.servlet.http.HttpServletRequest
/**
* #Author SecretService
*/
class LessRefresh {
static final Map<String, LessRefresh> FILES = new LinkedHashMap<String, LessRefresh>();
String file;
Boolean touched
List<AsyncContext> asyncContexts = new ArrayList<AsyncContext>();
String text;
public LessRefresh(String file) {
this.file = file;
}
/** Each request will be put on hold in a stack until dispatchAll below is called when the recompilation of the less file finished **/
public static AsyncContext stackRequest(HttpServletRequest request, String file) {
if ( !LessRefresh.FILES[file] ) {
LessRefresh.FILES[file] = new LessRefresh(file);
}
return LessRefresh.FILES[file].handleRequest(request);
}
public AsyncContext handleRequest(HttpServletRequest request) {
if ( Environment.current == Environment.DEVELOPMENT ) {
// We only touch it once since we are still waiting for the less compiler to finish from previous edits and recompilation
if ( !touched ) {
touched = true
touchFile(file);
}
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(10000)
asyncContexts.add (asyncContext);
asyncContext.addListener(new AsyncListener() {
#Override
void onComplete(AsyncEvent event) throws IOException {
event.getSuppliedResponse().writer << text;
}
#Override
void onTimeout(AsyncEvent event) throws IOException {
}
#Override
void onError(AsyncEvent event) throws IOException {
}
#Override
void onStartAsync(AsyncEvent event) throws IOException {
}
});
return asyncContext;
}
return null;
}
/** When recompilation is done, dispatchAll is called from LesscssResourceMapper.groovy **/
public void dispatchAll(String text) {
this.text = text;
if ( asyncContexts ) {
// Process all
while ( asyncContexts.size() ) {
AsyncContext asyncContext = asyncContexts.remove(0);
asyncContext.dispatch();
}
}
touched = false;
}
/** A touch of the lessfile will trigger a recompilation **/
int count = 0;
void touchFile(String uri) {
if ( Environment.current == Environment.DEVELOPMENT ) {
File file = getWebappFile(uri);
if (file && file.exists() ) {
++count;
if ( count < 5000 ) {
file << ' ';
}
else {
count = 0
file.write( file.getText().trim() )
}
}
}
}
static File getWebappFile(String uri) {
new File( Holders.getServletContext().getRealPath( uri ) )
}
}
In LesscssResourceMapper.groovy of the lesscsss-recources plugin:
...
try {
lessCompiler.compile input, target
// Update mapping entry
// We need to reference the new css file from now on
resource.processedFile = target
// Not sure if i really need these
resource.sourceUrlExtension = 'css'
resource.contentType = 'text/css'
resource.tagAttributes?.rel = 'stylesheet'
resource.updateActualUrlFromProcessedFile()
// ==========================================
// Call made here!
// ==========================================
LessRefresh.FILES[resource.sourceUrl.toString()]?.dispatchAll( target.getText() );
} catch (LessException e) {
log.error("error compiling less file: ${originalFile}", e)
}
...
In the index.gsp file:
<g:set var="uri" value="${"${App.files.root}App/styles/empty.less"}"/>
<link media="screen, projection" rel="stylesheet" type="text/css" href="${r.resource(uri:uri)}" refresh="${g.createLink(controller:'home', action:'refresh', params:[uri:uri])}" resource="true">
JavaScript method refreshResources to replace the previous link href=...
/**
* Should only be used in development mode
*/
function refreshResources(o) {
o || (o = {});
var timeoutBegin = o.timeoutBegin || 1000;
var intervalRefresh = o.intervalRefresh || 1000;
var timeoutBlinkAvoid = o.timeoutBlinkAvoid || 400 ;
var maxErrors = o.maxErrors || 200 ;
var xpath = 'link[resource][type="text/css"]';
// Find all link[resource]
$(xpath).each(function(i, element) {
refresh( $(element) );
});
function refresh(element) {
var parent = element.parent();
var next = element.next();
var outer = element.clone().attr('href', '').wrap('<p>').parent().html();
var uri = element.attr('refresh');
var errorCount = 0;
function replaceLink() {
var link = $(outer);
link.load(function () {
// The link has been successfully added! Now remove the other ones, then do again
errorCount = 0;
// setTimeout needed to avoid blinking, we allow duplicates for a few milliseconds
setTimeout(function() {
var links = parent.find(xpath + '[refresh="'+uri+'"]');
var i = 0;
// Remove all but this one
while ( i < links.length - 1 ) {
links[i++].remove();
}
replaceLinkTimeout();
}, timeoutBlinkAvoid );
});
link.error(function(event, handler) {
console.log('Error refreshing: ' + outer );
++errorCount;
if ( errorCount < maxErrors ) {
// Load error, it happens. Remove this & redo!
link.remove();
replaceLink();
}
else {
console.log('Refresh: Aborting!')
}
});
link.attr('href', urlRandom(uri)).get(0);
link.insertBefore(next); // Insert just after
}
function urlRandom(uri) {
return uri + "&rand=" + Math.random();
}
function replaceLinkTimeout() {
setTimeout(function() {
replaceLink();
}, intervalRefresh ) ;
}
// Waith 1s before triggering the interval
setTimeout(function() {
replaceLinkTimeout();
}, timeoutBegin);
}
};
Comments
I am unsure why Javascript style promises have not been added to the Grails stack.
You can not render or stuff like that in the onComplete. render, redirect and what not are not available.
Something tells me that Grails and Promises/Futures are not there yet. The design of the GPars libraries seems not take into account of the core features which is to resolve later. At least it is not simple to do so.
It would be great if the dispatch() method actually could be invoked with some paramaters to pass from the resolving context. I am able to go around this using static properties.
I might continue to write my own solution and possibly contribute with a more fitting solutions around the AsyncContext class, but for now, this is enough for me.
I just wanted to refresh my less resources automatically.
Phew...
EDIT:
I made it to support several number of files. It is complete now!

How to call javascript functions from blackberry native?

I am developing an app where i need to call some methods from blackberry native to javascript.
when i click on back key down event , i want to trigger the onBackKeyDown() method, which is declared in javascript.
Main.java
protected boolean keyDown(int keycode, int time) {
// TODO Auto-generated method stub
if(Keypad.key(keycode) == Keypad.KEY_ESCAPE)
{
// onBackKeyDown();
// i want to call the following method which is declared in main.js file
Dialog.alert("this is back button");
return true;
}
return super.keyDown(keycode, time);
}
main.js
function onBackKeyDown() {
try {
if ($.mobile.activePage.is("#Page1")) {
$.mobile.changePage("#page5");
} else if ($.mobile.activePage.is("#page2")) {
$.mobile.changePage("#main");
} else if ($.mobile.activePage.is("#page3")) {
$.mobile.changePage("#main");
} else if ($.mobile.activePage.is("#main")) {
navigator.app.exitApp();
}
} catch(e) {
alert("Exception:ConsoleLog.log:" + e);
}
}
As i am having idea that by using "extendScriptEngine" , the methods declared in javascript are invoked in native. But here how to invoke the methods in javascript which are in native as per my above code... can anyone please help me with this...
You don't show this code, but I have to assume that your app has some Screen that contains some kind of browser field, which is displaying HTML content.
I can't tell you for sure without seeing that code, but what I would recommend is to use net.rim.device.api.browser.field2.BrowserField (Browser Field 2), if your app only needs to support OS 5.0 and higher.
If you have to support less than OS 5.0, I'm not sure how to do that.
Anyway, with this 5.0+ BrowserField, you can do this:
BrowserFieldConfig config = new BrowserFieldConfig();
config.setProperty(BrowserFieldConfig.JAVASCRIPT_ENABLED, Boolean.TRUE); // should be the default
// Browser basic initialization
BrowserField _browserField = new BrowserField(config);
and then
protected boolean keyDown(int keycode, int time)
{
if(Keypad.key(keycode) == Keypad.KEY_ESCAPE)
{
// i want to call the following method which is declared in main.js file
_browserField.executeScript("onBackKeyDown()");
Dialog.alert("this is back button");
return true;
}
return super.keyDown(keycode, time);
}

Resources