Lab : Réduire une application AIR dans un dock ou dans le systray selon l'OS en AS3

Préliminaires

Les packages dont vous aurez besoin (en plus du reste smiley myconcept:actionscript & php développement et management pour applications RIA (internet, intranet et extranet))

	import flash.desktop.DockIcon;
	import flash.desktop.NativeApplication;
	import flash.desktop.NotificationType;
	import flash.desktop.SystemTrayIcon;
	import flash.display.NativeMenu;
	import flash.display.NativeMenuItem;
	import flash.events.Event;
	import flash.events.InvokeEvent;
	import flash.events.MouseEvent;
	...

Détection du support dock ou systray & préparation de l'icône

Détection du support dock ou systray pour une application AIR

Rien de bien sorcier il y a deux détections possible celle du dock et celle du systray. Cette détection permettra de choisir l'objet à instancier (un dockIcon ou un SystrayIcon) mais les deux auront le même menu et l'icône pourra être gérée de la même façons. Par facilité je ferai tjrs référence au dock dans le nom de mes variables et fonction car il est plus compréhensible de dire 'dock' et 'undock' que 'gosystray' et 'gounsystray' smiley myconcept:actionscript & php développement et management en Belgique.

private function initDockSupport():void{
	if(NativeApplication.supportsDockIcon){
		debug('OS  a un  dock ');
		var dockIcon:DockIcon = NativeApplication.nativeApplication.icon;
		NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE,undock);
	} else if (NativeApplication.supportsSystemTrayIcon){
		debug('OS a un systray');
		var sysTrayIcon:SystemTrayIcon = NativeApplication.nativeApplication.icon;
		sysTrayIcon.tooltip = 'Tooltip lors du mouseover de la souris au-dessus du systray';
		sysTrayIcon.addEventListener(MouseEvent.CLICK,undock);
	}
	else {
		debug('no systray & no dock');
	}
}

Les icônes à prévoir

En fait l'icône qui va apparaitre dans le systray ou le dock sera un bitmapData. AIR vous donne la possibiliter d'envoyer un array de bitmapData à l'OS qui choisira celui qu'il juge le plus adapter aux paramètres d'affichage du user.


Personnellement, je crée un mc avec les différents statuts de mon icone en 3 exemplaires avec +- de détails selon le type de résolution que je vais proposer (16x16 à 128x128). Je vais ensuite faire un draw() du mc avec le statut que je souhaite et l'envoye à l'OS :

/**
*  Met à jour l'icone du systray en fonction du statut du user
*  @param   Boolean     isOnline        Si le user est online ou pas
*  @return  void
**/
private function updateDockIcon(isOnline:Boolean):void{
	if(isOnline){
	    //Set Full detailed Icon (High def) to the online status
		DocIcon_HD.gotoAndStop('online');
		//Set Low def icon to online status
		DocIcon_LD.gotoAndStop('online');
	}
    else {
		DocIcon_HD.gotoAndStop('offline');
		DocIcon_LD.gotoAndStop('offline');
    }	
    var DocIcon_HD_bmpdata:BitmapData=new BitmapData(DocIcon_HD.width,DocIcon_HD.height,true,0x000000);
    var DocIcon_LD_bmpdata:BitmapData=new BitmapData(DocIcon_LD.width,DocIcon_LD.height,true,0x000000);			
	DocIcon_HD_bmpdata.draw(DocIcon_HD);
	DocIcon_LD_bmpdata.draw(DocIcon_LD);
	//Change the DockIcon only if minimized in the systray or dock
	if(stage.nativeWindow.visible==false){
		NativeApplication.nativeApplication.icon.bitmaps = [DocIcon_HD_bmpdata,DocIcon_LD_bmpdata];
	}
	//Remove icon from systray or Dock
	else {
        NativeApplication.nativeApplication.icon.bitmaps = [];
    }
}

Avec cet exemple je fais 3 actions :

  • Si viens de cacher l'application, ça va faire apparaitre l'icone dans le dock ou le systray
  • Si je viens de 'dédocker', réafficher la fenêtre de l'application, ça va faire disparaitre l'icone du dock ou du systray
  • Si l'application est déjà réduite et que le statut du user a changé, l'icône va changer d'apparence

Avec un peu d'imagination on peut animer l'icône du dock/systray

Le menu qui affiche les commandes du clic droit sur l'icône

On a détecté le dock ou le systray et on sait maintenant ajouter/retirer l'icône du systray. Il ne reste plus que permettre certaines commande en faisant un clic droit sur l'icone du dock ou du systray.

