Difference between revisions of "FR/Documentation/Plus loin avec Composants et boites de dialogue"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (Managing Radio Buttons Events)
m (Gérer des événements des boutons Radio)
Line 159: Line 159:
 
}
 
}
 
</source>
 
</source>
This code is working without reading the state of the radio button but I cannot certify it could be the case in any situation you will encounter. Note that we have already provided a code to access to the state of a radio button in the previous section. Note also <code>m_nDelta</code> is a new member value set to 1 by the constructor (corresponding to the default selected radio button).
+
Ce code fonctionne sans lire l'état des boutons radio (en ce qui concerne les méthodes associées "foo5" à "foo7"). Je ne peux pas vous certifier cependant que pour toutes les situations que vous rencontrerez dans votre vie de programmeur ce sera ainsi. Notez que l'on vous a déjà fourni le code pour accéder à l'état des boutons radio dans la section précédente. Notez aussi que <code>m_nDelta</code> est un nouveau membre positionnée à  1 par le constructeurr (ce qui correspond au bouton radio sélectionné par défaut).
  
 
=Using a listbox in a dialog=
 
=Using a listbox in a dialog=

Revision as of 10:41, 25 July 2009

Dans le chapitre précédent nous avons utilisé et programmé seulement deux types de contrôles dans nos boîtes de dialogue (bouton et zone de texte). Nous avons l'intention dans ce chapitre d'aller plus loin en utilisant des autres contrôles et voir comment ils fonctionnent. Vous ne pouvez pas aborder ce chapitre sans lire le chapitre précédent, particulièrement parce que seulement des extraits de code sont présentés.

Notre compteur sera encore le fil de ce chapitre même si nous finirons par l'abandonner à la fin.

Compteur avec des champs numériques

Quand nous avons construit la boîte de dialogue fonctionnant avec notre compteur, nous avons pris deux zones de texte pour nos données numériques. Parce que les zones de textes sont très souvent utilisées, notre exemple précédent reste important, mais il est temps de l'améliorer en utilisant des champs numériques. Puisque l'aspect visuel de la boîte de dialogue est pratiquement inchangée nous ne fournissons pas de copie d'écran de cette boîte.

Vous pouvez aller voir l'interface com.sun.star.awt.XNumericField et voir ainsi ce qui peut être fait avec cette interface : seules les méthodes getvalue et setValue seront utilisées dans cette section, mais vous pouvez vous amuser avec les autres méthodes. Nous ne fournirons que le code de la fonction callHandlerMethod dans le listing ci-après (voir le chapitre précédent et aussi l'interface correspondante com.sun.star.awt.XDialogEventHandler). Le code correspondant est :

// Listing 1
// c++
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("foo1")){//increment
	increment();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo2")){//decrement
	decrement();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo3")){ //setCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField1"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	setCount((sal_Int32)xNumericField->getValue());
	return sal_True;  
  } 
  if (MethodName.equalsAscii("foo4")){ //getCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField2"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	xNumericField->setValue(getCount());
	return sal_True;
   }
  return sal_False;
}

Nous n'avons pas besoin d'expliquer ce listing en détail. Nous allons maintenant nous intéresser à un autre exemple de contrôle : les boutons radio (ou cases de choix 1 parmi N).

Utiliser les boutons radio

Un bouton d'option com.sun.star.awt.UnoControlRadioButton est un simple commutateur avec deux états, qui sont sélectionnés par l'utilisateur. Les boutons d'option sont habituellement utilisés en groupe pour choisir plusieurs options, que l'utilisateur peut choisir. Bien que les boutons d'option et les cases à cocher semblent similaires, sélectionner un bouton radio se fait au détriment des autres du même groupe (mais on peut choisir plusieurs cases à cocher).

Dans notre exemple, on veut utiliser des boutons radio pour choisir la valeur de l'incrément/décrément du compteur (entre 1, 5 et 10). Voici une copie d'écran de notre boîte de dialogue :

Notre deuxime boîte de dialogue pour le compteur

où vous pouvez voir qu'une valeur de 5 pour l'incrément/décrément est choisie.

Pour cet exemple l'interface com.sun.star.awt.XRadioButton doit être consultée. Nous allons fournir deux solutions différentes à cet exemple. Nous commençons par examiner une méthode qui n'utilise que les quatre événements déjà utilisés correspondant aux quatre méthodes du compteur.

Une solution toute simple

Cette solution garde donc nos quatre méthodes gérées par callHandlerMethod() encore nommées "foo1", "foo2", .. "foo4" de l'interface com.sun.star.awt.XDialogEventHandler. Pour dire les choses autrement aucun événement nouveau n'est généré par notre boîte de dialogue. Nous présentons maintenant le code correspondant, et encore une fois avec seulement le code de callHandlerMethod. Regardez le chapitre précédent si vous voulez vous rappeler comment cela fonctionne.

// Listing 2
// C++
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("foo1")){//increment
        Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton1"));
	Reference< XRadioButton > xRadioButton(xControl,UNO_QUERY);
	if (xRadioButton->getState())  m_nDelta=1;
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton2"));
	Reference< XRadioButton > xRadioButton2(xControl,UNO_QUERY);
	if (xRadioButton2->getState())  m_nDelta=5;
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton3"));
	Reference< XRadioButton > xRadioButton3(xControl,UNO_QUERY);
	if (xRadioButton3->getState())  m_nDelta=10;
	increment();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo2")){//decrement
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton1"));
	Reference< XRadioButton > xRadioButton(xControl,UNO_QUERY);
	if (xRadioButton->getState())  m_nDelta=1;
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton2"));
	Reference< XRadioButton > xRadioButton2(xControl,UNO_QUERY);
	if (xRadioButton2->getState())  m_nDelta=5;
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton3"));
	Reference< XRadioButton > xRadioButton3(xControl,UNO_QUERY);
	if (xRadioButton3->getState())  m_nDelta=10;
	decrement();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo3")){ //setCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField1"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	setCount((sal_Int32)xNumericField->getValue());
	return sal_True;  
  } 
  if (MethodName.equalsAscii("foo4")){ //getCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField2"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	xNumericField->setValue(getCount());
	return sal_True;
   }
  return sal_False;
}

