static char View_id[] = "$Header: /u/oreilly/rov/tmacs/RCS/View.cc,v 1.9 1998/02/23 16:14:03 oreilly Exp $";


/*
$Log: View.cc,v $
Revision 1.9  1998/02/23 16:14:03  oreilly
*** empty log message ***

Revision 1.8  1997/12/12 17:58:42  oreilly
*** empty log message ***

Revision 1.7  1997/10/03 09:34:44  oreilly
*** empty log message ***

Revision 1.6  97/09/10  08:54:15  08:54:15  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.5  97/06/03  13:05:23  13:05:23  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.4  97/04/30  19:20:26  19:20:26  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.3  97/03/20  12:31:54  12:31:54  oreilly (Thomas C. O'Reilly)
..

Revision 1.2  96/10/28  09:12:53  09:12:53  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.1  96/07/22  10:42:21  10:42:21  oreilly (Thomas C. O'Reilly)
First external release

*/
#include <Xm/Form.h>
#include "Vk/VkInfoDialog.h"
#include "View.h"
#include "DmGuiObject.h"
#include "DmGuiApp.h"


DynArray<DmGuiObject *> *View::_children = new DynArray<DmGuiObject *>();


View::View(const char *name, Widget parent, int segments) : 
  VkComponent(name)
{
  _parent = parent;
  _baseWidget = XtCreateWidget(_name, xmFormWidgetClass, parent, NULL, 0);
  installDestroyHandler();

  Widget form = _baseWidget;  
  _segments = segments;
  if (segments)
    XtVaSetValues(form, XmNfractionBase, segments, NULL);

  _vkComponents = new VkComponentList();
  _isParentView = False;
}


View::~View()
{
}


void View::add(Widget w, Layout *layout)
{
  Arg args[50];
  int n = layout->setArgs(args);
  XtSetValues(w, args, n);
  return;
}


void View::add(VkComponent *obj, Layout *layout)
{
  _vkComponents->add(obj);
  
  add(obj->baseWidget(), layout);
}


void View::add(DmGuiObject *obj, Layout *layout)
{
  _vkComponents->add(obj);
  add(obj->baseWidget(), layout);

  if (_isParentView)
    obj->setStickyConsumer(True);
  else
    obj->setStickyConsumer(False);
}


void View::show()
{
  VkComponent::show();

  for (int i = 0; i < _vkComponents->size(); i++)
    (*_vkComponents)[i]->show();
  
  Boolean debug = False;
  Boolean error = False;
  char errbuf[512];

  // Start consumers of all DmGuiObjects in the View  
  DmGuiObject **obj;
  DmGuiApp *app = (DmGuiApp *)theApplication;

  /* 
     Start all consumers managed by this View. Note that we shouldn't
     call updateGui() for any DmGuiObjects within this loop, since
     updateGui() may refer to "peer" DmGuiObjects which haven't been
     started yet.
  */
  int nConsumers = 0;
  _children->clear();

  SListIter<DmGuiObject *> objects(app->dmGuiObjectList);
  
  objects.reset();
  while (obj = objects.next())
  {
    if (manages(*obj)) 
    {
//      dprintf(stderr, 
//		"View::show() - start consuming \"%s\" (%d consumers)\n",
//		(*obj)->name(), (*obj)->nConsumers());
      
      nConsumers += (*obj)->nConsumers();
      
      if ((*obj)->startConsume() == -1)
      {
	(*obj)->prtErrorMsg();
	(*obj)->clearError();
	error = TRUE;
      }
      _children->add(obj);
    }
  }
  dprintf(stderr, "Started %d consumers\n", nConsumers);
  
  if (error)
  {
    sprintf(errbuf, 
	    "View::show() - startConsume() failed "
	    "for one or more DmGuiObjects: see stderr\n");

    theInfoDialog->postAndWait(errbuf);
  }

  DmGuiObject *nObj;
  
  error = FALSE;
  for (int i = 0; i < _children->size(); i++)
  {
    _children->get(i, &nObj);
    dprintf(stderr, "View::show() - updateGui() for \"%s\"\n", 
	    nObj->name());

    nObj->updateGui();
    if (nObj->error())
    {
      fprintf(stderr, "%s::updateGui() - ", nObj->name());
      nObj->prtErrorMsg();
      nObj->clearError();
      error = TRUE;
    }    
  }
  
  if (error)
  {
    sprintf(errbuf, 
	    "View::show() - updateGui() failed for one or more "
	    "DmGuiObjects: see stderr\n");

    theInfoDialog->postAndWait(errbuf);
  }


}



void View::hide()
{
  VkComponent::hide();

  for (int i = 0; i < _vkComponents->size(); i++)
    (*_vkComponents)[i]->hide();

  Boolean error = False;
  Boolean debug = False;
  
  // Stop consumers of all DmGuiObjects in the View  
  DmGuiObject **obj;
  DmGuiApp *app = (DmGuiApp *)theApplication;

  SListIter<DmGuiObject *> *objects = 
    new SListIter<DmGuiObject *>(app->dmGuiObjectList);

  objects->reset();
  int nConsumers = 0;
  while (obj = objects->next())
  {
    if (manages(*obj) && !(*obj)->stickyConsumer()) 
    {
      dprintf(stderr, "View::hide() - stop consuming \"%s\"\n", 
	      (*obj)->name());
      
      nConsumers += (*obj)->nConsumers();
      
      if ((*obj)->stopConsume(CheckSticky) == -1)
      {
	(*obj)->prtErrorMsg();
	(*obj)->clearError();
	error = TRUE;
      }
    }
  }  

  // Done with iterator
  delete objects;
  
  dprintf(stderr, "Stopped %d consumers\n", nConsumers);
  
  if (error)
  {
    char errbuf[errorMsgSize];
    
    sprintf(errbuf, 
	    "stopConsume() failed for one or more DmGuiObjects: "
	    "see stderr\n");

    theInfoDialog->postAndWait(errbuf);
  }
}


Boolean View::manages(DmGuiObject *obj)
{
  Widget parent;
  Widget base = obj->baseWidget();
  
  while ((parent = XtParent(base)) != NULL && parent != this->_parent)
  {
    if (parent == this->_baseWidget)
      return True;

    base = parent;
  }

  return False;
}





ParentView::ParentView(const char *name, Widget parent, int segments)
  : View(name, parent, segments)
{
  _isParentView = True;
}


ParentView::~ParentView()
{
}


Boolean ParentView::manages(DmGuiObject *obj)
{
  Widget parent;
  Widget base = obj->baseWidget();
  
  while ((parent = XtParent(base)) != NULL && parent != this->_parent)
  {
    SListIter<View *> childViewList(_childViews);
    
    childViewList.reset();
    View **view;
    while (view = childViewList.next())
    {
      if ((*view)->baseWidget() == parent)
      {
	/* DmGuiObject belongs to a child view, so return False */
	return False;
      }
    }
    
    if (parent == this->_baseWidget)
      return True;

    base = parent;
  }

  return False;
}


void ParentView::addChildView(View *view)
{
  _childViews.append(view);
}


  
#ifdef ZILCH
void ParentView::add(
		     DmGuiObject *obj,    // i: object to be added
		     Layout *layout       // i: constraints on object position
		     )
{
  View::add(obj, layout);

  // All DmGuiObjects in ParentView are sticky consumers
  obj->setStickyConsumer(True);
}

#endif


