viernes, 27 de agosto de 2010

Script for dynamic JavaScript and CSS loading

With the following script, you can easily load javascripts and css files dynamically and asynchronously of course:


/**javascript and css loader
* @author: sgurin
*/
(function(){

var _loadF = function(name, type, listener){
var el=null;
if (type=="js"){
el=document.createElement("script");
el.setAttribute("type","text/javascript");
if(listener) {
el.onreadystatechange = function () {
if (this.readyState == 'complete') listener();
};
el.onload=listener;
}
el.setAttribute("src", name);
}
else if (type=="css"){
el=document.createElement("link");
el.setAttribute("rel", "stylesheet");
el.setAttribute("type", "text/css");
el.setAttribute("href", name);
}
document.body.appendChild(el);
};
/**public global function
* @param css - array of css url to load. can be null
* @param js - array of javascript scripts urls to load. can be null
* @param listener function that will be called when ALL js and css files are loaded.
*/
LOADFILE = function (css, js, listener) {
css=css==null?[]:css;
js=js==null?[]:js;
var subListener=function(){
LOADFILE.counter--;
if(LOADFILE.counter==0)
listener();
};
for(var i=0; i<css.length; i++) {
_loadF(css[i], "css", subListener);
}
for(var i=0; i<js.length; i++) {
LOADFILE.counter++;
_loadF(js[i], "js", subListener);
}
};
LOADFILE.counter=0;//file load counter

})();


For example, you can dynamically load all your javascript application's javascript and css files like this:


LOADFILE(
["http://yui.yahooapis.com/2.8.1/build/slider/assets/skins/sam/slider.css",
"http://yui.yahooapis.com/2.8.1/build/fonts/fonts-min.css",
"http://yui.yahooapis.com/2.8.1/build/colorpicker/assets/skins/sam/colorpicker.css"],

["http://yui.yahooapis.com/2.8.1/build/yahoo-dom-event/yahoo-dom-event.js",
"http://yui.yahooapis.com/2.8.1/build/animation/animation-min.js",
"http://yui.yahooapis.com/2.8.1/build/dragdrop/dragdrop-min.js",
"http://yui.yahooapis.com/2.8.1/build/slider/slider-min.js",
"http://yui.yahooapis.com/2.8.1/build/element/element-min.js",
"http://yui.yahooapis.com/2.8.1/build/colorpicker/colorpicker-min.js"],

function(){
//my javascript application's code
var Event = YAHOO.util.Event,
picker;
Event.onDOMReady(function() {
YAHOO.log("Creating Color Picker.", "info", "example");
picker = new YAHOO.widget.ColorPicker("container", {
showhsvcontrols: true,
showhexcontrols: true,
images: {
PICKER_THUMB: "assets/picker_thumb.png",
HUE_THUMB: "assets/hue_thumb.png"
}
});
YAHOO.log("Finished creating Color Picker.", "info", "example");
var onRgbChange = function(o) {
YAHOO.log("The new color value is " + o.newValue, "info", "example");
}
picker.on("rgbChange", onRgbChange);
Event.on("reset", "click", function(e) {
picker.setValue([255, 255, 255], false);
});
Event.on("gethex", "click", function(e) {
alert("Current hex value: " + picker.get("hex"), "info", "example");
});
});
});


Hope this help somebody

jueves, 29 de julio de 2010

svn error (405 Method Not Allowed) in commit

If you are web developer and are trying to commit your changes via svn to sourceforge.net or google code and the commit because a (405 Method Not Allowed), the first thing you want to check is the following.

For commiting code to this kind of sites, you have to commit using the https:// direction and NOT http://. You can checkout projects using http:// but for commiting changes you must use https://. This is a common mistake that can stuck svn novices (like me)

martes, 30 de marzo de 2010

How to start publishing your project in sourceforge

How to start publishing your project in sourceforge

This article is a step/by/step guide to those who want to maintain their development projects in sourceforge.net, with svn support for sharing their source code and a project web site.

