text: #include "global.h"
  #include "staticfunctions.h"
  #include "dcolordialog.h"
  #include "networks.h"
  #include "geoshaderfactory.h"
  #include "propertyeditor.h"
  
  #include <QDomDocument>
  
  
  Networks::Networks()
  {
    m_networks.clear();
    m_geoSpriteShader = 0;
    m_geoShadowShader = 0;
  }
  
  Networks::~Networks()
  {
    clear();
  }
  
  
  void
  Networks::show()
  {
    for (int i=0; i<m_networks.count(); i++)
      {
        m_networks[i]->setShow(true);
        m_networks[i]->addInMouseGrabberPool();
      }
  }
  
  void
  Networks::hide()
  {
    for (int i=0; i<m_networks.count(); i++)
      {
        m_networks[i]->setShow(false);
        m_networks[i]->removeFromMouseGrabberPool();
      }
  }
  
  bool
  Networks::show(int i)
  {
    if (i >= 0 && i < m_networks.count())
      return m_networks[i]->show();
    else
      return false;
  }
  
  void
  Networks::setShow(int i, bool flag)
  {
    if (i >= 0 && i < m_networks.count())
      {
        m_networks[i]->setShow(flag);
        if (flag)
  	m_networks[i]->addInMouseGrabberPool();
        else
  	m_networks[i]->removeFromMouseGrabberPool();
      }
  }
  
  void
  Networks::clear()
  {
    for (int i=0; i<m_networks.count(); i++)
      delete m_networks[i];
  
    m_networks.clear();
  }
  
  void
  Networks::allGridSize(int &nx, int &ny, int &nz)
  {
    nx = 0;
    ny = 0;
    nz = 0;
  
    if (m_networks.count() == 0)
      return;
  
    m_networks[0]->gridSize(nx, ny, nz);
  
    for(int i=1; i<m_networks.count();i++)
      {
        int mx, my, mz;
        m_networks[i]->gridSize(mx, my, mz);
        nx = qMax(nx, mx);
        ny = qMax(ny, my);
        nz = qMax(nz, mz);
      }
  }
  
  void
  Networks::allEnclosingBox(Vec& boxMin,
  			  Vec& boxMax)
  {
    if (m_networks.count() == 0)
      return;
  
    boxMin = Vec(0,0,0);
    boxMax = Vec(0,0,0);
  
    m_networks[0]->enclosingBox(boxMin, boxMax);
  
    for(int i=1; i<m_networks.count();i++)
      {
        Vec bmin, bmax;
        m_networks[i]->enclosingBox(bmin, bmax);
        boxMin = StaticFunctions::minVec(boxMin, bmin);
        boxMax = StaticFunctions::maxVec(boxMax, bmax);
      }
  }
  
  bool
  Networks::isInMouseGrabberPool(int i)
  {
    if (i < m_networks.count())
      return m_networks[i]->isInMouseGrabberPool();
    else
      return false;
  }
  void
  Networks::addInMouseGrabberPool(int i)
  {
    if (i < m_networks.count())
      m_networks[i]->addInMouseGrabberPool();
  }
  void
  Networks::addInMouseGrabberPool()
  {
    for(int i=0; i<m_networks.count(); i++)
      m_networks[i]->addInMouseGrabberPool();
  }
  void
  Networks::removeFromMouseGrabberPool(int i)
  {
    if (i < m_networks.count())
      m_networks[i]->removeFromMouseGrabberPool();
  }
  
  void
  Networks::removeFromMouseGrabberPool()
  {
    for(int i=0; i<m_networks.count(); i++)
      m_networks[i]->removeFromMouseGrabberPool();
  }
  
  
  bool
  Networks::grabsMouse()
  {
    for(int i=0; i<m_networks.count(); i++)
      {
        if (m_networks[i]->grabsMouse())
  	return true;
      }
    return false;
  }
  
  void
  Networks::addNetwork(QString flnm)
  {
    NetworkGrabber *tg = new NetworkGrabber();
    if (tg->load(flnm))
      m_networks.append(tg);
    else
      delete tg;
  }
  
  void
  Networks::postdraw(QGLViewer *viewer)
  {
    for(int i=0; i<m_networks.count();i++)
      {
        int x,y;
        m_networks[i]->mousePosition(x,y);
        m_networks[i]->postdraw(viewer,
  			     x, y,
  			     m_networks[i]->grabsMouse(),
  			     i);
      }
  }
  
  void
  Networks::predraw(QGLViewer *viewer,
  		  double *Xform,
  		  Vec pn,
  		  QList<Vec> clipPos,
  		  QList<Vec> clipNormal,
  		  QList<CropObject> crops,
  		  Vec lightVector)
  {
    for(int i=0; i<m_networks.count();i++)
      m_networks[i]->predraw(viewer,
  			   Xform,
  			   pn,
  			   clipPos, clipNormal,
  			   crops,
  			   lightVector);
  }
  
  void
  Networks::draw(QGLViewer *viewer,
  	      float pnear, float pfar,
  	      bool backlit)
  {
    for(int i=0; i<m_networks.count();i++)
      {
        m_networks[i]->draw(viewer,
  			  m_networks[i]->grabsMouse(),
  			  pnear, pfar,
  			  backlit);
  
        glUseProgramObjectARB(0);
      }
  
  }
  
  bool
  Networks::keyPressEvent(QKeyEvent *event)
  {
    for(int i=0; i<m_networks.count(); i++)
      {
        if (m_networks[i]->grabsMouse())
  	{
  	  if (event->key() == Qt::Key_G)
  	    {
  	      m_networks[i]->removeFromMouseGrabberPool();
  	      return true;
  	    }
  	  if (event->key() == Qt::Key_Delete ||
  	      event->key() == Qt::Key_Backspace ||
  	      event->key() == Qt::Key_Backtab)
  	    {
  	      m_networks[i]->removeFromMouseGrabberPool();
  	      m_networks.removeAt(i);
  	      return true;
  	    }
  	  if (event->key() == Qt::Key_Space)
  	    {
  	      PropertyEditor propertyEditor;
  	      QMap<QString, QVariantList> plist;
  
  	      QVariantList vlist;
  
  	      vlist.clear();
  	      vlist << QVariant("double");
  	      vlist << QVariant(m_networks[i]->vopacity());
  	      vlist << QVariant(0.0);
  	      vlist << QVariant(1.0);
  	      vlist << QVariant(0.1); // singlestep
  	      vlist << QVariant(1); // decimals
  	      plist["vertex opacity"] = vlist;
  
  	      vlist.clear();
  	      vlist << QVariant("colorgradient");
  	      QGradientStops vstops = m_networks[i]->vstops();
  	      for(int s=0; s<vstops.size(); s++)
  		{
  		  float pos = vstops[s].first;
  		  QColor color = vstops[s].second;
  		  int r = color.red();
  		  int g = color.green();
  		  int b = color.blue();
  		  int a = color.alpha();
  		  vlist << QVariant(pos);
  		  vlist << QVariant(r);
  		  vlist << QVariant(g);
  		  vlist << QVariant(b);
  		  vlist << QVariant(a);
  		}
  	      plist["vertex color gradient"] = vlist;
  
  
  	      vlist.clear();
  	      vlist << QVariant("combobox");
  	      vlist << QVariant(m_networks[i]->vertexAttribute());
  	      for(int va=0; va<m_networks[i]->vertexAttributeCount(); va++)
  		{
  		  QString vstr;
  		  float vmin, vmax;
  		  vstr = m_networks[i]->vertexAttributeString(va);
  		  m_networks[i]->vMinmax(va, vmin, vmax);
  		  vlist << QVariant(QString("%1 : %2 : %3 %4").\
  				    arg(va).arg(vstr).arg(vmin).arg(vmax));
  		}
  	      plist["vertex attribute list"] = vlist;
  
  
  	      int iva = m_networks[i]->vertexAttribute();
  	      float vmin, vmax;
  	      m_networks[i]->userVminmax(iva, vmin, vmax);
  	      vlist.clear();
  	      vlist << QVariant("string");
  	      vlist << QVariant(QString("%1 %2").arg(vmin).arg(vmax));
  	      plist["vertex attribute bounds"] = vlist;
  
  
  
  
  
  	      vlist.clear();
  	      vlist << QVariant("double");
  	      vlist << QVariant(m_networks[i]->eopacity());
  	      vlist << QVariant(0.0);
  	      vlist << QVariant(1.0);
  	      vlist << QVariant(0.1); // singlestep
  	      vlist << QVariant(1); // decimals
  	      plist["edge opacity"] = vlist;
  
  	      vlist.clear();
  	      vlist << QVariant("combobox");
  	      vlist << QVariant(m_networks[i]->edgeAttribute());
  	      for(int ea=0; ea<m_networks[i]->edgeAttributeCount(); ea++)
  		{
  		  QString estr;
  		  float emin, emax;
  		  estr = m_networks[i]->edgeAttributeString(ea);
  		  m_networks[i]->eMinmax(ea, emin, emax);
  		  vlist << QVariant(QString("%1 : %2 : %3 %4").\
  				    arg(ea).arg(estr).arg(emin).arg(emax));
  		}
  	      plist["edge attribute list"] = vlist;
  
  
  	      int nea = m_networks[i]->edgeAttribute();
  	      float emin, emax;
  	      m_networks[i]->userEminmax(nea, emin, emax);
  	      vlist.clear();
  	      vlist << QVariant("string");
  	      vlist << QVariant(QString("%1 %2").arg(emin).arg(emax));
  	      plist["edge attribute bounds"] = vlist;
  
  	      vlist.clear();
  	      vlist << QVariant("colorgradient");
  	      QGradientStops estops = m_networks[i]->estops();
  	      for(int s=0; s<estops.size(); s++)
  		{
  		  float pos = estops[s].first;
  		  QColor color = estops[s].second;
  		  int r = color.red();
  		  int g = color.green();
  		  int b = color.blue();
  		  int a = color.alpha();
  		  vlist << QVariant(pos);
  		  vlist << QVariant(r);
  		  vlist << QVariant(g);
  		  vlist << QVariant(b);
  		  vlist << QVariant(a);
  		}
  	      plist["edge color gradient"] = vlist;
  
  	      vlist.clear();
  	      QString mesg;
  	      mesg += QString("scalev : %1\n").arg(m_networks[i]->scaleV());
  	      mesg += QString("scalee : %1\n").arg(m_networks[i]->scaleE());
  	      vlist << mesg;
  	      plist["message"] = vlist;
  
  	      vlist.clear();
  	      plist["command"] = vlist;
  
  	      QStringList keys;
  	      keys << "vertex color gradient";
  	      keys << "vertex opacity";
  	      keys << "vertex attribute list";
  	      keys << "vertex attribute bounds";
  	      keys << "gap";
  	      keys << "edge color gradient";
  	      keys << "edge opacity";
  	      keys << "edge attribute list";
  	      keys << "edge attribute bounds";
  	      keys << "command";
  	      keys << "message";
  	      
  
  	      propertyEditor.set("Network Parameters", plist, keys);
  	      QMap<QString, QPair<QVariant, bool> > vmap;
  
  	      if (propertyEditor.exec() == QDialog::Accepted)
  		{
  		  QString cmd = propertyEditor.getCommandString();
  		  if (!cmd.isEmpty())
  		    return processCommand(i, cmd);
  
  		  vmap = propertyEditor.get();
  		}
  	      else
  		return true;
  
  
  	      for(int ik=0; ik<keys.count(); ik++)
  		{
  		  QPair<QVariant, bool> pair = vmap.value(keys[ik]);
  
  		  if (pair.second)
  		    {
  		      if (keys[ik] == "vertex color gradient")
  			{
  			  QGradientStops stops = propertyEditor.getGradientStops(keys[ik]);
  			  m_networks[i]->setVstops(stops);
  			}
  		      else if (keys[ik] == "vertex opacity")
  			m_networks[i]->setVOpacity(pair.first.toDouble());
  		      else if (keys[ik] == "vertex attribute list")
  			{
  			  QString vstr = pair.first.toString();
  			  QStringList vl = vstr.split(":");
  			  m_networks[i]->setVertexAttribute(vl[0].toInt());
  			}
  		      else if (keys[ik] == "vertex attribute bounds")
  			{
  			  QString vstr = pair.first.toString();
  			  QStringList vl = vstr.split(" ");
  			  if (vl.count() == 2)
  			    m_networks[i]->setUserVminmax(vl[0].toDouble(),
  							  vl[1].toDouble());
  			}
  		      else if (keys[ik] == "edge color gradient")
  			{
  			  QGradientStops stops = propertyEditor.getGradientStops(keys[ik]);
  			  m_networks[i]->setEstops(stops);
  			}
  		      else if (keys[ik] == "edge opacity")
  			m_networks[i]->setEOpacity(pair.first.toDouble());
  		      else if (keys[ik] == "edge attribute list")
  			{
  			  QString estr = pair.first.toString();
  			  QStringList el = estr.split(":");
  			  m_networks[i]->setEdgeAttribute(el[0].toInt());
  			}
  		      else if (keys[ik] == "edge attribute bounds")
  			{
  			  QString estr = pair.first.toString();
  			  QStringList el = estr.split(" ");
  			  if (el.count() == 2)
  			    m_networks[i]->setUserEminmax(el[0].toDouble(),
  							  el[1].toDouble());
  			}
  		    }
  		}
  	      
  	      return true;
  	    }
  	}
      }
  
    return false;
  }
  
  void
  Networks::createSpriteShader()
  {
    if (m_geoSpriteShader)
      glDeleteObjectARB(m_geoSpriteShader);
  
    QString shaderString;
  
    shaderString = GeoShaderFactory::genSpriteShaderString();
    m_geoSpriteShader = glCreateProgramObjectARB();
    if (! GeoShaderFactory::loadShader(m_geoSpriteShader,
  				     shaderString))
      exit(0);
  
    m_spriteParm[0] = glGetUniformLocationARB(m_geoSpriteShader, "spriteTex");
  }
  
  void
  Networks::createShadowShader(Vec attenuation)
  {
    if (m_geoShadowShader)
      glDeleteObjectARB(m_geoShadowShader);
  
    float r = attenuation.x;
    float g = attenuation.y;
    float b = attenuation.z;
  
    QString shaderString;
  
    shaderString = GeoShaderFactory::genSpriteShadowShaderString(r,g,b);
    m_geoShadowShader = glCreateProgramObjectARB();
    if (! GeoShaderFactory::loadShader(m_geoShadowShader,
  				     shaderString))
      exit(0);
  
    m_shadowParm[0] = glGetUniformLocationARB(m_geoShadowShader, "spriteTex");
  }
  
  void
  Networks::save(const char *flnm)
  {
    QDomDocument doc;
    QFile f(flnm);
    if (f.open(QIODevice::ReadOnly))
      {
        doc.setContent(&f);
        f.close();
      }
  
    QDomElement topElement = doc.documentElement();
  
    for(int i=0; i<m_networks.count(); i++)
      {
        QDomElement de = m_networks[i]->domElement(doc);
        topElement.appendChild(de);
      }
  
    QFile fout(flnm);
    if (fout.open(QIODevice::WriteOnly))
      {
        QTextStream out(&fout);
        doc.save(out, 2);
        fout.close();
      }
  }
  
  void
  Networks::load(const char *flnm)
  {
    QDomDocument document;
    QFile f(flnm);
    if (f.open(QIODevice::ReadOnly))
      {
        document.setContent(&f);
        f.close();
      }
  
    QDomElement main = document.documentElement();
    QDomNodeList dlist = main.childNodes();
    for(int i=0; i<dlist.count(); i++)
      {
        if (dlist.at(i).nodeName() == "network")
  	{
  	  QDomElement de = dlist.at(i).toElement();
  
  	  NetworkGrabber *tg = new NetworkGrabber();
  	  if (tg->fromDomElement(de))	    
  	    m_networks.append(tg);
  	  else
  	    delete tg;
  	}
      }
  
  }
  
  QList<NetworkInformation>
  Networks::get()
  {
    QList<NetworkInformation> tinfo;
  
    for(int i=0; i<m_networks.count(); i++)
      tinfo.append(m_networks[i]->get());
  
    return tinfo;
  }
  
  void
  Networks::set(QList<NetworkInformation> tinfo)
  {
    if (tinfo.count() == 0)
      {
        clear();
        return;
      }
      
    if (m_networks.count() == 0)
      {
        for(int i=0; i<tinfo.count(); i++)
  	{
  	  NetworkGrabber *tgi = new NetworkGrabber();	
  	  if (tgi->set(tinfo[i]))
  	    m_networks.append(tgi);
  	  else
  	    delete tgi;
  	}
  
        return;
      }
  
  
    QVector<int> present;
    present.resize(tinfo.count());
    for(int i=0; i<tinfo.count(); i++)
      {
        present[i] = -1;
        for(int j=0; j<m_networks.count(); j++)
  	{
  	  if (tinfo[i].filename == m_networks[j]->filename())
  	    {
  	      present[i] = j;
  	      break;
  	    }
  	}
      }
  
    QList<NetworkGrabber*> tg;
    tg = m_networks;
    
    m_networks.clear();
    for(int i=0; i<tinfo.count(); i++)
      {
        NetworkGrabber *tgi;
  
        if (present[i] >= 0)
  	tgi = tg[present[i]];
        else
  	tgi = new NetworkGrabber();
  	
        if (tgi->set(tinfo[i]))
  	m_networks.append(tgi);
        else
  	delete tgi;
      }
  
    for(int i=0; i<tg.count(); i++)
      {
        if (! m_networks.contains(tg[i]))
  	delete tg[i];
      }
  
    tg.clear();
  }
  
  bool
  Networks::processCommand(int id, QString cmd)
  {
    bool ok;
    cmd = cmd.toLower();
    QStringList list = cmd.split(" ", QString::SkipEmptyParts);
    
    if (list[0] == "scale")
      {
        float scl = 1.0;
        if (list.count() > 1)
  	scl = list[1].toFloat();
        m_networks[id]->setScale(scl);
        return true;
      }
    else if (list[0] == "scalev")
      {
        float scl = 1.0;
        if (list.count() > 1)
  	scl = list[1].toFloat();
        m_networks[id]->setScaleV(scl);
        return true;
      }
    else if (list[0] == "scalee")
      {
        float scl = 1.0;
        if (list.count() > 1)
  	scl = list[1].toFloat();
        m_networks[id]->setScaleE(scl);
        return true;
      }
    return false;
  }
  