Comme vous pouvez le constater, seules les méthodes increment() et decrement() cherchent à savoir quel est le bouton radio positionné. Le code de test correspondant est similaire dans les deux méthodes et gagnerait certainement en clareté s'il était mis dans une fonction. Aucun événement n'est déclenché quand on change l'état des boutons radio dans cet exemple. Mais il est possible d'appeler une méthode chaque fois que l'état d'un bouton radio est changé : notez que dans ce cas, il vous faut fournir une méthode par bouton. Examinons cette deuxième possibilité.

Gérer des événements des boutons Radio

Chaque fois qu'un utilisateur coche ou décoche un bouton radio un événement émis, événement géré par une méthode : vous avez ainsi à éditer chacune des propriétés correspondantes des boutons et les associer à une méthode de composant (voir encore le Developer's Guide). Parceque vous avez trois boutons radio, il vous faudra ajouter trois méthodes. On voit que ce genre de solution peut devenir vite treès compliquée quand le nombre de bouton radio croit.

Le code est ainsi le suivant :

// C++
// Listing 3
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("foo1")){//increment
	increment();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo2")){//decrement
	decrement();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo3")){ //setCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField1"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	setCount((sal_Int32)xNumericField->getValue());
	return sal_True;  
  } 
  if (MethodName.equalsAscii("foo4")){ //getCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField2"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	xNumericField->setValue(getCount());
	return sal_True;
   }
   if (MethodName.equalsAscii("foo5")){ //incr/decr +/-1
	if (m_nDelta!=1) m_nDelta=1;
	return sal_True;
   }
   if (MethodName.equalsAscii("foo6")){ //incr/decr +/-5
	if (m_nDelta!=5) m_nDelta=5;
	return sal_True;
   }
   if (MethodName.equalsAscii("foo7")){ //incr/decr +/-10
	if (m_nDelta!=10) m_nDelta=10;
	return sal_True;
   }
  return sal_False;
}
 
Sequence< OUString > SAL_CALL MyCounterImpl::getSupportedMethodNames() throw (RuntimeException){
  Sequence< OUString > SeqOUStr(7);
  SeqOUStr[0]=OUString::createFromAscii("foo1");
  SeqOUStr[1]=OUString::createFromAscii("foo2");
  SeqOUStr[2]=OUString::createFromAscii("foo3");
  SeqOUStr[3]=OUString::createFromAscii("foo4");
  SeqOUStr[4]=OUString::createFromAscii("foo5");
  SeqOUStr[5]=OUString::createFromAscii("foo6");
  SeqOUStr[6]=OUString::createFromAscii("foo7");
  return SeqOUStr;
}

Ce code fonctionne sans lire l'état des boutons radio (en ce qui concerne les méthodes associées "foo5" à "foo7"). Je ne peux pas vous certifier cependant que pour toutes les situations que vous rencontrerez dans votre vie de programmeur ce sera ainsi. Notez que l'on vous a déjà fourni le code pour accéder à l'état des boutons radio dans la section précédente. Notez aussi que m_nDelta est un nouveau membre positionnée à 1 par le constructeurr (ce qui correspond au bouton radio sélectionné par défaut).

Using a listbox in a dialog

In this section, we replace the radio button control with a list box. Have a look in com.sun.star.awt.XListBox inteface. We only use the getSelectedItemPos() method in the following code.

// XDialogEventHandler implementation
// C++
// Listing 4
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("foo1")){//increment
        Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("ListBox1"));
	Reference< XListBox > xListBox(xControl,UNO_QUERY);
	switch (xListBox->getSelectedItemPos()){
	case 0:  m_nDelta=1;break;
	case 1:  m_nDelta=5;break;
	case 2:  m_nDelta=10;break;
	}
	increment();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo2")){//decrement
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("ListBox1"));
	Reference< XListBox > xListBox(xControl,UNO_QUERY);
	switch (xListBox->getSelectedItemPos()){
	case 0:  m_nDelta=1;break;
	case 1:  m_nDelta=5;break;
	case 2:  m_nDelta=10;break;
	}
	decrement();
	return sal_True;
  }
  if (MethodName.equalsAscii("foo3")){ //setCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField1"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	setCount((sal_Int32)xNumericField->getValue());
	return sal_True;  
  } 
  if (MethodName.equalsAscii("foo4")){ //getCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField2"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	xNumericField->setValue(getCount());
	return sal_True;
   }
  return sal_False;
}

which yields the dialog below :

Our Third Counter Dialog

Multi-Page Dialog

The multi-page dialog with OOoBasic is tackled here. Our goal is to use a multipage dialiog with our counter and see how it works. Our second page will be very similar as the simple dialog we have already encountered and the first one manage increment step. The great difference is we have to manage more buttons, particularly the "cancel", "<<previous", "next>>" and "OK" buttons. Because I never make multi-page dialog working before writing this section, I begin with the corresponding OOoBasic program. Template:Documentation/Note

OOoBasic program

We first give the OOoBasic program. The first part after the main is correponding to the Counter, and the seond part is corresponding to the next previous (Step) management. This management is realized with two Sub :

  • "cmdPrev_Initiated" sub,
  • "cmdNext_Initiated" sub.

When you are in Step=1 the previous button is disabled while in the Step=2 the next button has to be disabled.

REM  *****  BASIC  *****
'Listing 5
Dim Dlg As Object
Dim Count As integer 
Dim IncrDecr As integer
 
Sub Main
  DialogLibraries.LoadLibrary("Standard")
  Dlg = CreateUnoDialog(DialogLibraries.Standard.Dialog2)
'Because of Multi-page don't forget to manage Step :
  Dlg.Model.Step=1
  Dlg.Execute()
  Dlg.dispose()
End Sub
 