First of all I suppose you have already created a new project in sourceforge.net. The important thing to remember is the project's unix name. In the following examples, my sourceforge.net user name is cancerbero_sgx and my project unix name is yui4java. As an administrator of your new project, using a linux shell, you can do the following activities:

copy files and directories with rsync:

# rsync -avP -e ssh foo.txt cancerbero_sgx,yui4java@web.sourceforge.net:htdocs/
# rsync -avP -e ssh /home/sgurin/dir1 cancerbero_sgx,yui4java@web.sourceforge.net:htdocs/

those will copy (synchronize) the file foo.txt and the directory /home/sgurin/dir1 to project's htdocs directory.

conecting using sftp:

sftp cancerbero_sgx,yui4java@web.sourceforge.net

Getting a web shell with ssh

with this option you will have access to a remote terminal in sf.net and there execute commands, access files ,etc
for connecting I use:

ssh -t cancerbero_sgx,yui4java@shell.sourceforge.net create


Publish your source code using svn

This will create a svn repository from a local source directory. Be carefull when typing commands when creating a new repository! Once this is done, you can svn checkout your own source files. Then you can work with svn (svn update, svn commit) in your own local working copy.

first you need to create a repository. for this you have to:

1)
connect via ssh as explained beore

2)
type the command :
adminrepo --checkout svn
(this will create a clone copy of your repository in /svnroot/yui4java.
* Use adminrepo --help for further information.)

3)
type the following commands (be carefull!)
rm -rf /svnroot/yui4java/*
# (Remove the clone copy of your repo)
create /svnroot/PROJECT
# (Create a new repository)

4)
type the following commands
cd
adminrepo --save svn


that operation can take some seconds... Once it is done, you can use your new svn repository. With the following command we will import a local source code directory into the svn repository:

svn import /home/sgurin/my/local/src/folder https://yui4java.svn.sourceforge.net/svnroot/yui4java/trunk

web page

The last thing we will create for our new project is its web page in sourceforge.net. In our project's main folder, we have the directory htdocs and this is the directory that is exposed to the web. In my example, this diretory is located at /home/groups/y/yu/yui4java/htdocs. This means that a file there, for example, /home/groups/y/yu/yui4java/htdocs/example.html can be navigated from http://yui4java.sourceforge.net/example.html.

it is important that all directory accesible from the web (for example, directories with javascript, css, images, etc), to contain a file .htaccess with the following content:

Options +Indexes
that's all. I hope this can be usefull to new sourceforge users.

miércoles, 3 de marzo de 2010

Problem with SVG feConvolveMatrix filter with kernel which sum is zero

Here I will document an issue that I had working with SVG feConvolveMatrix primitive filter that was a really pain for me but has a simple solution.

My problem was using feConvolveMatrix filter primitive to apply operations like blur, sharp, edge detection, etc to images. Everything works OK, except for kernel matrix which elements sum equals 0.

For example, the following filters works as spected:


<filter id="vstripe">
<feConvolveMatrix order="3"
kernelMatrix="
2 -1 2
-1 2 -1
2 -1 2"
/>
</filter>


but the following filter (with a kernel which elements sum equals 0) won't work ( will show an empty rectangle):


<filter id="vstripe">
<feConvolveMatrix order="3"
kernelMatrix="
-1 -1 -1
-1 8 -1
-1 -1 -1"
/>
</filter>


This problem manifest only for svg elements and in all svg user agents (mozilla, webkit, opera, inskape, etc). This problem is very frustrating because, there are a lot of convolution filters that use kernels which element sum must be 0 (specially edge detector filters).

The problem was because of the alpha channel of images. In most images, the alpha channel has a constant value for all pixels in a region and so, a convolution using these kernels will give 0 (totally transparent) and that is the reason for the empty rectangle.

The solution is setting the parameter preserveAlpha="true" so the alpha channel is not processed in the convolution:


<filter id="vstripe">
<feConvolveMatrix order="3" preserveAlpha="true"
kernelMatrix="
-1 -1 -1
-1 8 -1
-1 -1 -1"
/>
</filter>


I hope this article can help those poor souls that, like me, are stagnant with this problem.

martes, 2 de febrero de 2010

replacing text on files recursively over directories

In very special ocations, when I'm programming, I need to recursively replace text of all files in directories. For example, you want to recursively replace the string "import org.foo.bar.Class1" with "org2.foo.bar.Class1" in all .java files, in a java source folder. I know this can be done with a relatively simple shell (bash) script using sed, grep, etc unix commands, but what about systems that doesn't have bash? Also, there is a program called rpl (http://www.laffeycomputer.com/rpl.html) which purpose is this but, unfortunately, didn't worked for me (I compiled it on my machine, but the command fails with an error message (couldn't allocate memory or simply doesn't finnish its execution). So I implemented this functionality in java. I tested it on large source folders and works quick and nice. I hope this can be helpful for somebody:



package org.sgx.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
* replace strings with new strings in multiple text files recursively over
* directories and supports limiting the search to specific file names.
*
* @author sgurin
*
*/
public class RPL {
public static void copyDirAndReplaceRecursively(File src, File dest,
String filter, String str, String replacement)
throws FileNotFoundException, IOException {
if (src.isDirectory()) {
dest.mkdirs();
File[] childs = src.listFiles();
for (int i = 0; i < childs.length; i++) {
File child = childs[i];
File destChild = new File(dest.getAbsolutePath()
+ File.separator + child.getName());
copyDirAndReplaceRecursively(child, destChild, filter, str,
replacement);
}
} else {
if (src.getName().contains(filter)) {
copyFileAnReplacetext(src, dest, str, replacement);
} else {
copyFileAnReplacetext(src, dest, null, null);
}
}

}

public static void copyFileAnReplacetext(File srcFile, File destFile,
String str, String replacement) throws FileNotFoundException,
IOException {
StringBuffer sb = new StringBuffer();
InputStream is = new FileInputStream(srcFile);
readFile(is, sb);
is.close();
String s = sb.toString();
if (str != null && replacement != null)
s = s.replace(str, replacement);
FileOutputStream os = new FileOutputStream(destFile);
os.write(s.getBytes());
os.close();
}

public static void readFile(InputStream in, StringBuffer sb)
throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
}

