1.14. La clase GanttView

Utilizaremos esta clase para modificar la vista(agrupación) que tenemos del panel que contiene la información de los nodos.

Para este ejemplo tendremos un botón en nuestro formulario el cual nos cambiará la vista de nuestros registros; lo que nos permitirá verlos agrupados por proyecto o trabajador.

En la imágenes podréis ver como quedará nuestro formulario una vez hagamos las modificaciones de este post.

La primera imagen muestra registros de los empleados y el botón tiene el texto Project para indicar que si presionamos cambiaremos a la vista de proyectos.


Si presionamos el botón automáticamente cambiará la agrupación y el texto que se muestra en el botón.



Lo primero que nos haremos será crearnos un enumerado para indicarle la vista que debe mostrar.



El siguiente paso es hacer una clase GanttView. Para eso nos crearemos una  que extienda de dicha clase.
A continuación os pondré una serie de métodos con los que realizar el cambio de vista.


class XBB_GanttView_SchedEmpl extends GanttView
{
     NoYes mustReloadData;
     // current view
     XBB_GanttView currentView;
     NoYes currentViewChanged;
     NoYes workerViewGroupingChanged;
     NoYes workerViewInitiallyCollapsed;
     NoYes workerViewInitiallyCollapsedChanged;
     NoYes projectViewGroupingChanged;
     NoYes projectViewInitiallyCollapsed;
     NoYes projectViewInitiallyCollapsedChanged;
 

     #define.CurrentVersion(1)
     #localmacro.CurrentList
         currentView,
         currentViewChanged,
         workerViewGroupingChanged,
         workerViewInitiallyCollapsed,
         workerViewInitiallyCollapsedChanged,
         projectViewGroupingChanged,
         projectViewInitiallyCollapsed,
         projectViewInitiallyCollapsedChanged
     #endmacro
}




El siguiente método lo llamaremos para cambiar la agrupación del Gantt.



protected boolean applyChangedValues()
{
    XBB_GanttActiveXVarchart_SchedEmpl ganttVisualization = this.parmGanttClient().parmGanttVisualization();

    if(!super()) 
    {
       return false;   
    }
    if(mustReloadData)
    {
       return ganttClient.reload();

    }

    // Worker view
    if(currentView == XBB_GanttView::Worker)
    {
        if(workerViewGroupingChanged || currentViewChanged)        {
           ganttVisualization.groupByCurrentView();
        }
           else if(workerViewInitiallyCollapsedChanged)
        {
           ganttVisualization.collapseAllGroups(workerViewInitiallyCollapsed);
        }
    }
    // Project view
    else if(currentView == XBB_GanttView::Project)    {
        if(projectViewGroupingChanged || currentViewChanged)
        {
           ganttVisualization.groupByCurrentView();
        }
        else if(projectViewInitiallyCollapsedChanged)
        {
           ganttVisualization.collapseAllGroups(projectViewInitiallyCollapsed);
        }
    }
    return true;
 }

 


Al llamar a este método le asignaremos a nuestra variable currentView la vista actual.


public void changeCurrentView()
{     
     if(currentView == XBB_GanttView::Worker)
     {
        this.parmCurrentView(XBB_GanttView::Project);
     }
 
    else if(currentView == XBB_GanttView::Project)
     {
        this.parmCurrentView(XBB_GanttView::Worker);
     }

 
    needRefreshVisualization = false;

     this.applyChanges();
}
 



public XBB_GanttView getOppositeView()
{
    
switch (currentView)
     {
      
case XBB_GanttView::Project:
            return XBB_GanttView::Worker;
       case XBB_GanttView::Worker:
            return XBB_GanttView::Project;
       default:
            throw error(strfmt("@SYS27147", classId2Name(classidget(this))));
     }
}




Inicializaremos los valores de las vistas por defecto.

public void initParmDefault()
{   

   super();
   
   this.initParmDefaultCurrentView();
   this.initParmDefaultProjectView();
   this.initParmDefaultWorkerView();
}
 


protected void initParmDefaultCurrentView()
{
   currentView = XBB_GanttView::Worker;
}
 


protected void initParmDefaultProjectView()
{
   projectViewInitiallyCollapsed = NoYes::Yes;
}
 