'Our counter begins here <-----------
Sub Increment
  Count = Count + IncrDecr
End Sub
 
Sub Decrement
  Count = Count - IncrDecr
End Sub    
 
Sub getCount
   Dim oNumericField
   oNumericField = Dlg.getControl("NumericField2")
   oNumericField.Value = Count
End Sub
 
Sub setCount
   Dim oNumericField
   oNumericField = Dlg.getControl("NumericField1")
   Count = oNumericField.Value
End Sub
' Our Counter ends here <------------
 
Sub cmdNext_Initiated
   Dim cmdNext As Object
   Dim cmdPrev As Object
   cmdPrev = Dlg.getControl("cmdPrev")
   'inspect(cmdPrev)
   cmdNext = Dlg.getControl("cmdNext")
   cmdPrev.Model.Enabled = Not cmdPrev.Model.Enabled
   cmdNext.Model.Enabled = False
   'if Next update IncrDecr
   If Dlg.Model.Step = 1 Then
     If Dlg.getControl("OptionButton1").State Then
       IncrDecr = 1
     End If
     If Dlg.getControl("OptionButton2").State Then
       IncrDecr = 5
     End If
     If Dlg.getControl("OptionButton3").State Then
       IncrDecr = 10
     End If    
   End If
   Dlg.Model.Step = Dlg.Model.Step + 1 
End Sub
 
Sub cmdPrev_Initiated
   Dim cmdNext As Object
   Dim cmdPrev As Object
   cmdPrev = Dlg.getControl("cmdPrev")
   cmdNext = Dlg.getControl("cmdNext")
   cmdPrev.Model.Enabled = False
   cmdNext.Model.Enabled = True
   Dlg.Model.Step = Dlg.Model.Step - 1 
End Sub

Note also that the radio buttons are checked only when clicking on the Next button in Step 1. The dialog then changes its appearance as follows:

Page 1 (Step 1 in OOoBasic code)

where you see "<<Previous" button disabled and

Page 2 (Step 2 in OOoBasic code)

where you see "Next>>" button is disabled.

C++ program

Our goal in this section is to reuse the previous multi-page dialog but with C++. It was easy for me to manage the Next Previous buttons but spend many hours for translating the simple OOoBasic line :

REM  *****  BASIC  *****
Dlg.Model.Step = Dlg.Model.Step + 1

Finally Java Inspector C++ code generation shows me the way. The code is as follows :

// C++
// Listing 6
// XDialogEventHandler implementation
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("increment")){//increment
	increment();
	return sal_True;
  }
  if (MethodName.equalsAscii("decrement")){//decrement
	decrement();
	return sal_True;
  }
  if (MethodName.equalsAscii("setCount")){ //setCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField1"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	setCount((sal_Int32)xNumericField->getValue());
	return sal_True;  
  } 
  if (MethodName.equalsAscii("getCount")){ //getCount
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("NumericField2"));
	Reference< XNumericField > xNumericField(xControl,UNO_QUERY);
	xNumericField->setValue(getCount());
	return sal_True;
   }
   if (MethodName.equalsAscii("cmdPrev_Initiated")){ //<<Previous
// xDialog is a parameter
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("cmdPrev"));
//com.sun.star.awt.XConrolModel
	Reference< XControlModel> xControlModel= xControl->getModel();
	Any any;
	sal_Bool Boolval;
	Reference< XPropertySet > xPropertySet( xControlModel,UNO_QUERY);
	any=xPropertySet->getPropertyValue(OUString::createFromAscii("Enabled"));
	any >>= Boolval;
	Boolval = !Boolval;
	any <<= Boolval;
	xPropertySet->setPropertyValue(OUString::createFromAscii("Enabled"),any);
 
	xControl=xControlContainer->getControl(OUString::createFromAscii("cmdNext"));
	xControlModel= xControl->getModel();
	Reference< XPropertySet > xPropertySet2( xControlModel,UNO_QUERY);
	any=xPropertySet2->getPropertyValue(OUString::createFromAscii("Enabled"));
	any >>= Boolval;
	Boolval = !Boolval;
	any <<= Boolval;
	xPropertySet2->setPropertyValue(OUString::createFromAscii("Enabled"),any);
 
// found with JavaInspector C++ code generation	:Step property management
	sal_Int32 step;
	Reference< XControl > xControl2 (xDialog,UNO_QUERY_THROW);
	xControlModel= xControl2->getModel(); 
	Reference< XPropertySet > xPropertySet3( xControlModel,UNO_QUERY);
	step = 1;
	any <<= step;
	xPropertySet3->setPropertyValue(OUString::createFromAscii("Step"),any);
	return sal_True;
   }
  if (MethodName.equalsAscii("cmdNext_Initiated")){ //Next>>
// xDialog is a parameter
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl=xControlContainer->getControl(OUString::createFromAscii("cmdPrev"));
//com.sun.star.awt.XConrolModel
	Reference< XControlModel> xControlModel= xControl->getModel();
	Any any;
	sal_Bool Boolval;
	Reference< XPropertySet > xPropertySet( xControlModel,UNO_QUERY);
	any <<= sal_True;
	xPropertySet->setPropertyValue(OUString::createFromAscii("Enabled"),any);
 
	xControl=xControlContainer->getControl(OUString::createFromAscii("cmdNext"));
	xControlModel= xControl->getModel();
	Reference< XPropertySet > xPropertySet2( xControlModel,UNO_QUERY);
	any <<= sal_False;
	xPropertySet2->setPropertyValue(OUString::createFromAscii("Enabled"),any);
// RadioButton management : not great with such if !
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton1"));
	Reference< XRadioButton > xRadioButton(xControl,UNO_QUERY);
	if (xRadioButton->getState())  m_nDelta=1;
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton2"));
	Reference< XRadioButton > xRadioButton2(xControl,UNO_QUERY);
	if (xRadioButton2->getState())  m_nDelta=5;
	xControl=xControlContainer->getControl(OUString::createFromAscii("OptionButton3"));
	Reference< XRadioButton > xRadioButton3(xControl,UNO_QUERY);
	if (xRadioButton3->getState())  m_nDelta=10;
// found with JavaInspector C++ code generation	
	sal_Int32 step;
	// the trick is here : not line below 
	// Reference< XControl >xControl2=xControlContainer->getControl(OUString::createFromAscii("Dialog1"))
	Reference< XControl > xControl2 (xDialog,UNO_QUERY_THROW);
	xControlModel= xControl2->getModel(); 
	Reference< XPropertySet > xPropertySet3( xControlModel,UNO_QUERY);
	step = 2;
	any <<= step;
	xPropertySet3->setPropertyValue(OUString::createFromAscii("Step"),any);
	return sal_True;
   } 
  return sal_False;
}
Sequence< OUString > SAL_CALL MyCounterImpl::getSupportedMethodNames() throw (RuntimeException){
  Sequence< OUString > SeqOUStr(6);
  SeqOUStr[0]=OUString::createFromAscii("increment");
  SeqOUStr[1]=OUString::createFromAscii("decrement");
  SeqOUStr[2]=OUString::createFromAscii("setCount");
  SeqOUStr[3]=OUString::createFromAscii("getCount");
  SeqOUStr[4]=OUString::createFromAscii("cmdNext_Initiated");
  SeqOUStr[5]=OUString::createFromAscii("cmdPrev_Initiated");
  return SeqOUStr;
}

