Artifact Content
Not logged in

Artifact 9da5605d97dbb6357d7254002ef64e5227d51db2


     1  /* This file is a part of CanDyDOC fileset.
     2     File is written by Victor Nakoryakov and placed into the public domain.
     3  
     4     This file is javascript with classes that represents explorer window.
     5     And things related to navigation. */
     6     
     7  var explorer = new Explorer();
     8  
     9  ///////////////////////////////////////////////////////////////////////////////
    10  // Current symbol marker class constructor
    11  ///////////////////////////////////////////////////////////////////////////////
    12  function Marker()
    13  {
    14      this.top    = document.createElement("div");
    15      this.middle = document.createElement("div");
    16      this.bottom = document.createElement("div");
    17      this.container = document.createElement("div");
    18      
    19      this.setTo = function(term)
    20      {
    21          // find definition related to `term`
    22          var def = term.nextSibling;
    23          while (def && def.nodeName != "DD")
    24              def = def.nextSibling;
    25              
    26          var defHeight = 0;
    27          var childrenHeight = 0; // children of current declaration
    28          if (def)
    29          {
    30              defHeight = def.offsetHeight;
    31              var child = def.firstChild;
    32              
    33              // traverse until DL tag, until children definition
    34              while (child && child.nodeName != "DL")
    35                  child = child.nextSibling;
    36                  
    37              if (child)
    38                  childrenHeight = child.offsetHeight;
    39          }
    40          
    41          this.top.style.height = term.offsetHeight;
    42          this.middle.style.height = defHeight - childrenHeight;
    43          this.bottom.style.height = childrenHeight;
    44          
    45          if (childrenHeight == 0)
    46              this.bottom.style.display = "none";
    47          else
    48              this.bottom.style.display = "";
    49          
    50          this.container.style.left = getLeft(term) - 8;
    51          this.container.style.top = getTop(term);
    52          this.container.style.display = "";
    53      }
    54          
    55      ///////////////////////////////////////////////////////////////////////////
    56      this.container.style.position = "absolute";
    57      this.container.style.display = "none";
    58      
    59      this.top.className = "markertop";
    60      this.middle.className = "markermiddle";
    61      this.bottom.className = "markerbottom";
    62      
    63      this.container.appendChild(this.top);
    64      this.container.appendChild(this.middle);
    65      this.container.appendChild(this.bottom);
    66      
    67      //document.body.appendChild( this.container );
    68      
    69      // Workaround bug in IE 5/6. We can not append anything to document body until
    70      // full page load.
    71      window.marker = this;
    72      if (window.addEventListener)
    73          window.addEventListener("load", new Function("document.body.appendChild( window.marker.container );"), false);
    74      else if (window.attachEvent)
    75          window.attachEvent("onload", new Function("document.body.appendChild( window.marker.container );"));
    76  }
    77  
    78  ///////////////////////////////////////////////////////////////////////////////
    79  // Outline class constructor
    80  ///////////////////////////////////////////////////////////////////////////////
    81  function Outline()
    82  {
    83      this.tree           = new TreeView();
    84      this.mountPoint     = null;    
    85      this.writeEnabled   = false;
    86      this.marker         = new Marker();        
    87      this.classRegExp    = new RegExp;
    88      this.structRegExp   = new RegExp;
    89      this.enumRegExp     = new RegExp;
    90      this.templateRegExp = new RegExp;
    91      this.aliasRegExp    = new RegExp;
    92      this.funcRegExp     = new RegExp;
    93      
    94      this.incSymbolLevel = function()
    95      {
    96          if (this.mountPoint == null)
    97              this.mountPoint = this.tree.children[ 0 ];
    98          else
    99              this.mountPoint = this.mountPoint.lastChild();
   100      }
   101  
   102      this.decSymbolLevel = function()
   103      {
   104          // place icons near items according to extracted below type
   105          for (var i = 0; i < this.mountPoint.children.length; ++i)
   106          {
   107              child = this.mountPoint.children[i];
   108              var term = child.termRef;
   109              
   110              // find first span node
   111              var n = term.firstChild;
   112              while (n && n.nodeName != "SPAN")
   113                  n = n.nextSibling;
   114              
   115              if (!n) // shouldn't happen
   116                  continue;
   117              
   118              var iconSrc;
   119              if (n.firstChild.nodeName == "#text")
   120              {
   121                  var text = n.firstChild.data; // text before declaration
   122                  
   123                  if ( this.classRegExp.test(text) )
   124                      iconSrc = "candydoc/img/outline/class.gif";
   125                  else if ( this.structRegExp.test(text) )
   126                      iconSrc = "candydoc/img/outline/struct.gif";
   127                  else if ( this.enumRegExp.test(text) )
   128                      iconSrc = "candydoc/img/outline/enum.gif";
   129                  else if ( this.templateRegExp.test(text) )
   130                      iconSrc = "candydoc/img/outline/template.gif";
   131                  else if ( this.aliasRegExp.test(text) )
   132                      iconSrc = "candydoc/img/outline/alias.gif";
   133                  else // function or variable? check whether '(' ')' exists on the right
   134                  {
   135                      var np = n.firstChild;
   136                      while (np && np.nodeName != "SCRIPT") // find our script "onDecl"
   137                          np = np.nextSibling;
   138                          
   139                      if (np && np.nextSibling && np.nextSibling.nodeName == "#text" &&
   140                          this.funcRegExp.test(np.nextSibling.data))
   141                      {
   142                          iconSrc = "candydoc/img/outline/func.gif";
   143                      }
   144                      else
   145                          iconSrc = "candydoc/img/outline/var.gif";
   146                  }
   147              }
   148              else // enum member ?
   149                  iconSrc = "candydoc/img/outline/var.gif";
   150                      
   151              child.icon.src = iconSrc;
   152              child.icon.width = 16;
   153              child.icon.height = 16;
   154          }
   155          
   156          this.mountPoint = this.mountPoint.parentNode;
   157      }
   158  
   159      this.addDecl = function(decl)
   160      {
   161          function getLastLeaf(elem)
   162          {
   163              if (elem.childNodes.length > 0)
   164                  return getLastLeaf(elem.lastChild);
   165              else
   166                  return elem;
   167          }
   168  
   169          function getCurrentTerm()
   170          {
   171              var ret = getLastLeaf( document.getElementById("content") );
   172              while (ret && ret.nodeName != "DT")
   173                  ret = ret.parentNode;
   174              
   175              return ret;
   176          }
   177          
   178          if (this.writeEnabled)
   179          {
   180              var node = this.mountPoint.createChild(decl);
   181              node.termRef = getCurrentTerm();
   182              node.setOnclick( new Function("explorer.outline.mark(this.termRef);") );
   183          }
   184      }
   185  
   186      this.mark = function(term)
   187      {
   188          this.marker.setTo(term);
   189          window.scrollTo(0, getTop(term) - getWindowHeight() / 6);    
   190      }
   191          
   192      
   193      this.classRegExp.compile("(.*\b)?class(\b.*)?");
   194      this.structRegExp.compile("(.*\b)?struct(\b.*)?");
   195      this.enumRegExp.compile("(.*\b)?enum(\b.*)?");
   196      this.templateRegExp.compile("(.*\b)?template(\b.*)?");
   197      this.aliasRegExp.compile("(.*\b)?alias(\b.*)?");
   198      this.funcRegExp.compile(/.*\(.*/);    
   199  }
   200  
   201  
   202  
   203  
   204  ///////////////////////////////////////////////////////////////////////////////
   205  // Package explorer class constructor
   206  ///////////////////////////////////////////////////////////////////////////////
   207  function PackageExplorer()
   208  {
   209      this.tree = new TreeView(true);    
   210      
   211      this.addModule = function(mod)
   212      {
   213          var moduleIco = "candydoc/img/outline/module.gif";
   214          var packageIco = "candydoc/img/outline/package.gif";
   215  
   216          var path = mod.split("\.");
   217          var node = this.tree.branch(path[0]);
   218          if ( !node )
   219          {
   220              node = this.tree.createBranch(path[0], (path.length == 1) ? moduleIco : packageIco);
   221              // modified by k.inaba : link for toplevel module
   222              if (path.length == 1)
   223                  node.setRef(path[0] + ".html");
   224          }
   225          
   226          for (var i = 1; i < path.length; ++i)
   227          {
   228              var prev = node;
   229              node = node.child(path[i]);
   230              if (!node)
   231                  node = prev.createChild(path[i], (path.length == i + 1) ? moduleIco : packageIco);
   232                  
   233              if (path.length == i + 1)
   234                  node.setRef(path[i] + ".html");
   235          }
   236      }
   237  }
   238  
   239  
   240  
   241  ///////////////////////////////////////////////////////////////////////////////
   242  // Explorer class constructor
   243  ///////////////////////////////////////////////////////////////////////////////
   244  function Explorer()
   245  {
   246      this.outline         = new Outline();
   247      this.packageExplorer = new PackageExplorer();
   248      this.tabs            = new Array();
   249      this.tabCount        = 0;
   250      
   251      this.initialize = function(moduleName)
   252      {
   253          this.tabArea = document.getElementById("tabarea");
   254          this.clientArea = document.getElementById("explorerclient");
   255          
   256          // prevent text selection
   257          this.tabArea.onmousedown = new Function("return false;");
   258          this.tabArea.onclick = new Function("return true;");
   259          this.tabArea.onselectstart = new Function("return false;");
   260          this.clientArea.onmousedown = new Function("return false;");
   261          this.clientArea.onclick = new Function("return true;");
   262          this.clientArea.onselectstart = new Function("return false;");
   263          
   264          this.outline.tree.createBranch( moduleName, "candydoc/img/outline/module.gif" );
   265          
   266          // create tabs
   267          this.createTab("Outline", this.outline.tree.domEntry);
   268          this.createTab("Package", this.packageExplorer.tree.domEntry);
   269      }
   270      
   271      this.createTab = function(name, domEntry)
   272      {
   273          var tab = new Object();
   274          this.tabs[name] = tab;
   275          this.tabCount++;
   276          
   277          tab.domEntry = domEntry;
   278          tab.labelSpan = document.createElement("span");
   279          
   280          if (this.tabCount > 1)
   281          {
   282              tab.labelSpan.className = "inactivetab";
   283              tab.domEntry.style.display = "none";
   284          }
   285          else
   286          {
   287              tab.labelSpan.className = "activetab";
   288              tab.domEntry.style.display = "";
   289          }
   290          
   291          tab.labelSpan.appendChild( document.createTextNode(name) );
   292          tab.labelSpan.owner = this;
   293          tab.labelSpan.onclick = new Function("this.owner.setSelection('" + name + "');");
   294          
   295          this.tabArea.appendChild( tab.labelSpan );
   296          this.clientArea.appendChild( domEntry );
   297      }
   298      
   299      this.setSelection = function(tabName)
   300      {
   301          for (name in this.tabs)
   302          {
   303              this.tabs[name].labelSpan.className = "inactivetab";
   304              this.tabs[name].domEntry.style.display = "none";
   305          }
   306          
   307          this.tabs[tabName].labelSpan.className = "activetab";
   308          this.tabs[tabName].domEntry.style.display = "";
   309      }
   310  }