protected void initParmDefaultWorkerView()
{
   workerViewInitiallyCollapsed = NoYes::Yes;
}
 


public container pack()
{
  
 return [#CurrentVersion,#CurrentList];
}


public XBB_GanttView parmCurrentView(XBB_GanttView _currentView = currentView)
{
 
  if(currentView != _currentView)
   {
      currentViewChanged = NoYes::Yes;
      currentView        = _currentView;
   }

  
return currentView;
}

public GanttClient parmGanttClient(GanttClient _ganttClient = ganttClient)
{
 
  return super(_ganttClient);
}



En los siguientes métodos le indicaremos si los grupos deben estar colapsados o desplegados.


public NoYes parmProjectViewInitiallyCollapsed(NoYes _projectViewInitiallyCollapsed = projectViewInitiallyCollapsed)
{
  ;
 
if(projectViewInitiallyCollapsed != _projectViewInitiallyCollapsed)
  {
     projectViewInitiallyCollapsedChanged = NoYes::Yes;
     projectViewInitiallyCollapsed = _projectViewInitiallyCollapsed;
  }

 
return projectViewInitiallyCollapsed;
}

public NoYes parmWorkerViewInitiallyCollapsed(NoYes _workerViewInitiallyCollapsed = workerViewInitiallyCollapsed)
{
 
if(workerViewInitiallyCollapsed != _workerViewInitiallyCollapsed)
  {
     workerViewInitiallyCollapsedChanged = NoYes::Yes;
     workerViewInitiallyCollapsed = _workerViewInitiallyCollapsed;
  }
 
 
  return workerViewInitiallyCollapsed;
}

protected void resetChangedValues()
{
 
super();

  mustReloadData = NoYes::No;
 
 
  // current view
  currentViewChanged = NoYes::No;
 
 
  // order view
  workerViewGroupingChanged = NoYes::No;
  workerViewInitiallyCollapsedChanged = NoYes::No;
 
 
  // resource view
  projectViewGroupingChanged = NoYes::No;
  projectViewInitiallyCollapsedChanged = NoYes::No;
}
 


public boolean unpack(container packedClass)
{   boolean ret;

   Integer version = conpeek(packedClass,1);
   ;
 
  switch (version)
   {
 
    case #CurrentVersion:
        [version, #CurrentList] = packedClass;
       
ret = true;
     break;
     default:
        ret = false;
   }
 
 
   return ret;
}

public static XBB_GanttView_SchedEmpl construct()
{   

   return new XBB_GanttView_SchedEmpl();
}

public static XBB_GanttView_SchedEmpl newGanttClient(XBB_GanttClient_SchedEmpl _ganttClient)
{

  XBB_GanttView_SchedEmpl ganttView = XBB_GanttView_SchedEmpl::construct();

  ganttView.parmGanttClient(_ganttClient);
 
 
  return ganttView;
}




A continuación modificaremos las clases existentes para que utilice nuestra clase GanttView.
Empezaremos por nuestra clase GanttActiveXVarchar, modificaremos o añadiremos los siguientes métodos.

Dependiendo de la vista actual realizará una agrupación o otra.

public void groupByCurrentView()
{
   XBB_GanttView_SchedEmpl ganttView =    this.parmGanttClient().parmGanttView();
 
   switch (ganttView.parmCurrentView())
   {
 
     case XBB_GanttView::Worker:
         this.groupByWorkerView();
     
    break;
      case XBB_GanttView::Project:
         this.groupByProjectView();
        
break;
      default:
         throw error("Vista no definida.");
   }
}
 



Como podéis ver en los siguientes métodos modificaremos la agrupación aprovechando la funcionalidad que nos ofrece la clase GanttVcGantt, tan solo deberemos pasarle al método parmGroupingField el campo por el que agrupar y si lo deseamos en el parmGroupingOrderField el campo por el que ordenar la agrupación.


public void groupByProjectView()
{
 
int groupingLevel = #emptyGroupingLevel;

  XBB_GanttView_SchedEmpl ganttView = this.parmGanttClient().parmGanttView();
 
XBB_GanttClient_SchedEmpl localGanttClient = this.parmGanttClient() as XBB_GanttClient_SchedEmpl;

  if (this.parmGanttClient() == null)
  {
 
    throw error(strfmt("@SYS27147", classId2Name(classidget(this))));
  }

  this.resetGrouping();
  this.resetGroupingLevels();
  groupingLevel++;

  ganttVcGantt.parmGroupingField(groupingLevel,
 
ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, ProjId)));
  ganttVcGantt.parmGroupingOrderField(groupingLevel,
 
ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, ProjId)));

  maxGroupingLevel = groupingLevel;
  this.groupNodes();
 
 
  // collapse/expand groups
  this.collapseAllGroups(ganttView.parmProjectViewInitiallyCollapsed());
  this.postGroupByView();
}
 