See com.sun.star.awt.XControl, com.sun.star.awt.XControlContainer, com.sun.star.awt.XControlModel and com.sun.star.beans.XPropertySet, Interfaces.

We turn now to other examples where we leave our Counter only because it's too simple.

The New Tree Control

The New Tree Contol is tackled here but the corresponding article is under construction (since 2006). Frankly speaking I am not completly satisfied with this control at the moment for different reasons :

  • the tree expanded listener is useless if your node has no child (not fired). This raises probably problems when wanting to manage a dynamic tree (for instance for an introspection tool)
  • The event property in OpenOffice.org dialog editor too simple and is unable to replace event listener. For instance there is no event to manage a selection change as in Radio Button.

You probably wonder why I take time to write a documentation in such a situation. It's only because I think if the documentation lack nobody will use this control and then nobody will improve the code of this control.

The most important concept underlying the Tree Control is that of complete separation between data and how that data is displayed on the screen. This is commonly known as Model/View/Controller-design (MVC)

Our starting OOoBasic program

rvc44 posted in OOOForum (Thu Dec 20, 2007) an example in OOoBasic which serves me as starting point. I have added event listener and obtain the code snippet as follows :

REM  *****  BASIC  *****
'Listing 7
Option Explicit
'Most of this code belongs to rvc44 http://www.oooforum.org/forum/viewtopic.phtml?t=67005&highlight=
Private oDlg as Object, oLbDescription as Object
Private oTreeCtrl as Object, oTreeModel as Object
Private oMutableTreeDataModel  as Object
Private oRootNode as Object, oChildNode as Object, ogNode as Object
 
 
Sub mainTree '[Simple example: collapsing and expanding folders]
   DialogLibraries.loadLibrary("Standard")
 
   'create the dialog
   oDlg = CreateUnoDialog(DialogLibraries.Standard.SimpleTreeDialog)
   If IsNull(oDlg) Then Exit Sub
 
   'get a refrence to the control/s and its model/s
   oLbDescription = oDlg.getControl("lbDescription")
   oLbDescription.setText( "A very simple tree control with listeners." & _
                     chr(13) & chr(13) &_
                     "Expanding and collapsing happends automatically" )
 
   oTreeCtrl = oDlg.getControl("TreeControl1")
   oTreeModel = oTreeCtrl.Model   
 
   'XRay oTreeModel
   'instantiate the MutableTreeDataModel service
   oMutableTreeDataModel = createUnoService(_
         "com.sun.star.awt.tree.MutableTreeDataModel")
   'XRay oMutableTreeDataModel
   'MutableTreeDataModel implemets XMutableTreeDataModel
   'use XMutableTreeNode::createNode(
   '                  [in] any DisplayValue,
   '                  [in] boolean ChildsOnDemand )
   'to create the root node
   'If you pass to the boolean parameter TRUE as a argument,
   'the created node will be treated as a non-leaf (branch) node
   'by the XTreeControl , even when it has no child nodes.
   'If false, the node will be a leaf.
   'The root should obviously be a non-leaf node.
   oRootNode = oMutableTreeDataModel.createNode( "Root", true )  
   'use XMutableTreeNode::setRoot( [in] XMutableTreeNode RootNode )
   'to set this node as the root of the model
   oMutableTreeDataModel.setRoot(oRootNode)
 
   'now create the children of the root
 
   Dim oChildNode1
   oChildNode1 = oMutableTreeDataModel.createNode( "Parent 1", true )
   oRootNode.appendChild(oChildNode1)   
      'Create this child's own children      
            'In two steps:
            Dim oSubChildNode
            oSubChildNode = oMutableTreeDataModel.createNode(_
               "Child 1", true )
            oChildNode1.appendChild(oSubChildNode)
                  'In only one:
                  'Go deeper in the hierarchical structure
                  oSubChildNode.appendChild( _
                     oMutableTreeDataModel.createNode( _
                        "Grandson 1", false ) )
                  oSubChildNode.appendChild( _
                     oMutableTreeDataModel.createNode( _
                        "Grandson 2", false ) )
 
            'In only one:
            oChildNode1.appendChild( oMutableTreeDataModel.createNode( _
                                 "Child 2", true ) )
 
   '=======================================================================
   'As you see, the Data Model always creates the nodes
   '(XMutableDataModel::createNode)
   'and then you add it to the node you want, taking care that
   'the node created and the parent node belong to the same data model
 
   Dim oChildNode2
   oChildNode2 = oMutableTreeDataModel.createNode( "Parent 2", true )
   oRootNode.appendChild(oChildNode2)
 
   Dim oChildNode3
   oChildNode3 = oMutableTreeDataModel.createNode( "Parent 3", FALSE )
   'oChildNode3.setCollapsedGraphicURL( ANY_DOC )
   'oChildNode3.setExpandedGraphicURL( ANY_DOC )
   'oChildNode3.setNodeGraphicURL( BASIC_BRAKE )
   oRootNode.appendChild(oChildNode3)
 
   Dim oChildNode4
   oChildNode4 = oMutableTreeDataModel.createNode( "Parent 4", true )
   oRootNode.appendChild(oChildNode4)
 
   Dim oChildNode5
   oChildNode5 = oMutableTreeDataModel.createNode( "Parent 5", true )
   oRootNode.appendChild(oChildNode5)
 
   Dim oChildNode6
   oChildNode6 = oMutableTreeDataModel.createNode( "Parent 6", FALSE )
   oRootNode.appendChild(oChildNode6)
      'Although the API refrence states the following:
      '   "If you want to add child nodes to your tree on demand
      '   you can .[..] Make sure the parent node returns true
      '   for XTreeNode::hasChildsOnDemand() either by implementing
      '   XTreeNode yourself or, if you use the MutableTreeDataModel ,
      '   use XMutableTreeNode::setHasChildsOnDemand() ."
      'http://api.openoffice.org/docs/common/ref/com/sun/star/awt/tree/TreeControl.html
      Dim bHasChildernOnDemand as Boolean
      'in this case hasChildsOnDemand returns FALSE
      'bHasChildernOnDemand = oChildNode6.hasChildsOnDemand()
      Dim aChild : aChild = oMutableTreeDataModel.createNode( "Grandson", FALSE )
      'BUT the node is appended to this node that has no children on demand
      oChildNode6.appendChild(aChild)
      'Should it throw an exception?
 
   'set the data model at the TreeControlModel::DataModel property.
   oTreeModel.DataModel = oMutableTreeDataModel
 
   ' oTreeCtrl.DefaultExpandedGraphicURL = FOLDER_OPEN
   'oTreeCtrl.DefaultCollapsedGraphicURL = FOLDER_CLOSED
 
   Dim oListener,oListener2
   oListener = CreateUnoListener("Tree_","com.sun.star.awt.tree.XTreeExpansionListener")
   oListener2 = createUnoListener("Select_","com.sun.star.view.XSelectionChangeListener")
   'Xray oListener2
   oTreeCtrl.addTreeExpansionListener(oListener)
   oTreeCtrl.addSelectionChangeListener(oListener2)
   oDlg.execute()
   oTreeCtrl.removeSelectionChangeListener(oListener2)
   oTreeCtrl.removeTreeExpansionListener(oListener)
   oDlg.dispose()
