Forums : Xul, Xbl, JS...

Aller à la discussion :  Plus récente Plus ancienne

# Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : Raphael

Date : 12/05/2010 15:58

Bonjour,

Je sais actuellement utiliser l'interface "treeview" classique en créant un tableau possédant plusieurs caractéristiques :

// Elevelist (Liste des élèves filtrés)
var elevelistview = {
	rowCount : 0,
getCellText : function(row,col){
		if (col.id == "eleve_id") return eleves[row].Eleve_ID;
		if (col.id == "eleve_login") return eleves[row].Login;
		if (col.id == "eleve_nom") return eleves[row].Nom;
		if (col.id == "eleve_prenom") return eleves[row].Prenom;
		if (col.id == "eleve_classes") return eleves[row].Classes;
		if (col.id == "eleve_naissance") return eleves[row].Naissance;
		else return null;
	},
	setTree: function(treebox){ this.treebox = treebox; },
	isContainer: function(row){ return false; },
	isSeparator: function(row){ return false; },
	isSorted: function(row){ return false; },
	getLevel: function(row){ return 0; },
	getImageSrc: function(row,col){
		return null;
	},
	getRowProperties: function(row,props){},
	getCellProperties: function(row,col,props){},
	getColumnProperties: function(colid,col,props){}
};

C'est très facile à utiliser et très performant, même pour un grand nombre de lignes.

Maintenant, j'aimerais pouvoir utiliser un treeview, mais avec des arbres dépliables. Comment puis-je adapter facilement mon code pour obtenir quelque chose comme ça (interface codée en "dur", ne fonctionne pas) :

Regarder le 2ème tree, celui avec des arbres dépliables

Merci d'avance.

EDIT : Après recherches sur Xulfr et MDC, il semble que cela soit quand même compliqué de passer par un treeview non ? L'exemple est bien fait mais uniquement pour une colonne ! Adapter cet exemple à mon problème pour plusieurs colonnes me semble difficile.

Je me demandais donc si je ne pouvais pas faire autrement :

  • Au pire : Fonctionner en créant/supprimant manuellement mes lignes avec le DOM... Je sais que c'est très peu performant, mais pour mon tableau, je n'aurai que 60/70 lignes maxi...
  • Si je peux faire plus simple en utilisant un gabarit, je veux bien... Mais RDF me donne des boutons. Il m'a semblé voir passé il y a quelques mois/années des nouvelles concernant des gabarits XML ? Car le XML, je préfère... Il me faudrait donc juste créer un XML à la volée et le filer à mon tree, ça me parait envisageable mais je voudrais avoir confirmation de cette possibilité ?

Merci.

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : mothsart

Date : 18/05/2010 00:32

Renseignes-toi sur les fonctions "toggleOpenState", "isContainerOpen", "getLevel". La page tree ou en anglais tree et surtout son exemple devrait te parler d'avantage. Sinon, tu peux toujours t'amuser à regarder comment fonctionne des extensions de qualité tel que FireFTP.

Pour les gabarits XML, je n'ai pas essayé.

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : aMan

Date : 18/05/2010 12:41

Bonjour,

Tu peux aussi penser à du SQLIte pour peupler ton arbre... car rien ne t'empeche de créer une table sqlite temporaire a chaqu'un de tes affichages.

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : Raphael

Date : 19/05/2010 06:06

Ben en fait mes données sont dans une BDD Sqlite.

Mais pour des treeview non hiérarchisé, je n'utilise pas les templates SQLite mais j'extraie les données pour les stocker comme il faut dans un tableau.

Est-ce simple un tree hiérarchisé avec les templates SQLite ?

Ce que j'aimerais, c'est un "modèle" de code où y aurait quasiment rien à retoucher, et je n'aurais qu'à adapter la structure de mes données en amont pour les faire s'incruster dans ce pan de code.

Mon problème actuel est que l'exemple sur MDC et xulfr.org est super... mais pour une unique colonne... Et je ne sais pas vraiment comment l'adapter pour du multi-colonnes.

Me faudrait un exemple basique, car étudier FireFTP me parait complexe (beaucoup de code imbriqué, de POO,...) pour voir la structure du bouzin.

Merci à vous deux pour vos réponses en tous cas =)

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : mothsart

Date : 19/05/2010 13:23