// test
public static void main(String[] args) {
try {
File srcDir = new File(
"/home/sebastian/desarrollo/portal4/blogsJavas/src2"), destDir = new File(
"/home/sebastian/desarrollo/portal4/blogsJavas/src");
String str = "com.liferay.portlet.blogs", repl = "org.sgx.portlet.circulares";
FSUtils.copyDirAndReplaceRecursively(srcDir, destDir, ".java", str,
repl);

} catch (Exception e) {
e.printStackTrace();
}
}
}

lunes, 18 de enero de 2010

Problem with keyboard event handling in java, both with swing and swt

I will try to explain, with my bad english, a recent problem that I'm having with keyboard event handling in java using both swing and swt GUI libraries. Basically the problem is that there is not a way, both in swing and swt, of knowing the status of the keyboard keys. Basically the problem is that, while the user is still pressing the key (and never release it), keyrelease events are being throwed (!) and for that it is impossible to get the real keyrelease event. This problem only manifest in programs that need to use advance keyboard controlling; think for example in a piano simulator in which the user uses the keyboard keys as if it where a piano's keys. When the user presses a key a note turn on, and it is turned off only when the user releases it. The user can hold the key an arbitrary amount of time without release it and the note must be turned on in all that time.

I will present the problem with two simple GUI snippets, one for swing and other for swt, and I will compile and execute them both in windows and linux, using sun jdk version 1.6_13. The snippets are a window that listens to keypressed and keyreleased events and prints a message when the event notification is received. In all the tests, the user will press a key and will keep it pressed for some time (more than a second) and then release it. So the correct output for this "use case" would be only two messages "keyPressed" and
"keyReleased" in the output console. The only toolkit and OS combination that worked as spected was swt+linux. In the rest of the combinations, several "keyPressed" and
"keyReleased" are repeated while the user is keeping the key presssed.











