//
//  ChoixNomenclaturaInterfaceController.java
//  ChoixNomenclaturaIC.java
//  Structure
//
//  Created by Luc-Henri Barthélémy on Wed Sep 27 2006.
//  Copyright (c) 2001 __MyCompanyName__. All rights reserved.
//
// InterfaceController
// qui gere le choix d un item dans une nomenclature en reseau
// le choix se fait via un parcours hierarchique (JTree)
//


package Structure.client;

import com.webobjects.foundation.*;
import com.webobjects.eocontrol.*;
import com.webobjects.eoapplication.*;
import com.webobjects.eodistribution.client.*;
import com.webobjects.eointerface.*;
import com.webobjects.eointerface.swing.*;

import java.util.Enumeration;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;


import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.lang.reflect.*;

public class ChoixNomenclaturaIC extends EOInterfaceController {
	
	public JTree tree; /* arbre de choix */
	public JScrollPane scrollPane; /* outline des structures */
	public JButton affectButton; /* bouton d affectation de l association */
	
	public EODisplayGroup treeDG; /* DG du treeView */
	
	protected STAssociation selectedAssociation;
	protected EOGenericRecord destinationObject;
	// gestion du treeView
	protected NSMutableArray treeNodes;
	protected NSMutableArray nodesToInvalidate;
	protected EOTreeAssociation treeAssoc;
	protected DefaultTreeModel treeModel;
	protected EOSimpleWindowController theFrame;
	protected EOModalDialogController theDialog;
	// variables transmises a l init
	protected String libelleRacine;
	protected String methodeRetour;
	protected EOInterfaceController sender;
	protected String senderMethode;
	protected EODisplayGroup destinationDG; /* DG de reception de l association */
	protected Window choixWindow;
	
	protected EOEditingContext refreshableContext;
	protected TreeSelectionListener tsl;

    public ChoixNomenclaturaIC() {
        super();
    }
	
    public ChoixNomenclaturaIC(EOEditingContext substitutionEditingContext) {
        super(substitutionEditingContext);
    }
	
	//
	// init 1
	// l affectation est geree dans l objet appelant
	// relier le bouton d affectation a setSenderAssociation
	//
    public ChoixNomenclaturaIC(EOEditingContext substitutionEditingContext, String racine, EOInterfaceController objetAppelant, String methodeRetour) {
        super(substitutionEditingContext);
		libelleRacine = racine;
		sender = objetAppelant;
		senderMethode = methodeRetour;
    }
	
	/***  exemples historiques ****/
	
	/***
	// init 2
	// ne peut bien marcher
	//
	public ChoixNomenclaturaIC(EOEditingContext substitutionEditingContext, String racine, EODisplayGroup dgDestination) {
        super(substitutionEditingContext);
		libelleRacine = racine;
		destinationDG = dgDestination;
    }
		
	***/
	
	// relier le bouton d affectation a setAssociation

	//
	// init 4  on passe une frame pour pouvoir positionner le fenetre (cf methode appelante)
	// on passe le DG au lieu de l objet pour gerer le changement de selection en cas de non modal
	//
	//
	public ChoixNomenclaturaIC(EOEditingContext substitutionEditingContext, String racine, EODisplayGroup dgDestination, EOFrameController myFrame) {
        super(substitutionEditingContext);
		libelleRacine = racine;
		destinationDG = dgDestination;
		theFrame = myFrame;
    }
	
	//
	// init 4bis (modal)  on passe une frame pour pouvoir positionner le fenetre (cf methode appelante)
	// on passe le DG au lieu de l objet pour gerer le changement de selection en cas de non modal
	//
	public ChoixNomenclaturaIC(EOEditingContext substitutionEditingContext, String racine, EODisplayGroup dgDestination, EOModalDialogController myFrame) {
        super(substitutionEditingContext);
		libelleRacine = racine;
		destinationDG = dgDestination;
		theFrame = myFrame;
    }
	