mais t'as au moins testé le code sur mdc?

C'est bien un tree avec 2 colonnes. C'est suffisent même si tu comptes travailler sur d'avantages de colonnes.

(le principe reste le même)

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : Raphael

Date : 20/05/2010 06:08

Es-tu sûr ?

Pour moi, le tree simple est sur 2 colonnes (ligne, date), mais le tree hiérarchique qui m'intéresse n'a pour moi qu'une seule colonne (Element) pour déplier Solide, Gazeux, Liquide...

La structure des données pour plusieurs colonnes doit être radicalement différente, ainsi que le code qui affiche ces données il me semble... non ?

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : mothsart

Date : 21/05/2010 00:36

Ok, je crois que je n'avais pas pris le temps de bien cerner ta question.

Tu veux un tree dépliable et d'autres colonnes.

Certes, il n'y a pas d'exemple tout conçu mais la structure d'un tree m'a vite mis sur la voie.

J'ai modifié le code de l'exemple pour tes besoins...ça devrait te convenir au poil maintenant.

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window onload="init();"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree id="elementList" flex="1">
  <treecols>
    <treecol id="element" label="Élément" primary="true" flex="1"/>
    <treecol id="other" label="Autre" flex="1"/>
  </treecols>
  <treechildren/>
</tree>
<script>
<![CDATA[
var treeView = {
  childData : {
    Solides: ["Argent", "Or", "Plomb"],
    Liquides: ["Mercure"],
    Gaz: ["Hélium", "Azote"]
  },
  visibleData : [
    ["Solides", true, false],
    ["Liquides", true, false],
    ["Gaz", true, false]
  ],
    otherData : [
    "exemple_1",
    "exemple_2",
    "exemple_3"
  ],
  treeBox: null,
  selection: null,
  get rowCount()                     { return this.visibleData.length; },
  setTree: function(treeBox)         { this.treeBox = treeBox; },
  getCellText: function(idx, column) {
    dump(column.id+'\n');
    if(column.id == 'element'){
      return this.visibleData[idx][0];
    }
    else{
      return this.otherData[idx];
    }
  },
  isContainer: function(idx)         { return this.visibleData[idx][1]; },
  isContainerOpen: function(idx)     { return this.visibleData[idx][2]; },
  isContainerEmpty: function(idx)    { return false; },
  isSeparator: function(idx)         { return false; },
  isSorted: function()               { return false; },
  isEditable: function(idx, column)  { return false; },
  getParentIndex: function(idx) {
    if (this.isContainer(idx)) return -1;
    for (var t = idx - 1; t >= 0 ; t--) {
      if (this.isContainer(t)) return t;
    }
  },
  getLevel: function(idx) {
    if (this.isContainer(idx)) return 0;
    return 1;
  },
  hasNextSibling: function(idx, after) {
    var thisLevel = this.getLevel(idx);
    for (var t = idx + 1; t < this.visibleData.length; t++) {
      var nextLevel = this.getLevel(t)
      if (nextLevel == thisLevel) return true;
      else if (nextLevel < thisLevel) return false;
    }
  },
  toggleOpenState: function(idx) {
    var item = this.visibleData[idx];
    if (!item[1]) return;
    if (item[2]) {
      item[2] = false;
      var thisLevel = this.getLevel(idx);
      var deletecount = 0;
      for (var t = idx + 1; t < this.visibleData.length; t++) {
        if (this.getLevel(t) > thisLevel) deletecount++;
        else break;
      }
      if (deletecount) {
        this.visibleData.splice(idx + 1, deletecount);
        this.treeBox.rowCountChanged(idx + 1, -deletecount);
      }
    }
    else {
      item[2] = true;
      var label = this.visibleData[idx][0];
      var toinsert = this.childData[label];
      for (var i = 0; i < toinsert.length; i++) {
        this.visibleData.splice(idx + i + 1, 0, [toinsert[i], false]);
      }
      this.treeBox.rowCountChanged(idx + 1, toinsert.length);
    }
  },
  getImageSrc: function(idx, column) {},
  getProgressMode : function(idx,column) {},
  getCellValue: function(idx, column) {},
  cycleHeader: function(col, elem) {},
  selectionChanged: function() {},
  cycleCell: function(idx, column) {},
  performAction: function(action) {},
  performActionOnCell: function(action, index, column) {},
  getRowProperties: function(idx, column, prop) {},
  getCellProperties: function(idx, column, prop) {},
  getColumnProperties: function(column, element, prop) {},
};
function init() {
  document.getElementById("elementList").view = treeView;
}
]]></script>
</window>