End Sub
 
Sub Tree_treeExpanding(oEvt)
'oEvt.Node has methods :
  'getChildAt 	Returns the child tree node at Index .  
  'getChildCount 	Returns the number of child nodes.  
  'getParent 	Returns the parent node of this node.  
  'getIndex 	Returns the index of Node in this instances children.  
  'hasChildsOnDemand 	Returns true if the childs of this node are created on demand.  
  'getDisplayValue 	If not empty, the textual representation of this any is used as the text part of this node.  
  'getNodeGraphicURL 	The URL for a graphic that is rendered before the text part of this node.  
  'getExpandedGraphicURL 	The URL for a graphic that is rendered to visualize expanded non leaf nodes.  
  'getCollapsedGraphicURL 	The URL for a graphic that is rendered to visualize collapsed non leaf nodes.
   MsgBox("Node : " & oEvt.Node.getDisplayValue &" expanding")
   ogNode = oEvt.Node
end sub
Sub Tree_treeExpanded(oEvt)
'   MsgBox("Tree expanded")
end sub
Sub Tree_treeCollapsing(oEvt)
   'MsgBox("Tree collapsing")
end sub
Sub Tree_treeCollapsed(oEvt)
'   MsgBox("Tree collapsed")
end sub
Sub Tree_requestChildNodes(oEvt)
  'print oEvt.Node.getIndex(oEvt.Node)
    'XRay oEvt.Node
'   Msgbox ("Tree_requestChildNodes")
End Sub
Sub Tree_disposing(oEvt)
'   Msgbox ("Tree_disposing")
End Sub   
Sub Select_selectionChanged(oEvt)
  MsgBox("Selection Changed")
end sub

Here is the corresponding snapshot

Our tree control with treeExpanding listener messageBox

and the second with an other listener at work.

Our tree control with selectionChanged listener messageBox

If you want to construct such a tree with an other programming language you have to investigate the corresponding interfaces :

It's time to examine the C++ translation of this example.

C++ Code without Listener

As usual we plan to use the previous OOoBasic dialog but with C++ code. Because we only want a demonstration we will simplify the Tree. Our goal is to retrieve the expanded node but as mentioned in the section title we don't want to use listener that means we want only to manage events of the tree dialog control with our member functions. We will investigate first with OOoBasic.

Managing Events of Tree Control with OOoBasic

Our goal is simple : retrieve the selected node of the tree. We first remove all the event listener of the OOoBasic code :

REM  *****  BASIC  *****
'Listing 8
...
 
Sub mainTree '[Simple example: collapsing and expanding folders]
 
   .....
   'Dim oListener,oListener2
   'oListener = CreateUnoListener("Tree_","com.sun.star.awt.tree.XTreeExpansionListener")
   'oListener2 = createUnoListener("Select_","com.sun.star.view.XSelectionChangeListener")
   'Xray oListener2
   'oTreeCtrl.addTreeExpansionListener(oListener)
   'oTreeCtrl.addSelectionChangeListener(oListener2)
   oDlg.execute()
   'oTreeCtrl.removeSelectionChangeListener(oListener2)
   'oTreeCtrl.removeTreeExpansionListener(oListener)
   oDlg.dispose()
End Sub

We choose among the events shown below

The managable Events of a Tree Control