	//
	// init 5  on passe une frame pour pouvoir positionner la fenetre (cf methode appelante)
	// on passe le DG au lieu de l objet pour gerer le changement de selection en cas de non modal
	// on passe le nom de la methode retour
	//
	public ChoixNomenclaturaIC(EOEditingContext substitutionEditingContext, String racine, EODisplayGroup dgDestination, String retourMet, EOFrameController myFrame) {
        super(substitutionEditingContext);
		libelleRacine = racine;
		destinationDG = dgDestination;
		theFrame = myFrame;
		methodeRetour = retourMet;
    }
	
	
	public void connectionWasEstablished()
	{
		//System.out.println("connectionWasEstablished");
		activate();
		choixWindow = theFrame.window();
		//initEOAssociation ();
		affectButton.setEnabled(false);
	}
	
	
	//
	// l objet appelant donne en parametre la methode
	// qui permet d affecter l objet Association selectionne
	// au bon repart association (init 1)
	//
	// utile si on veut changer la destination sans
	// fermer la fenetre (en non modal)
	//
	public void setSenderAssociation()
	{
		NSSelector sel;
		if(sender != null && selectedAssociation != null)
		{
			//System.out.println("SC Structure selectionnee : "+treeController.structure().toString());
			sel = new NSSelector(senderMethode,new Class [] {STAssociation.class});
			try{
				sel.invoke(sender,selectedAssociation);
			}
			catch (NoSuchMethodException e1)
			{
				System.out.println("Methode non connue");
			}		
			catch (IllegalAccessException e2)
			{
				System.out.println("Access illegal");
			}
			catch (InvocationTargetException e3)
			{
				System.out.println("Cible interdite");
			}
		}
		
		saveAndMakeInvisible();
			
	}
	
	public void setMethodeRetour(String theMethode)
	{
		methodeRetour = theMethode;
	}

	
	//
	// methode utilise en cas de passage du DG dont la valeur doit etre affectee (init 2 et 3 4 et 5)
	//
	