Tu remarqueras que j'ai rajouté une colonne <treecol /> à la structure et que dans la fonction getCellText je trie les donnés en fonction de la colonne.

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : Raphael

Date : 21/05/2010 08:35

Déja, un grand merci pour le temps passé sur mon problème.

Je vois, en fait, tu as juste rajouté une petite modif dans getCellText, comme je fais pour mon tree sans arbre. Et tu as rajouté des données dans un tableau séparé.

Je vais tester dans la matinée mais j'ai un doute sur la validité.

On dirait que tu affiches "exemple_1" sur la même ligne que "Solides" alors que ce n'est pas ce que je veux... Solides est le conteneur... mais c'est quand il est déplié que je veux afficher le contenu sur plusieurs colonnes, genre "couleur, beauté, prix".

A mon sens, il faudrait modifier la fonction toggleOpenState() pour jouer avec childData.

Et je ne sais pas trop comment structurer mes données... car là, tu proposes un tableau à part, pas vraiment relié à mes contenants, et marchant pour une colonne ?

Enfin, peut-être ai-je maintenant tellement l'habitude copier/coller mon propre code de logiciel en logiciel que je ne vois plus d'autres manières de faire que la mienne, c'est très possible aussi XD

Je vais faire quelques tests et je te tiens au courant. Ca a au moins eu l'avantage de me motiver pour cette aventure car j'étais sur le point de commencer à coder 2/3 fonctions de gestions "manuelles" du tree façon DOM.

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : Raphael

Date : 22/05/2010 08:30

Bon, après une journée d'essais, je progresse : j'arrive à afficher plusieurs colonnes, quitte à afficher un peu n'importe quelle information.

Plus je teste et plus je relis le code, plus je comprends comment il fonctionne.

Là, je pars en week-end mais j'ai un très bonne piste pour parvenir à mes fins.

Si cela fonctionne, je posterai le code histoire de voir s'il n'est pas trop "pourri".

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : mothsart

Date : 22/05/2010 16:25

Bon, j'ai remanié mon code et je pense m'approcher de ce que tu veux.

J'ai cherché à répondre à ton attente au niveau fonctionnel... niveau optimisation, il reste certainement du travail mais ce n'était pas vraiment le but.

L'important est que tu comprennes le code et l'adapte à tes besoins.

Optimiser, c'est bien mais si tu relis ton code dans quelques mois et qu'il t'ai trop indigeste... autant ne pas l'optimiser du tout!

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window onload="init();"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree id="elementList" flex="1">
  <treecols>
    <treecol id="element" label="Élément" primary="true" flex="1"/>
    <treecol id="color" label="Couleur" flex="1"/>
    <treecol id="beauty" label="Beauté" flex="1"/>
    <treecol id="price" label="Prix" flex="1"/>
  </treecols>
  <treechildren/>