where you can see the Losing Focus Event ("perte de focus" in French) is used with the sub :

REM  *****  BASIC  *****
'Listing 9
Sub LosingFocus(Event As Object)
  'inspect(oTreeCtrl)
  'getSelection is member fuction of com.sun.star.awt.tree.XTreeControl interface
  'getDisplayValue is member function of com.sun.star.awt.tree.XTreeNode interface
  MsgBox(oTreeCtrl.getSelection.getDisplayValue())
End Sub

When expanding the tree and selecting a node, you only click in the Text control to see the result

Retrieving the Name of the selected Node

where you see the LosingFocus Sub above is fired.

Managing Events of Tree Control with a C++ member function

We change the preceding OOoBasic example in four ways :

  1. we simplify the tree to be displayed,
  2. we display the selection in the already present control text instead in a message Box,
  3. because we are dealing with components (and not addon) we have to start from an IDL file. I have keep the counter IDL file even if my new Dialog is unable to make it working.
  4. the "losing focus" event property is bound to a component method called "LosingFocus" (see Developper's Guide).

The new Constructor

The constructor has to display the tree in the corresponding control. To say it differently we shall find almost of the OOoBasic "mainTree" sub of the previous example in this constructor. The code is then as follows :

// cpp
// Listing 10
inline MyCounterImpl( Reference< XComponentContext > const & xContext) throw ()
        : m_xContext( xContext ) {
	m_xMCF=m_xContext->getServiceManager();
	Reference< XDesktop > xDesktop(
            m_xMCF->createInstanceWithContext( 
            OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ),
            xContext ), UNO_QUERY_THROW );
	Reference< XComponent > xcomponent = xDesktop->getCurrentComponent(); 
	Sequence< Any> Args(1);
	Args[0] <<= xcomponent;
	Reference< XDialogProvider2 > xDialog2(m_xMCF->createInstanceWithArgumentsAndContext( 
            					OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) ),
						Args,
						xContext),
						UNO_QUERY_THROW );
// Uncomment below and comment above if you want the OOoDesktop as parent of your dialog
//	Reference< XDialogProvider2 > xDialog2(m_xMCF->createInstanceWithContext( 
//            					OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) ),
//						xContext),
//						UNO_QUERY_THROW );
	Reference< XDialog > xDialog=xDialog2->createDialogWithHandler(
		OUString::createFromAscii( "vnd.sun.star.script:Standard.SimpleTreeDialog?location=application" ),
		(XCountable *)this);
// Constructing the Tree (17th Jul 2009)
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl = xControlContainer->getControl(OUString::createFromAscii("TreeControl"));
	Reference< XMutableTreeDataModel > xTreeMutDatMod (m_xMCF->createInstanceWithContext(
			OUString::createFromAscii("com.sun.star.awt.tree.MutableTreeDataModel"),xContext),UNO_QUERY_THROW);
//	Reference< XMutableTreeDataModel > xTreeMutDatMod(xTreeControl,UNO_QUERY); //NO NO NO:hangs the office
	Any any;
	any <<= OUString::createFromAscii("root");
	Reference< XMutableTreeNode > xMTN=xTreeMutDatMod->createNode(any,sal_True);
	xTreeMutDatMod->setRoot(xMTN);
	any <<= OUString::createFromAscii("Parent 1");
	Reference< XMutableTreeNode > xChildNode = xTreeMutDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
		any <<= OUString::createFromAscii("Child 1");
		Reference< XMutableTreeNode > xChildNode2 = xTreeMutDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
			any <<= OUString::createFromAscii("Grandson 1");
			Reference< XMutableTreeNode > xChildNode3 = xTreeMutDatMod->createNode(any,sal_False);
			xChildNode2->appendChild(xChildNode3);
			any <<= OUString::createFromAscii("Grandson 2");
			xChildNode3 = xTreeMutDatMod->createNode(any,sal_False);
			xChildNode2->appendChild(xChildNode3);
		any <<= OUString::createFromAscii("Child 2");
		xChildNode2 = xTreeMutDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
	any <<=  OUString::createFromAscii("Parent 2");
	xChildNode=xTreeMutDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
// set the model to see the tree in control (two hours to find the four lines below)
// translation of oTreeModel = oTreeCtrl.Model and oTreeModel.DataModel = oMutableTreeDataModel
        Reference< XControlModel > xControlModel=xControl->getModel();
	Reference< XPropertySet > xPropertySet( xControlModel,UNO_QUERY);
	any <<= xTreeMutDatMod;
	xPropertySet->setPropertyValue(OUString::createFromAscii("DataModel"),any);
// execute dialog
	xDialog->execute();
	}

The "LosingFocus" method

The LosingFocus sub in OOoBasic was very simple. I have translated it with Introspection tools and IDL documentation like com.sun.star.awt.tree.XTreeControl, com.sun.star.awt.tree.XTreeNode and com.sun.star.awt.XTextComponent.

// C++
// Listing 11
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("LosingFocus")){//When Losing Focus in Tree control
        Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl = xControlContainer->getControl(OUString::createFromAscii("TreeControl"));
// com.sun.star.awt.tree.XTreeControl
        Reference< XTreeControl > xTreeControl(xControl,UNO_QUERY);
	Any any=xTreeControl->getSelection();
	Reference< XTreeNode > xTreeNode;
        any >>= xTreeNode;
	// put the result of selection in text control
	xControl = xControlContainer->getControl(OUString::createFromAscii("lbDescription"));
        Reference< XTextComponent > xTextComponent(xControl,UNO_QUERY);
	any = xTreeNode->getDisplayValue();
	OUString OUStr;
 	any >>= OUStr;
	xTextComponent->setText(OUStr + OUString::createFromAscii(" -- DONE --"));
	return sal_True;
  }
  return sal_False;
}

This method is called when losing focus : click in the text control for instance.

Here is a snapshot of the corresponding dialog :

The new Tree Control at work

Because only a method is used you have also to change the getSupportedMethodNames() member function :