	public void setAssociation()
	{

		if (destinationDG != null)
			destinationObject = (EOGenericRecord)destinationDG.selectedObject();
		else
			System.out.println("ChoixNomenclaturaIC destinationDG = null");
		
		if(destinationObject != null && selectedAssociation != null)
		{
			if(methodeRetour == null)
				destinationObject.takeStoredValueForKey(selectedAssociation, "association");
			else
				destinationObject.takeStoredValueForKey(selectedAssociation,methodeRetour);
		}
		else
			System.out.println("ChoixNomenclaturaIC destinationObject or selectedAssociation = null");
		
		if(choixWindow != null)
			choixWindow.setVisible(false);
		else
		{
			saveAndMakeInvisible();
			//System.out.println("Save && make invisible");
		}
		
		/**
			if(theFrame != null && theFrame.isModal())
		 {
				theFrame.finishModal();
		 }
		 **/
	}

	
	public void activate()
	{

		
		tree = new JTree();
		treeModel = (DefaultTreeModel)tree.getModel();
		
		
		//
		// Ajout dans le JScrollPane du nib
		//
		scrollPane.getViewport().add(tree);
		
		//setAutosizingMask(Component component, int autosizingMask);
		
		//
		// config du tree
		//
		tree.setRootVisible(false);
		tree.setScrollsOnExpand(true);
		tree.setShowsRootHandles(true);
		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		//
		// tree.setExpandsSelectedPaths(true);
		//
		// Le JTree est inconnu de la palette IB-EOF
		// par contre l interface de programmation existe bien
		// 
		
		
		treeAssoc = new EOTreeAssociation(tree);
		
		//
		// on cree les EOAssociations et les binds
		// a la mano aussi
		//
		
		//
		// ce bind est essentiel
		// sons est la relation
		// to many vers les sous classes
		//
		System.out.println("Avant binds ! ");

		treeAssoc.bindAspect("children",treeDG,"sons");
		//treeAssoc.bindAspect("children",treeDG,"toGroupesFils");
		
		// le libelle affiche dans le tree
		treeAssoc.bindAspect("value",treeDG,"libelle");
		
		//
		// la methode pour determiner s il s agit d un noeud
		//
		// methode ajoute ds l objet d entreprise
		// ici (VStructurePere) est une vue et isLeaf est cree ds la def de la vue
		//
		
		treeAssoc.bindAspect("isLeaf",treeDG,"isLeaf");
		
		
		//
		// tout se fait ici
		//
		//
		// LHB Tests de filtre
		//
		
		treeAssoc.establishConnection();
		System.out.println("apres establishConnection ! ");
		
		// prevoir la desallocation de l assoc
		disposableRegistry().addObject(treeAssoc);

		//
		// oldies : dans IB on associe un qualifier au DG pour qu il ne retourne
		// que la racine : (cStructure = '16721')
		// 
		//treeDG.setSelectsFirstObjectAfterFetch(true);
		
		//
		// le DG renvoie les structures parentes d elles memes (qualifier ds le modele)
		//
		//treeDG.fetch();
		STAssociation myRoot = null;
			if(libelleRacine.equals("") == false)
		{
			 myRoot = STAssociation.rootWithlibelle(editingContext(),libelleRacine);
		}
		if(myRoot != null)
			treeDG.setObjectArray(new NSArray(myRoot));
		
		//
		// on gere la selection a la mano 
		//
		// on ne peut pas se servir du DG
		// car dans celui-ci il n y a qu un seul objet : la racine
		//
		
		tree.addTreeSelectionListener(tsl = new TreeSelectionListener() {
			public void valueChanged(TreeSelectionEvent e) {
				//
				// on passe dans cette classe en cas de selection d un item
				// ds le treeView
				//
				
				//
				// le Jtree est constitue de DefaultMutableTreeNodes
				// qui pointent vers un userObject de type EOSwingTreePlugin._TreeNode
				// qui lui meme pointe vers un objet de type EOEntreprise
				// ici un VStructurePere
				//
				DefaultMutableTreeNode node;
				TreePath treePath;
				//STStructureUlr  myObject = null;
				selectedAssociation = null;
				//structure = null;
				//System.out.println("Value changed ! " + e.toString());
				
				node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
				//System.out.println("Path complet "+(selectedPath.toString()));
			    if(node!=null)
				{
					//
					// recuperation du record structure courant
					// putain ca craint !!!
					// il a fallut decompiler le EOSwingTreePlugin
					//
					selectedAssociation = (STAssociation)((EOSwingTreePlugin._TreeNode)node.getUserObject()).object();
					affectButton.setEnabled(true);
					//sourceDG.setObjectArray(new NSArray(selectedAssociation));
					//System.out.println("STAssociation selectionnee ! " + selectedAssociation.toString());
				}
			}
		});
		
		
	}
	
	public void dispose ()
	{
		if(choixWindow != null)
			choixWindow.setVisible(false);
		tree.removeTreeSelectionListener(tsl);
		super.dispose();
	}
	
	
	
	//
	// on peut aussi mettre en place une EOActionInsertionAssociation
	// mais le bouton d affectation ne s enable disable pas automatiquement
	// donc interet limite
	// necessite en plus un sourceDG  alimente a partir de la selection du treeDG
	//
	
	/**

	public void initEOAssociation ()
	{
		EOActionInsertionAssociation insertAssoc;
		
		insertAssoc = new EOActionInsertionAssociation(affectButton);
		
		//
		// on cree les EOAssociations et les binds
		// a la mano aussi
		//
		
		//
		// ce bind est essentiel
		// toStructuresFilles est la relation
		// to many vers les sous structures
		//
		
		insertAssoc.bindAspect("source",sourceDG,"this");
		//treeAssoc.bindAspect("children",treeDG,"toGroupesFils");
		
		// le libelle affiche dans le tree
		insertAssoc.bindAspect("destination",destinationDG,"association");
		
		//
		// la methode pour determiner s il s agit d un noeud
		//
		// methode ajoute ds l objet d entreprise
		// ici (VStructurePere) est une vue et isLeaf est cree ds la def de la vue
		//
		
		//treeAssoc.bindAspect("isLeaf",treeDG,"isLeaf");
		
		
		//
		// tout se fait ici
		//
		//
		// LHB Tests de filtre
		//
		
		insertAssoc.establishConnection();
		//sourceDG.fetch();
		
	}
	 **/
}