</tree>
<script>
<![CDATA[
var treeView = {
  childData : {
    Bijoux: [
      ["Collier de saphirs",["bleu", "extra", "1000€"]],
      ["Boucles d'oreilles", ["or", "belles", "200€"]],
      ["Bague", ["argent", "peu apprécié", "150€"]]
    ],
    Vêtements: [
      ["Jeans", ["bleu", "cool", "30€"]],
      ["T-shirt", ["blanc", "sobre", "10€"]],
      ["chaussettes", ["multicolore", "superbe", "20€"]]
    ],
    Jouets: [
      ["Legos", ["rouge", "sympa", "80€"]],
      ["Nounours", ["marron", "attachant", "10€"]],
      ["balançoire", ["verte et jaune", "géant", "320€"]],
      ["vélo", ["gris", "très moche", "170€"]]
    ]
  },
  visibleData : [
    ["Bijoux", true, false],
    ["Vêtements", true, false],
    ["Jouets", true, false]
  ],
  colorData : [
    "",
    "",
    ""
  ],
  beautyData : [
    "",
    "",
    ""
  ],
  priceData : [
    "",
    "",
    ""
  ],
  treeBox: null,
  selection: null,
  get rowCount()                     { return this.visibleData.length; },
  setTree: function(treeBox)         { this.treeBox = treeBox; },
  getCellText: function(idx, column) {
    if(column.id == 'element'){
      return this.visibleData[idx][0];
    }
    else if(column.id == 'color'){
      return this.colorData[idx];
    }
    else if(column.id == 'beauty'){
      return this.beautyData[idx];
    }
    else if(column.id == 'price'){
      return this.priceData[idx];
    }
  },
  isContainer: function(idx)         { return this.visibleData[idx][1]; },
  isContainerOpen: function(idx)     { return this.visibleData[idx][2]; },
  isContainerEmpty: function(idx)    { return false; },
  isSeparator: function(idx)         { return false; },
  isSorted: function()               { return false; },
  isEditable: function(idx, column)  { return false; },
  getParentIndex: function(idx) {
    if (this.isContainer(idx)) return -1;
    for (var t = idx - 1; t >= 0 ; t--) {
      if (this.isContainer(t)) return t;
    }
  },
  getLevel: function(idx) {
    if (this.isContainer(idx)) return 0;
    return 1;
  },
  hasNextSibling: function(idx, after) {
    var thisLevel = this.getLevel(idx);
    for (var t = idx + 1; t < this.visibleData.length; t++) {
      var nextLevel = this.getLevel(t)
      if (nextLevel == thisLevel) return true;
      else if (nextLevel < thisLevel) return false;
    }
  },
  toggleOpenState: function(idx) {
    var item = this.visibleData[idx];
    if (!item[1]) return;
    if (item[2]){
      item[2] = false;
      var thisLevel = this.getLevel(idx);
      var deletecount = 0;
      for (var t = idx + 1; t < this.visibleData.length; t++) {
        if (this.getLevel(t) > thisLevel) deletecount++;
        else break;
      }
      if (deletecount) {
        this.visibleData.splice(idx + 1, deletecount);
        this.colorData.splice(idx + 1, deletecount);
        this.beautyData.splice(idx + 1, deletecount);
        this.priceData.splice(idx + 1, deletecount);
        this.treeBox.rowCountChanged(idx + 1, -deletecount);
      }
    }
    else {
      item[2] = true;
      var label = this.visibleData[idx][0];
      var toinsert = this.childData[label];
      for (var i = 0; i < toinsert.length; i++) {
        this.visibleData.splice(idx + i + 1, 0, [toinsert[i][0], false]);
        this.colorData.splice(idx + i + 1, 0, toinsert[i][1][0]);
        this.beautyData.splice(idx + i + 1, 0, toinsert[i][1][1]);
        this.priceData.splice(idx + i + 1, 0, toinsert[i][1][2]);
      }
      this.treeBox.rowCountChanged(idx + 1, toinsert.length);
    }
  },
  getImageSrc: function(idx, column) {},
  getProgressMode : function(idx,column) {},
  getCellValue: function(idx, column) {},
  cycleHeader: function(col, elem) {},
  selectionChanged: function() {},
  cycleCell: function(idx, column) {},
  performAction: function(action) {},
  performActionOnCell: function(action, index, column) {},
  getRowProperties: function(idx, column, prop) {},
  getCellProperties: function(idx, column, prop) {},
  getColumnProperties: function(column, element, prop) {},
};
function init() {
  document.getElementById("elementList").view = treeView;
}
]]></script>
</window>

# Re: Treeview hiérarchisé ? Quelle structure de tableaux ?

Envoyé par : Raphael

Date : 26/05/2010 06:01

Intéressant ! Mon approche des données était un peu différente. En fait j'avais remarqué que la fonction toggle ne faisait qu'insérait des lignes en répercutant le nombre là où ça va bien. J'étais donc parti sur l'idée de stocker le même type de données dans childdata et visibledata, et filtrer via des "if" dans getCellText().

J'essaierai ta méthode et si j'ai le temps j'irai au bout de la mienne pour voir si la structure de données n'est pas plus simple à gérer... car ensuite, je dois prévoir un structure d'enregistrement, avec des ID, tout ça...

Merci beaucoup en tous cas :)

Il n'est plus possible de poster des messages dans ce forum.


Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.

Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.