/**
* Retourne le menu contextuel de l'icone du systray
* @return   NativeMenu
**/
private function getDockMenu():NativeMenu{
    var contextualIconMenu:NativeMenu = new NativeMenu();
    //La commande qui va 'undocker' l'application 
    var unDockCommand: NativeMenuItem = new NativeMenuItem('Show  Only4Access');
    contextualIconMenu.addItem(unDockCommand);
    unDockCommand.addEventListener(Event.SELECT, undock);
    //pour Windows uniquement
    if(NativeApplication.supportsSystemTrayIcon){
        var exitCommand: NativeMenuItem = new NativeMenuItem('Exit  Only4Access');
        contextualIconMenu.addItem(exitCommand);
        exitCommand.addEventListener(Event.SELECT, closeZeBox);
    }
    return iconMenu;
}

Et pour attribuer ce menu on fait :

//pour le dock
dockIcon.menu = getDockMenu();
//pour le systray
sysTrayIcon.menu = getDockMenu();

Le tout mélangé smiley myconcept:actionscript php project developments & managements

Heu n'ayant pas Flash sur la machine où j'ai rédigé ce texte, je n'ai pas pu tester le code de cette page mais ça devrait le faire smiley myconcept:actionscript & php développement et management en Belgique.

Pour plus d'infos sur les commandes de bases (agrandir, minimiser,...) cf l'article du lab à ce sujet.

/**
 * Détection et instanciation du dock
 * @return  void 
 **/ 
private function initDockSupport():void{
	if(NativeApplication.supportsDockIcon){
		debug('OS  a un  dock ');
		var dockIcon:DockIcon = NativeApplication.nativeApplication.icon;
		NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE,undock);
		dockIcon.menu = getDockMenu();
	} else if (NativeApplication.supportsSystemTrayIcon){
		debug('OS a un systray');
		var sysTrayIcon:SystemTrayIcon = NativeApplication.nativeApplication.icon;
		sysTrayIcon.tooltip = 'Tooltip lors du mouseover de la souris au-dessus du systray';
		sysTrayIcon.addEventListener(MouseEvent.CLICK,undock);
		sysTrayIcon.menu = getDockMenu();
	}
	else {
		debug('no systray & no dock');
	}
}

/**
 * Close the AIR Window
 * @param   *       e       The Event > set to * 'cause will be a MouseEvent or Event following the target (stage click (DisplayObject) or systray click (NativeMenuItem)).    
 * @return  void
 **/ 
private function closeZeBox(e:*):void{
    stage.nativeWindow.close();
}

/**
* Réduit ds le systray
* @param    *   e           The Event > set to * 'cause will be a MouseEvent or Event following the target (stage click (DisplayObject) or systray click (NativeMenuItem)).
* @return void
**/  
private function dock(e:*):void{
    debug('Docking...');
    stage.nativeWindow.visible = false;
	updateDockIcon();
}

/**
* Restaure la fenêtre et fait disparaitre l'icone du systray
* @param    *   e           The Event > set to * 'cause will be a MouseEvent or Event following the target (stage click (DisplayObject) or systray click (NativeMenuItem)).
* @return void
**/ 
private function undock(e:*):void{
	debug('Undocking...');
	stage.nativeWindow.visible = true; 
	// ou  utiliser NativeWindow.activate() ça force le premier plan en plus de le rendre visible
	updateDockIcon();
}

/**
* Retourne le menu contextuel de l'icone du systray
* @return   NativeMenu
**/
private function getDockMenu():NativeMenu{
    var contextualIconMenu:NativeMenu = new NativeMenu();
    //La commande qui va 'undocker' l'application 
    var unDockCommand: NativeMenuItem = new NativeMenuItem('Show  MyAIRApp');
    contextualIconMenu.addItem(unDockCommand);
    unDockCommand.addEventListener(Event.SELECT, undock);
    //pour Windows uniquement
    if(NativeApplication.supportsSystemTrayIcon){
        var exitCommand: NativeMenuItem = new NativeMenuItem('Exit  MyAIRApp');
        contextualIconMenu.addItem(exitCommand);
        exitCommand.addEventListener(Event.SELECT, closeZeBox);
    }
    return iconMenu;
}

/**
*  Met à jour l'icone du systray
*  @return  void
**/
private function updateDockIcon():void{
    var DocIcon_bmpdata:BitmapData=new BitmapData(DocIcon_mc.width,DocIcon_mc.height,true,0x000000);
    //Change the DockIcon only if minimized in the systray or dock
    if(stage.nativeWindow.visible==false){
        NativeApplication.nativeApplication.icon.bitmaps = [DocIcon_bmpdata];
    }
    //Remove icon from systray or Dock
    else {
        NativeApplication.nativeApplication.icon.bitmaps = [];
    }
}
- MY Concept FlashPlayer Loader for actionscript demo's and movie/animation player-