public void groupByWorkerView()
{
 
int groupingLevel = #emptyGroupingLevel;

  XBB_GanttView_SchedEmpl ganttView = this.parmGanttClient().parmGanttView();
 
XBB_GanttClient_SchedEmpl localGanttClient = this.parmGanttClient() as XBB_GanttClient_SchedEmpl;

  if (this.parmGanttClient() == null)
  {
 
    throw error(strfmt("@SYS27147", classId2Name(classidget(this))));
  }

  this.resetGrouping();
  this.resetGroupingLevels();
  groupingLevel++;
  ganttVcGantt.parmGroupingField(groupingLevel,
 
ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, PersonnelNumberId)));

  ganttVcGantt.parmGroupingOrderField(groupingLevel,
 
ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, PersonnelNumberId)));

  maxGroupingLevel = groupingLevel;

  this.groupNodes();
  
  // collapse/expand groups
  this.collapseAllGroups(ganttView.parmWorkerViewInitiallyCollapsed());
  this.postGroupByView();
}
 



Al siguiente método le pasaremos el grupo e indicaremos si el grupo debe tener todos los nodos en una sola fila, lo mismo que podíamos hacer mediante la configuración del Gantt.


protected boolean groupMustHaveAllNodesInOneRow(GanttVcGroup _ganttVcGroup)
{  

    return true;
}

protected void postGroupByView()
{
 
// sort groups and make status bars visible
 
ganttVcGantt.sortGroups();
}
 



En nuestra clase GanttClient añadiremos los siguientes métodos.

protected GanttView createGanttView()
{
 
return XBB_GanttView_SchedEmpl::newGanttClient(this);
}



En el método ya existente onNodeInDiagram le cambiaremos el valor a false en la línea que busca por recId para que no nos devuelva un error si el nodo esta vacío.


public str onNodeInDiagram()
{
 
GanttActiveXVarchart     localGanttVisualization = this.parmGanttVisualization() as GanttActiveXVarchart;
  XBB_GanttData_SchedEmpl  localGanttData =    localGanttVisualization.parmGanttClient().parmGanttData() as XBB_GanttData_SchedEmpl;
  XBB_GanttTmpSchedEmpl    localGanttTmpSchedEmpl;
  GanttVcNode              ganttVcNode = localGanttVisualization.parmCurrentGanttVcNode();
  XBB_GanttTable_SchedEmpl ganttTable = localGanttData.parmGanttTable_SchedEmpl();

 
if(!ganttVcNode)
  {
 
    throw error(strfmt("@SYS27147", classId2Name(classidget(this))));
  } 

 ganttTable.findRecId(ganttVcNode.recId(localGanttVisualization.parmGanttVcGantt()), false);

  localGanttTmpSchedEMPL = ganttTable.parmTableBuffer();
 
 
  return "ProjectId: " + localGanttTmpSchedEMPL.ProjId + "\n" +
      "ActivitytNum: " + localGanttTmpSchedEMPL.ActivityNumber + "\n" +
        "Start time: " + time2StrHMS(localGanttTmpSchedEMPL.StartTime) + "\n" +
          "End time: " + time2StrHMS(localGanttTmpSchedEMPL.EndTime);
}


En el formulario agregaremos un botón y modificaremos el método init para que llame al método initControl


void initControls()
{
   this.setTextCurrentViewBtn();
}
 


void setTextCurrentViewBtn()
{
   XBB_GanttView_SchedEmpl localGanttView = ganttClient.parmGanttView();

  
currentViewBtn.text(enum2str(localGanttView.getOppositeView()));
}


En el método clicked de nuestro nuevo botón añadiremos las siguientes líneas de código.