SWT snippetSWING snippet

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class KeyPressTest extends org.eclipse.swt.widgets.Dialog {
    
    private Shell dialogShell;
    
    public KeyPressTest(Shell parent, int style) {
        super(parent, style);
    }
    
    public void open() {
        try {
            Shell parent = getParent();
            dialogShell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
            dialogShell.addKeyListener(new KeyListener() {
                @Override
                public void keyReleased(KeyEvent arg0) {
                    System.out.println("keyReleased");
                }
                @Override
                public void keyPressed(KeyEvent arg0) {
                    System.out.println("keyPressed");
                }
            });
            dialogShell.setLayout(new FormLayout());
            dialogShell.layout();
            dialogShell.pack();
            dialogShell.setLocation(getParent().toDisplay(100, 100));
            dialogShell.open();
            Display display = dialogShell.getDisplay();
            while (!dialogShell.isDisposed()) {
                if (!display.readAndDispatch())
                display.sleep();
            }
            } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        try {
            Display display = Display.getDefault();
            Shell shell = new Shell(display);
            KeyPressTest inst = new KeyPressTest(shell, SWT.NULL);
            inst.open();
            } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class KeyPressTest extends javax.swing.JFrame {
    public KeyPressTest() {
        super();
        initGUI();
    }
    private void initGUI() {
        try {
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            this.addKeyListener(new KeyListener() {
                @Override
                public void keyTyped(KeyEvent e) {
                }
                @Override
                public void keyReleased(KeyEvent e) {
                    System.out.println("keyReleased");
                }
                @Override
                public void keyPressed(KeyEvent e) {
                    System.out.println("keyPressed");
                }
            });
            pack();
            setSize(400, 300);
            } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                KeyPressTest inst = new KeyPressTest();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }
}


And the results, for swing and swt in combination with windows and linux are:















windowslinux
swing

keyPressed
keyReleased
keyPressed
keyReleased
keyPressed
keyReleased
....
keyPressed
keyReleased

keyPressed
keyReleased
keyPressed
keyReleased
keyPressed
keyReleased
....
keyPressed
keyReleased
SWT

keyPressed
keyReleased
keyPressed
keyReleased
keyPressed
keyReleased
....
keyPressed
keyReleased

keyPressed
keyPressed
keyPressed
keyPressed
keyPressed
...
keyPressed
keyPressed
keyReleased


As I understand, THIS IS A BUG, because the behaviour does not apply the documentation. For example, this is the more relevant paragraph about keypressed and keyreleased events of swing (java.awt.event.KeyEvent javadoc):

"Key pressed" and "key released" events are lower-level and depend on the platform and keyboard layout. They are generated whenever a key is pressed or released, and are the only way to find out about keys that don't generate character input (e.g., action keys, modifier keys, etc.).

and this is not true because keyreleased events are generated without a key being released

Note that the only different situation is swt in linux. Imho it is still incorrect (because several keypressed events are fired but only one actually happens) but in this case we can we can know when the key is really releaed. In the other scenarios it is impossible.

IMHO, a cause of this problem coud be that swt and swing designers have modeled the keyboard event system thinking on text and not in other keyboard usage. In the case of swt that heavily relies on underlying plafform (gtk in linux, winapi in windows), I think the event stuff is a responsability of the uderlying platform and it is there where we note the defferencies.

So my question for java developers reading this is if there exists a way of being correctly notified when a keyrelease event occurs using swing or swt. Other question could be if there exists other library for java which handles this correctly because now, I havent figure out how to do this simple task in java ;(.

If you are a java programmer and want a workaround, I think the only one is the following. Since, while the key is pressed the keypressed event is fired regularly, the way we have to know that a key is released is when keypressed event is not firing anymore for that key. Note that this will be incorrect (because it is not really a keyrelease event) and can be expensive to implement because it because it require, for each key, a listener thread that triggers the fake keyrelease event when it detects no more keypressed. My proposal is the following keylistener (KeyListener2 inner class):


package org.sgx.javatests.keypress.swingAll;

import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class SwingSollutionAllClasses {

/**
* this class is responsible for maintaining a key status map
* @author sebastian
*
*/
static class InputManager implements KeyListener {
//sgurin : þe last keypressed and keyreleased events registered for each key
Map lastKeyPressedEvents = new HashMap();
Map lastKeyReleasedEvents = new HashMap();
//one for each ascii character.
public boolean[] key_state_up = new boolean[256]; //true if pressed
public boolean[] key_state_down = new boolean[256]; //true if not pressed
//a string used as a buffer by widgets or other text input controls
private String keyCache = "";
public InputManager(){
for (int i = 0; i < key_state_up.length; i++) {
key_state_up[i]=true;
key_state_down[i]=false;
}
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if( code >= 0 && code < 256 ) {
key_state_down[code] = true;
key_state_up[code] = false;
lastKeyPressedEvents.put(code, e);
}
}
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if( code >= 0 && code < 256 ) {
key_state_up[code] = true;
key_state_down[code] = false;
lastKeyReleasedEvents.put(code, e);
}
}
public void keyTyped(KeyEvent e) {
keyCache += e.getKeyChar();
}
public boolean isKeyDown( int key ) {
return key_state_down[key];
}
public boolean isKeyUp( int key ) {
return key_state_up[key];
}
}

/**
* this class is a new KeyListener adapter that corrects the default keyreleased
* notification policy (repeatedly notifies keypressed and keyreleased events
* when a key is pressed and not released for a while).
*
* note that this is a heavy listener, use only at special cases (when you need different behaviour for keyreleased event handling)
* it uses an InputManager that mantains the key status and starts a thread that checks each key status and notify changes
*
* @author sgurin
*
*/
static abstract class KeyListener2 implements KeyListener {

KeyChecker checkerThread ;
public KeyListener2(Component target) {
super();
checkerThread=new KeyChecker(this, target);
checkerThread.start();
}
public void destroy() {
checkerThread.stopChecking();
}

static class KeyChecker extends Thread implements KeyListener {
private static final long SLEEP_AMOUNT =50;
InputManager iman;
Component target;
volatile private boolean stoped;
public boolean[] last_key_state_up=null, last_key_state_down=null;
KeyListener2 listener;

public KeyChecker(KeyListener2 listener, Component target){
iman = new InputManager();
this.target = target;
this.listener = listener;
target.addKeyListener(iman);
target.addKeyListener(this);
}

@Override
public void run() {
last_key_state_down=cloneArray(iman.key_state_down);
last_key_state_up = cloneArray(iman.key_state_up);
while(!stoped) {
try {
Thread.sleep(SLEEP_AMOUNT);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < last_key_state_up.length; i++) {
if(last_key_state_up[i] && iman.key_state_down[i])
listener.keyPressed(iman.lastKeyPressedEvents.get(i));
if(last_key_state_down[i] && iman.key_state_up[i])
listener.keyReleased(iman.lastKeyReleasedEvents.get(i));
}
last_key_state_down=cloneArray(iman.key_state_down);
last_key_state_up = cloneArray(iman.key_state_up);
}
}
private boolean[] cloneArray(boolean[] a) {
if(a==null)
return null;
boolean [] r = new boolean[a.length];
for (int i = 0; i < r.length; i++)
r[i]=a[i];
return r;
}
public void stopChecking() {
stoped=true;
}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
listener.keyTyped(e);
}
}
}

/**
* swing test
*/
static class KeyPressTest extends javax.swing.JFrame {
public KeyPressTest() {
super();
initGUI();
}
private void initGUI() {
try {
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
new KeyListener2(this) {
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased");
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed");
}
};
pack();
setSize(400, 300);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
KeyPressTest inst = new KeyPressTest();
inst.setLocationRelativeTo(null);
inst.setVisible(true);
}
});
}
}
public static void main(String[] args) {
KeyPressTest.main(args);
}
}



Related information I found:
http://stackoverflow.com/questions/1736828/how-to-stop-repeated-keypressed-keyreleased-events-in-swing
http://groups.google.com/group/comp.lang.java.gui/browse_thread/thread/e215f9729154511e
http://gpsnippets.blogspot.com/2008/03/keyboard-input-polling-system-in-java.html