// C++
// Listing 12
Sequence< OUString > SAL_CALL MyCounterImpl::getSupportedMethodNames() throw (RuntimeException){
  Sequence< OUString > SeqOUStr(1);
  SeqOUStr[0]=OUString::createFromAscii("LosingFocus");
//  SeqOUStr[1]=OUString::createFromAscii("foo2");
//  SeqOUStr[2]=OUString::createFromAscii("foo3");
//  SeqOUStr[3]=OUString::createFromAscii("foo4");
  return SeqOUStr;
}
Documentation caution.png I am not sure xml2cmp tools which proceeds the CppComponent.uno.xml file is able to work with a type as follows :
<type>com.sun.star.awt.tree.XTreeControl</type>

In this type, "awt" is no more the module name but "tree" is. Is the problem here ? Have added it to MakeFile to make it working. If you confirm or infirm that please contact me.SergeMoutou 16:30, 17 July 2009 (UTC)

C++ code with listener

Altough I like event listener in OOoBasic I dislike them in C++ : they are easy to use in OOoBasic but hard in C++. Then I don't know when I will write such a documentation.

TO DO

Dynamic Trees

In this section, we want to Investigate how to manage a dynamic tree. A dynamic tree is a tree that is constructed on the demand.

Dynamic Trees in OOoBasic

In fact I begun to write the next section first. Because I encounter some problem I decided to write this section. After many hours I am not able to make dynamic tree working in C++ while it takes me only few minutes to make it working in OOoBasic ! FYI : dynamic Trees in C++ in the next section are working now.

I keep the initial OOoBasic tree and add two buttons : "OK" button and "add Child" Button. You select a node and when clicking on "add Child" button a child is added. Its name is the name of the selected node followed with ".n" where n is the number of the child. This is a dynamic tree because its size is not fixed. Its code is as follows:

REM  *****  BASIC  *****
'Listing 14
Option Explicit
 
Private oDlg as Object, oLbDescription as Object
Private oTreeCtrl as Object, oTreeModel as Object
Private oMutableTreeDataModel  as Object
Private oRootNode as Object, oChildNode as Object, ogNode as Object
 
 
Sub mainTree '[Simple example: collapsing and expanding folders]
   DialogLibraries.loadLibrary("Standard")
 
   oDlg = CreateUnoDialog(DialogLibraries.Standard.SimpleTreeDialog)
   If IsNull(oDlg) Then Exit Sub
 
   oTreeCtrl = oDlg.getControl("TreeControl1")
   oTreeModel = oTreeCtrl.Model   
 
   oMutableTreeDataModel = createUnoService(_
         "com.sun.star.awt.tree.MutableTreeDataModel")
 
   oRootNode = oMutableTreeDataModel.createNode( "Root", true )  
 
   oMutableTreeDataModel.setRoot(oRootNode)
 
   Dim oChildNode1
   oChildNode1 = oMutableTreeDataModel.createNode( "Parent 1", true )
   oRootNode.appendChild(oChildNode1)   
      'Create this child's own children      
            'In two steps:
            Dim oSubChildNode
            oSubChildNode = oMutableTreeDataModel.createNode(_
               "Child 1", true )
            oChildNode1.appendChild(oSubChildNode)
                  'In only one:
                  'Go deeper in the hierarchical structure
                  oSubChildNode.appendChild( _
                     oMutableTreeDataModel.createNode( _
                        "Grandson 1", false ) )
                  oSubChildNode.appendChild( _
                     oMutableTreeDataModel.createNode( _
                        "Grandson 2", false ) )
 
            'In only one:
            oChildNode1.appendChild( oMutableTreeDataModel.createNode( _
                                 "Child 2", true ) )
 
   Dim oChildNode2
   oChildNode2 = oMutableTreeDataModel.createNode( "Parent 2", true )
   oRootNode.appendChild(oChildNode2)
 
   Dim oChildNode3
   oChildNode3 = oMutableTreeDataModel.createNode( "Parent 3", FALSE )
   oRootNode.appendChild(oChildNode3)
 
   Dim oChildNode4
   oChildNode4 = oMutableTreeDataModel.createNode( "Parent 4", true )
   oRootNode.appendChild(oChildNode4)
 
   Dim oChildNode5
   oChildNode5 = oMutableTreeDataModel.createNode( "Parent 5", true )
   oRootNode.appendChild(oChildNode5)
 
   Dim oChildNode6
   oChildNode6 = oMutableTreeDataModel.createNode( "Parent 6", FALSE )
   oRootNode.appendChild(oChildNode6)
      Dim bHasChildernOnDemand as Boolean
      Dim aChild : aChild = oMutableTreeDataModel.createNode( "Grandson", FALSE )
      oChildNode6.appendChild(aChild)
 
   oTreeModel.DataModel = oMutableTreeDataModel
 
   oDlg.execute()
   oDlg.dispose()
End Sub
 
Sub addChild(Event As Object)
  Dim oParentNode, oChildNode
  Dim nb as long
  Dim oChildName as String
  oParentNode = oTreeCtrl.getSelection()
  nb = oParentNode.getChildCount()
  nb=nb+1 'I want numerotation begins with 1
  oChildName = oParentNode.getDisplayValue() + "." + nb
  oChildNode = oMutableTreeDataModel.createNode(oChildName , TRUE )
  oParentNode.appendChild(oChildNode)
  oLbDescription = oDlg.getControl("lbDescription")
  oLbDescription.setText(oChildName)
End Sub

The sub "addChild" is bound with the corresponding button. Here is a snapshot of a result:

Dynamic Tree in a Tree Control (OOoBasic)

Question : what is the last created node ? Answer see the Text control : "Root.7.1.2".

Let's turn to the corresponding C++ example.

Dynamic Trees in C++

I start from the previous tree (C++) with the same functioning as premvious section. When a node is selected, "add Child" button creates a child with name nodename.i where i is the number of the child and nodename the name of the node. For debuging intention, I put also the name of the added node in the text control.

Our new constructor

The constructor of previous section is slighty modified. Here is the corresponding code  :

