• 11gen
    Categories: Programming Commenti disabilitati

    I recently bought an Android phone and now I wish to develop some mobile apps. This is why I took a look at Flex technology and discovered with disappoint that Adobe is 1) selling their IDE at a very high cost 2) not supporting Linux anymore.

    In any case, being FlashBuilder based on Eclipse Platform, it's possible to run its plugins on a clean eclipse installation. The only unavoidable limitation is the usage of Adobe AIR 2.6, the last release for Linux systems.

    Merging the Flex SDK with Adobe AIR

    Although any Flex SDK can be used in FlashBuilder-Eclipse, it's recommended to use version 4.5.1 that at the time of writing is the only one that features the Design Mode (EDIT: it seems there is no way to make Design Mode functional. The closest environment is this web tool: http://designview.sourceforge.net/). Flex SDK can be obtained at http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK, while Adobe AIR 2.6 for Linux should remain available at the following link: http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRSDK.tbz2. It's afterward necessary to copy AIR runtimes/ to SDK runtimes/ and substitute SDK bin/adl with AIR bin/adl [1]

    Install FlashBuilder over Eclipse

    First, download a new Eclipse and install it somewhere, for instance in /usr/share/flashbuilder and optionally rename the eclipse executable to flashbuilder. Then, follow instructions at http://code.google.com/p/fb4linux/wiki/HowToInstall to install the port of the Adobe Flash Builder 4.5 to Linux. Actually to me it was impossible to use the Eclipse p2 updater and I simply dragged the features/ and plugins/ directories from the downloaded archive over the Eclipse folder. From now on, it will be possible to update the IDE (including module updates from Adobe) using the p2 updater.

    Troubleshooting

    A few problems arose at this time; this is an alpha software in any case.

    1) Resolve PermGen space errors during execution and updates

    FlashBuilder requires much more memory than eclipse, run it with command line parameters -vmargs -Xms768m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m to be sure it doesn't run out of memory. Those parameters could also be set directly in the eclipse.ini file [2]

    2) Sporadic crashes (for instance when choosing an external web browser):

    Investigating the crash dump revealed the xulrunner library was the cause of this issue. Further googling helped to find the solution [3]: add the -Dorg.eclipse.swt.browser.XULRunnerPath=/usr/lib/xulrunner-2/libxul.so parameter, to the command line execution, too.

    Eye candy

    To complete the integration with the desktop environment (Gnome Shell) I performed the steps that follows. Attached to this post, a zip file containing a Flash Builder icon and a splash screen: flashbuilder-eyecandy.zip

    1) Make flashbuilder a permanent entry to the dock

    Create a new file /usr/share/applications/flashbuilder.desktop with the following content, so that when FlashBuilder-Eclipse is run for the first time it will be possible to add it as favorite:

    [Desktop Entry]
    Name=Flash Builder
    GenericName=Adobe Flash Builder
    Comment=Eclipse IDE modified in order to use Adobe Flash Builder plugins
    Exec=/usr/share/flashbuilder/flashbuilder -vmargs -Xms768m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m -Dorg.eclipse.swt.browser.XULRunnerPath=/usr/lib/xulrunner-2/libxul.so
    Icon=flashbuilder
    Terminal=false
    Type=Application
    Categories=Development;IDE;Flex;

    Note that the definition searches for a flashbuilder.* icon in the /usr/share/icons/ folder.

    2) Change FlashBuilder-Eclipse splash screen

    Follows the steps reported here [4] to change the Eclipse default splash screen

    References

    [1] http://zoltanb.co.uk/how-to-set-up-flex-4-5-sdk-with-air-2-6-on-linux-using-fdt/

    [2] http://www.javaquery.com/2010/11/how-to-solve-permgen-space-error-in.html

    [3] http://kishalmi.net/cms/node/55

    [4] http://www.mkyong.com/java/how-to-change-eclipse-splash-welcome-screen-image/

    Tags: , ,
  • 20ott
    Categories: Programming Commenti disabilitati

    Reference: http://www.javakb.com/Uwe/ForumPost.aspx?article=java-setup:7069:1131419458.848897.223820%40z14g2000cwz.googlegroups.com

    Tags:
  • 15giu
    Categories: Programming Commenti disabilitati

    Althought development is in its initial stage and there are known bugs, the following completion scenarios are supported:

    • Package, classes and interfaces names from the project classpath
    • Engine scope Rhino object and function names
    • Fields, methods and constructors names of Rhino objects
    • Static methods invocation
    • Inline interface implementation
    • Methods signature with parameter type guessing
    Netbeans plugin: Rhino content assist

    Netbeans plugin: Rhino content assist

    Download from Netbeans plugins

    The plugin now allows to use a customized set of rules and even different ScriptEngine simply by class extension. This means that anybody can extend it to suit a Rhino interpreted language, which is the next thing I'm into.

  • 16apr
    Categories: Programming Commenti disabilitati

    This plugin allows to create a canvas and use mouse dragging (similar to iPhone/iPad scroll) to scroll every object queried by the scroller, providing a smooth scroll effect. The plugin allows customization of redraw function in order to cope with performance issues (eg.: to implement clipping of far away canvas items)

    See a live demo
    Download

    Tags:
  • 16ago
    Categories: Programming Commenti disabilitati

    A small example of javascript and css to achieve the stretch effect of a background image in website design. It's very simple and it does not require any library; yet it won't work with IE6 ("and who cares?" I'd say...)

    Source code:stretch_bg.tar.gz

    Stretch background script

    Stretch background script

  • 12gen
    Categories: Programming Commenti disabilitati

    Field definition. Here are the form field definitions; in this case they are inserted in a form alter hook.
    UPDATE 2010/2/16: Note that every combobox is linked onblur with the next one and on focus with the previous one.
    UPDATE 2010/4/12: Download the source code .

    1. function module_form_alter(&$form, $form_state, $form_id) {
    2. if($form_id == "target_form_id") {
    3. $form['field_parent']=array(
    4. '#type' => 'textfield',
    5. '#title' => t('Parent'),
    6. '#autocomplete_path' => 'autocomplete/parent',
    7. '#attributes' => array('onblur' => 'parentSelected($(this));')
    8. );
    9.  
    10. $form['field_child']=array(
    11. '#type' => 'textfield',
    12. '#title' => t('Child'),
    13. '#autocomplete_path' => 'autocomplete/child',
    14. '#attributes' => array('onfocus' => 'parentSelected($("#edit-field-parent"));'),
    15. );
    16. }
    17. }

    Client side script. When a value for the parent textfield is selected, the available values for the child textfield are restricted in a range (this is why they are linked, right). This is done altering the autocomplete path of the child

    1. function parentSelected(parent) {
    2. // Get the url from the child autocomplete hidden form element
    3. var url = $("#edit-field-child-autocomplete").val();
    4. // Alter it according to parent value
    5. url = url.replace(/\?q=autocomplete(.*)/, "?q=autocomplete/child")+"/"+parent.val();
    6. // Recreate autocomplete behaviour for the child textfield
    7. var input = $('#edit-field-child').attr('autocomplete', 'OFF')[0];
    8. recreateAutoComplete(input, url);
    9. }
    10.  
    11. function recreateAutoComplete(input, url) {
    12. $(input).unbind();
    13. var acdb = new Drupal.ACDB(url);
    14. $(input.form).submit(Drupal.autocompleteSubmit);
    15. new Drupal.jsAC(input, acdb);
    16. }

    The menu hook. The parent textfield is defined like a normal autocomplete callback, while the child's one accept a parameter from the url.

    1. function module_menu(){
    2. $items['autocomplete/parent'] = array(
    3. 'title' => 'Parent textfield autocomplete',
    4. 'page callback' => 'module_autocomp_parent',
    5. 'access callback' => TRUE,
    6. 'access arguments' => array('access content'),
    7. 'type' => MENU_CALLBACK
    8. );
    9.  
    10. $items['autocomplete/child'] = array(
    11. 'title' => 'Child textfield autocomplete',
    12. 'page callback' => 'module_autocomp_child',
    13. 'page arguments' => array(2,3),
    14. 'access callback' => TRUE,
    15. 'access arguments' => array('access content'),
    16. 'type' => MENU_CALLBACK
    17. );
    18. }

    Autocomplete callback. The autocomplete callback for the child is enabled to receive as first parameter the value specified in the parent textfield

    1. function module_autocomp_child($parentValue, $childValue) {
    2. }
  • 10ott
    Categories: Programming Commenti disabilitati

    Passing arguments to the function repeated in setInterval is not implemented in Internet explorer; even if there is a documented way to pass parameters to it, this way only works in IE for static parameters. What about, for example, if you need to set an interval for a function that, in a certain moment, clears itself?

    Fortunately, javascript can do closures (as Actionscript does); which means that, having two nested functions, you can still access outer variables from the inner function even if the outer one has already terminated execution. Using this trick, you can define setInterval parameters as outer scope vars; in other words:

    function outerScope() {
        var arg = "Hello world!";
        var innerFn = function() {
            alert(arg);
            clearInterval(interval);
        };
        var interval = setInterval(innerFn(), 1000);
    }
    outerScope();

    The code above will alert a message after one second, then clear the repeating event. This could also be done with setTimeout as obviously the same applies to setTimeout. It's elegant and cross-browser. Knowing language characteristics can help you write much less code...

  • 06ott
    Categories: Programming Commenti disabilitati

    Drupal menu Ext JS integration

    Did you ever need to use drupal with ext js? If you did, you probably wanted to use ext also for drupal main menu. Now, there is a way to display all sidebar blocks into an accordion panel, preserving html/javascript functionality.

    First step is to load ext library in one of your modules. You can accomplish this task by calling the init hook of the module, in my case called "extjs":

    function extjs_init() {
    	drupal_add_css("javascript/ext/resources/css/ext-all.css");
    	drupal_add_js("javascript/ext/adapter/ext/ext-base.js");
    	drupal_add_js("javascript/ext/ext-all.js");
    
        return $block;
    }

    Then, in the block hook, include the following html:

    <div id="extjs_sidebar"></div>
    <div id="extjs_smartbar"></div>
    <div id="extjs_tasksbar"></div>
    <script type="text/javascript">
    
    	function createCookie(name,value,days) {
    		if (days) {
    			var date = new Date();
    			date.setTime(date.getTime()+(days*24*60*60*1000));
    			var expires = "; expires="+date.toGMTString();
    		}
    		else var expires = "";
    		document.cookie = name+"="+value+expires+"; path=/";
    	}
    
    	function readCookie(name) {
    		var nameEQ = name + "=";
    		var ca = document.cookie.split(';');
    		for(var i=0;i < ca.length;i++) {
    			var c = ca[i];
    			while (c.charAt(0)==' ') c = c.substring(1,c.length);
    			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    		}
    		return null;
    	}
    
    	// Written by Jonathan Snook, http://www.snook.ca/jonathan
    	// Add-ons by Robert Nyman, http://www.robertnyman.com
    	function getElementsByClassName(oElm, strTagName, strClassName){
    		var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
    		var arrReturnElements = new Array();
    		strClassName = strClassName.replace(/\-/g, "\\-");
    		var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    		var oElement;
    		for(var i=0; i<arrElements.length; i++){
    			oElement = arrElements[i];
    			if(oRegExp.test(oElement.className)){
    				arrReturnElements.push(oElement);
    			}
    		}
    		return (arrReturnElements)
    	}
    
         /* List of all DOM event handler names.
         */
         var dom_events =
         ["onblur", "onfocus", "oncontextmenu", "onload",
         "onresize", "onscroll", "onunload", "onclick",
         "ondblclick", "onmousedown", "onmouseup", "onmouseenter",
         "onmouseleave", "onmousemove", "onmouseover",
         "onmouseout", "onchange", "onreset", "onselect",
         "onsubmit", "onkeydown", "onkeyup", "onkeypress",
         "onabort", "onerror"]; // ondasher, onprancer, etc.
    
         /*
          Fixes copy errors introduced by [email protected] element#cloneNode}, e.g. failure to copy classically-registered event handlers and the value property.
          @param {element} o The original DOM element
          @param {element} copy The result of o.cloneNode()
          @return {element} A modified copy with event handlers maintained
          */
          function fix_dom_clone(o, copy) {
    		if(o != "undefined" && copy != "undefined") {
    			for (var i = 0;i < dom_events.length;i++) {
    				var event = dom_events[i];
    				if (event in o) { copy[event] = o[event]; }
    			}
    			if ("value" in o) { copy.value = o.value; }
    			// recur
    			var o_kids = o.childNodes;
    			var c_kids = copy.childNodes;
    			for (i = 0;i < o_kids.length;i++) {
    				fix_dom_clone(o_kids[i], c_kids[i]);
    			}
    		}
          }
    
    	Ext.onReady(function(){
    
    		Ext.QuickTips.init();
    
    		/*
    		 * ================  Ricerca Altri Moduli ==================
    		 */
    		var elements = getElementsByClassName(document.getElementById("sidebar-left"), "div", "block");
    		var avoidSidebarBlock = new RegExp('(^|\\s)block-sidebar(\\s|$)');
    		var titleTag=new RegExp("<h2 .*?>(.*?)</h2>","i");
    		var reRes, childs;
    		var blocks = new Array(); var blockCopies = new Array(); var titles = new Array(); var j = 0;
    		for(var i = 0; i < elements.length; i++) {
    
    			if (avoidSidebarBlock.test(elements[i].className) ) {
    			} else
    			{
    				html = document.getElementById(elements[i].id).innerHTML;
    				reRes=titleTag.exec(html);
    				titles[j] = (reRes) ? reRes[1] : "";
    				// Prende il div di contenuto del blocco drupal. E' il secondo dei 2 div annidati nel div blocco
    				childs = elements[i].childNodes;
    				// ie non ritorna i TextNodes!!!
    				// ie non ritorna i TextNodes!!!
    				for(k = 0; k < childs.length; k++) {
    					if(childs.item(k).className == "content") {
    						blocks[j] = childs.item(k);
    						blockCopies[j] = childs.item(k).cloneNode(true);
    					};
    				}
    
    				j++;
    
    			}
    		}
    
    		// Legge il cookie impostato
    		var lastActive = readCookie("sideBar_mainmenu_selTab");
    
    		// Crea dei pannelli che salvano lo stato su cookie
    		var blockItems = new Array();
    		for (i = 0; i < blocks.length; i++) {
    			blockItems[i] = {
    				title: titles[i],
    				html: '<div id="sideBarBlock'+i+'"></div>',
    				id: 'sideBar_mainmenu_Tab'+i,
    				listeners: {
    					beforeexpand: function() {
    						document.cookie = createCookie("sideBar_mainmenu_selTab", this.getId());
    					}
    				}
    			};
    
    			if(lastActive == blockItems[i].id)
    				blockItems[i].collapsed = false;
    			else
    				blockItems[i].collapsed = true;
    		}
    
    		/*
    		 * ================  Barra laterale  =======================
    		 */
    		var lastCollapse = readCookie("sideBar_mainmenu_collapse");
    		if(lastCollapse == null) lastCollapse = "false";
    		var bd = Ext.get("extjs_sidebar");
    		var sideBar	 = new Ext.Panel({
    			title: 'Men&ugrave; principale',
    			layout:'accordion',
    			collapsible: true,
    			id: 'sideBar_mainmenu',
    			defaults: {
    				// applied to each contained panel
    				bodyStyle: 'padding:5px; overflow: auto;'
    			},
    			layoutConfig: {
    				// layout-specific configs go here
    				titleCollapse: true,
    				animate: true,
    				activeOnTop: false,
    				fill: false
    			},
    			width: 200,
    			autoHeight: true,
    			items: blockItems,
    			listeners: {
    					beforeexpand: function() {
    						document.cookie = createCookie("sideBar_mainmenu_collapse", false);
    					},
    					expand: function() {
    						this.doLayout();
    					},
    					beforecollapse: function() {
    						document.cookie = createCookie("sideBar_mainmenu_collapse", true);
    					}
    				}
    		});
    
    		sideBar.render(bd);
    		if(lastCollapse == "true")
    			sideBar.collapse(false);
    
    		for (i = 0; i < blocks.length; i++) {
    			fix_dom_clone(blocks[i], blockCopies[i]);
    			document.getElementById("sideBarBlock"+i).appendChild(blocks[i]);
    		}
    	});
    </script>
    

    I hope not to have made copy/paste errors. Notify me if you find any. Happy tweaking to those who need this!