void clicked()
{
 
  super();
   
   ganttClient.parmGanttView().changeCurrentView();

   element.setTextCurrentViewBtn();
}



Si deseamos que nos cree los nodos de los empleados aunque éstos no tengan ninguna planificación, agregaremos este método a nuestro ActivexGantt, el cual creará tantos nodos como empleados existan aunque estos no tengan planificación alguna.


protected void insertEmptyNodes()
{
    GanttVcDataTable        ganttVcDataTable;
 
   XBB_GanttData_SchedEmpl localGanttData = this.parmGanttClient().parmGanttData() as XBB_GanttData_SchedEmpl;
    HcmEmploymentDetail     hcmEmploymentDetail;
    Map                     mapEmptyPersonnelNumber = localGanttData.getMapEmptyPersonnelNumber();
    MapEnumerator           mapEnumerator;
    Map                     mapInsertedFields;
    HcmPersonnelNumberId    hcmPersonnelNumberId;
    Hcmworker               worker;

 
   if(mapEmptyPersonnelNumber == null || setStrRecIdsEmptyNodes == null)
    {
      
throw error(strFmt("@SYS27147", classId2Name(classIdGet(this))));
    }
    if(!mapEmptyPersonnelNumber.elements())
    {
 
      return;
    }

   
ganttVcDataTable = ganttVcGantt.ganttVcDataTableCollection().findTableName(tableStr(XBB_GanttTmpSchedEmpl), true);

    mapEnumerator = mapEmptyPersonnelNumber.getEnumerator();
 
 
    while(mapEnumerator && mapEnumerator.moveNext())
    {
        hcmPersonnelNumberId = mapEnumerator.currentKey();
       
mapInsertedFields = new Map(Types::String, Types::String);
        worker = HcmWorker::findByPersonnelNumber(hcmPersonnelNumberId);
        hcmEmploymentDetail = HcmEmploymentDetail::findByEmployment(worker.EVR_HcmEmployment().RecId);
 
       mapInsertedFields.insert(fieldStr(XBB_GanttTmpSchedEmpl, PersonnelNumberId), hcmPersonnelNumberId);
 
        ganttVcDataTable.insertUserDefinedRecord(mapInsertedFields,      #prefixRecIdEmptyNode);

        setStrRecIdsEmptyNodes.add(ganttVcDataTable.lastUserCreatedRecId(#prefixRecIdEmptyNode));
     }
}
 
 
 
  



Y, ¿Si quisiéramos hacer una subagrupación como en la imagen?





Fácil, sólo deberemos indicárselo al método que deseemos en este caso a la agrupación del proyecto, como veréis se ha agregado otro grupo.
Importante indicarle al maxGroupingLevel el número de agrupaciones existentes.


public void groupByProjectView()
{  int groupingLevel = #emptyGroupingLevel;

  XBB_GanttView_SchedEmpl ganttView = this.parmGanttClient().parmGanttView();  XBB_GanttClient_SchedEmpl localGanttClient = this.parmGanttClient() as XBB_GanttClient_SchedEmpl;


  if (this.parmGanttClient() == null)
  {     throw error(strfmt("@SYS27147", classId2Name(classidget(this))));
  }

  this.resetGrouping();
  this.resetGroupingLevels();
  groupingLevel++;

  ganttVcGantt.parmGroupingField(groupingLevel,
 
 ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, ProjId)));
  ganttVcGantt.parmGroupingOrderField(groupingLevel,  ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, ProjId)));

  groupingLevel++;
  ganttVcGantt.parmGroupingField(groupingLevel,
 
 ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, ActivityNumber)));
  ganttVcGantt.parmGroupingOrderField(groupingLevel,  ganttVcGantt.detectFieldIndex(tablestr(XBB_GanttTmpSchedEmpl),
                                fieldstr(XBB_GanttTmpSchedEmpl, ActivityNumber)));

  maxGroupingLevel = groupingLevel;
  this.groupNodes();
 
 
  // collapse/expand groups
  this.collapseAllGroups(ganttView.parmProjectViewInitiallyCollapsed());
  this.postGroupByView();
}
 


Descargar xpo solo los objetos de este post
Descargar xpo con todo el proyecto.

Nota: Es posible que falte alguna clase así que lo agrego de nuevo.

Descargar xpo.

 
  

  
  
  
  
  











 

Comentarios