// c++
// Listing 15
// added this constructor 06/06/09 
    inline MyCounterImpl( Reference< XComponentContext > const & xContext) throw ()
        : m_xContext( xContext ) {
	m_xMCF=m_xContext->getServiceManager();
//	Reference< XMutableTreeDataModel > xTreeMutDatMod(xTreeControl,UNO_QUERY); //NO NO NO:hangs the office : see below
	Reference< XMutableTreeDataModel > xMutTreeDatMod(m_xMCF->createInstanceWithContext(
			OUString::createFromAscii("com.sun.star.awt.tree.MutableTreeDataModel"),m_xContext),UNO_QUERY_THROW);
	m_xMutTreeDatMod = xMutTreeDatMod;
// If you want to use java Inspector
	Reference< XInstanceInspector > xInspector(m_xMCF->createInstanceWithContext( 
            					OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.InstanceInspector" ) ),
						m_xContext),
						UNO_QUERY_THROW );
	m_xInspector = xInspector;	
	Reference< XDesktop > xDesktop(
            m_xMCF->createInstanceWithContext( 
            OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ),
            xContext ), UNO_QUERY_THROW );
	Reference< XComponent > xcomponent = xDesktop->getCurrentComponent(); 
	Sequence< Any> Args(1);
	Args[0] <<= xcomponent;
	Reference< XDialogProvider2 > xDialog2(m_xMCF->createInstanceWithArgumentsAndContext( 
            					OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) ),
						Args,
						xContext),
						UNO_QUERY_THROW );
//	Reference< XDialogProvider2 > xDialog2(m_xMCF->createInstanceWithContext( 
//            					OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) ),
//						xContext),
//						UNO_QUERY_THROW );
	Reference< XDialog > xDialog=xDialog2->createDialogWithHandler(
		OUString::createFromAscii( "vnd.sun.star.script:Standard.SimpleTreeDialog?location=application" ),
		(XCountable *)this);
// Constructing the Tree 21th Jul 2009 (dynamic Tree)
	Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl = xControlContainer->getControl(OUString::createFromAscii("TreeControl"));
 
	Any any;
	any <<= OUString::createFromAscii("root");
	Reference< XMutableTreeNode > xMTN=m_xMutTreeDatMod->createNode(any,sal_True);
	m_xMutTreeDatMod->setRoot(xMTN);
	any <<= OUString::createFromAscii("Parent 1");
	Reference< XMutableTreeNode > xChildNode = m_xMutTreeDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
		any <<= OUString::createFromAscii("Child 1");
		Reference< XMutableTreeNode > xChildNode2 = m_xMutTreeDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
			any <<= OUString::createFromAscii("Grandson 1");
			Reference< XMutableTreeNode > xChildNode3 = m_xMutTreeDatMod->createNode(any,sal_False);
			xChildNode2->appendChild(xChildNode3);
			any <<= OUString::createFromAscii("Grandson 2");
			xChildNode3 = m_xMutTreeDatMod->createNode(any,sal_False);
			xChildNode2->appendChild(xChildNode3);
		any <<= OUString::createFromAscii("Child 2");
		xChildNode2 = m_xMutTreeDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
	any <<=  OUString::createFromAscii("Parent 2");
	xChildNode=m_xMutTreeDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
// set the model to see the tree in control (two hours to find four lines below)
// translation of oTreeModel = oTreeCtrl.Model and oTreeModel.DataModel = oMutableTreeDataModel
        Reference< XControlModel > xControlModel=xControl->getModel();
	Reference< XPropertySet > xPropertySet( xControlModel,UNO_QUERY);
	any <<= m_xMutTreeDatMod;
	xPropertySet->setPropertyValue(OUString::createFromAscii("DataModel"),any);
// execute dialog
	xDialog->execute();
	}
// end of constructor

The new callHandlerMethod

As you can see in the code below only "addChild" method is used in this example:

// C++
// Listing 16
// XDialogEventHandler implementation
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("LosingFocus")){//When Losing Focus in Tree control
	// not used in this example
	return sal_True;
  }
  if (MethodName.equalsAscii("addChild")){//add a child to the selected node
// First retrieve the selection
        Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl = xControlContainer->getControl(OUString::createFromAscii("TreeControl"));	
	// com.sun.star.awt.tree.XTreeControl
        Reference< XTreeControl > xTreeControl(xControl,UNO_QUERY);
	Any any=xTreeControl->getSelection();
	// Parent
	Reference< XMutableTreeNode > xParentNode;
	any >>= xParentNode;	
// adding
	sal_Int32 nb=xParentNode->getChildCount();
	// Child
	OUString OUStr;
 
	any=xParentNode->getDisplayValue();
	any >>= OUStr;
	OUStr = OUStr + OUString::createFromAscii(".") + OUString::valueOf((sal_Int32)++nb);
// put the new node name in text control
	xControl = xControlContainer->getControl(OUString::createFromAscii("lbDescription"));
        Reference< XTextComponent > xTextComponent(xControl,UNO_QUERY);
	xTextComponent->setText(OUStr);
	any <<= OUStr;
	Reference< XMutableTreeNode > xChildMutTreeNode = m_xMutTreeDatMod->createNode(any ,sal_True);
// Introspection
//	any <<= xChildMutTreeNode;
//	m_xInspector->inspect(any,OUString::createFromAscii("Inspector"));        
	xParentNode->appendChild(xChildMutTreeNode);
	return sal_True;
  }
  return sal_False;
}
Sequence< OUString > SAL_CALL MyCounterImpl::getSupportedMethodNames() throw (RuntimeException){
  Sequence< OUString > SeqOUStr(2);
  SeqOUStr[0]=OUString::createFromAscii("LosingFocus");
  SeqOUStr[1]=OUString::createFromAscii("addChild");
  return SeqOUStr;
}

Here is a snapshot

Dynamic Tree in a Tree Control

where you can see all the nodes added.

Home Page

HomePageCpp.png Return to Document Home page

See also

Personal tools