/* ==================================================== ======== ======= *
 *
 *  uucontext.cc
 *  Ubit Project  [Elc][beta1][2001]
 *  Author: Eric Lecolinet
 *
 *  Part of the Ubit Toolkit: A Brick Construction Game Model for Creating GUIs
 *
 *  (C) 1999-2001 Eric Lecolinet @ ENST Paris
 *  WWW: http://www.enst.fr/~elc/ubit   Email: elc@enst.fr (subject: ubit)
 *
 * ***********************************************************************
 * COPYRIGHT NOTICE : 
 * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY AND WITHOUT EVEN THE 
 * IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 
 * YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF THE GNU 
 * GENERAL PUBLIC LICENSE AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION; 
 * EITHER VERSION 2 OF THE LICENSE, OR (AT YOUR OPTION) ANY LATER VERSION.
 * SEE FILES 'COPYRIGHT' AND 'COPYING' FOR MORE DETAILS.
 * ***********************************************************************
 *
 * ==================================================== [Elc:01] ======= *
 * ==================================================== ======== ======= */

//pragma ident	"@(#)uucontext.cc	ubit:b1.6.0"
#include <udefs.hh>
#include <ubrick.hh>
#include <ubox.hh>
#include <uwin.hh>
#include <uview.hh>
#include <ucolor.hh>
#include <uevent.hh>
#include <ustyle.hh>
#include <ucontext.hh>


UWinContext::~UWinContext() {
  if (flags) free(flags);
  if (exts)  free(pexts);
  flags  = null;
  exts   = null;
  pflags = null; 
  pexts  = null;
}

// this method recopies the internal flags and exts arrays
void UWinContext::copy(UWinContext &wc) {
  *this = wc;
  flags = null;
  exts  = null;
  pflags= &flags;
  pexts = &exts;
  int k;

  if (wc.flags && wc.flagCount > 0) {
    flags = (const UFlag**) malloc(wc.flagCount * sizeof(UFlag*));
    for (k = 0; k < wc.flagCount; k++) 
      flags[k] = wc.flags[k];
  }

  if (wc.exts && wc.extCount > 0) {
    exts = (UBrick**) malloc(wc.extCount * sizeof(UBrick*));
    for (k = 0; k < wc.extCount; k++) 
      exts[k] = wc.exts[k];
  }
}

/* ==================================================== ======== ======= */
// creates the first layer of the context stack
// -- !Warning: 'win_view' must be a valid (not null) window view!

UWinContext::UWinContext(UView *win_view) : UContext() {
  flags  = null;
  exts   = null;
  pflags = &(flags);
  pexts  = &(exts);
  flagCount = extCount = 0;
  
  winview = win_view;
  // getBox suffisant et necessaire
  UBox *win = winview->getBox();
  obj = win;

  const UStyle *style = win->getStyle(null);
  if (!style) {
    uerror("UContext::UContext", "!Fatal error: Null Style");
    return;
  }

  local      = style->local;
  boxIsHFlex = boxIsVFlex = false;
  enabled    = obj->isEnabled(); // !!!
  if (obj->isDef(0, UMode::HAS_AUTOCLOSE_BHV)) 
    autoClose = obj->isDef(0, UMode::AUTOCLOSE_BHV); 
  else autoClose = false;

  if (winview->isDef(UView::TRANSPARENT))
    firstTranspView = win_view;
  else firstTranspView = null;

  firstLayoutView = win_view;

  if (obj->getBrowseGroup()) browseGroup = win->getBrowseGroup();
  else browseGroup = null;

  //obs: background  = style->background;  //15.0: moved to localprops
  cursor     = style->cursor;

  // COLORS
  color       = style->getFG(obj); 
  bgcolor     = style->getBG(obj);
  // symcolor = 
  
  if (!bgcolor) bgcolor = &UBgcolor::none;
  if (!color)   color = &UColor::black;
  // symcolor = 

  //NB: lscale = LOGICAL scale
  lscale = 0;

  // NB: UFont::standard imposes lsize = DEFAULT_LSIZE
  fontdesc.set(&UFont::standard);

  // c'est un ajout de caracteristqiues: n'ecrase pas forcement tous les champs
  if (style->font) fontdesc.merge(style->font, lscale);
}

/* ==================================================== ======== ======= */
/* ==================================================== ======== ======= */

UContext::UContext(UGroup *grp, UView *view, const UContext &parp) {
  obj       = grp;
  winview   = parp.winview;
  pflags    = parp.pflags;
  pexts     = parp.pexts;
  flagCount = parp.flagCount;
  extCount  = parp.extCount;
 
 //!ATT: getContainingParent() returns null if parent is a Window
  const UStyle *style = grp->getStyle(view->getContainingParent());
  if (!style) {
    uerror("UContext::UContext", "!Fatal error: Null Style");
    return;
  }
  
  // static props (must be done before retrieving states)
  // [a cause de width et height qui peuvent etre modifiee]

  local = style->local;
  
  // inherited dynamic props // FAIRE AVEC des &
  enabled = parp.enabled;
  if (!obj->isEnabled()) enabled = false; // !!!

  if (obj->isDef(0, UMode::HAS_AUTOCLOSE_BHV)) {
    autoClose = obj->isDef(0, UMode::AUTOCLOSE_BHV);
    //printf("obj %s autoclose = %d \n", obj->cname(), autoClose);
  } 
  else autoClose = parp.autoClose;

  lscale     = parp.lscale;  //NB: lscale = LOGICAL scale
  boxIsVFlex = (parp.local.valign == UValign::flex.get());
  boxIsHFlex = (parp.local.halign == UHalign::flex.get());


  //!!! NB on pourrait appliquer la meme technique que pour firstLayoutView !!
  //!! et n'utiliser que UContext et pas UEvent !!

  if (view->isDef(UView::TRANSPARENT)) {
    // firstTranspView doit etre la 1ere view transparente dans l'arbre
    if (!parp.firstTranspView) firstTranspView = view;
    else firstTranspView = parp.firstTranspView; 
  }
  // si cette vue est opaque il est alors inutile de tenir compte
  // des vues transparentes precedentes ==> ecraser firstTranspView
  else firstTranspView = null;

  // si la taille de cet objet est fixe il est inutile de recalculer
  // le Layout et de reafficher depuis la racine
  // de plus: si FLOATING, inutile de recalculer le layout des parents
  if (obj->isDef(0, UMode::FLOATING)
      || view->isAllDef(UView::FIXED_WIDTH | UView::FIXED_HEIGHT))
    firstLayoutView = view;
  else
    firstLayoutView = parp.firstLayoutView;

  if (parp.browseGroup)  browseGroup = parp.browseGroup;
  else if (obj->getBrowseGroup())  browseGroup = grp->getBrowseGroup();
  else browseGroup = null;

  cursor = (style->cursor ? style->cursor : parp.cursor);
  //obs: background  = style->background;  //15.0: moved to localprops

  // COLORS
  color       = style->getFG(obj);
  bgcolor     = style->getBG(obj);

  // symcolor = 
  if (bgcolor == &UBgcolor::inherit) bgcolor = parp.bgcolor;
  if (color   == &UColor::inherit)   color = parp.color;

  // securite:
  if (!bgcolor) bgcolor = &UBgcolor::none;
  if (!color)   color = &UColor::black;
  // symcolor = 
  
  // FONTS:
  // -1- les fontes s'AJOUTENT et c'est pourquoi il faut toujours
  //     recopier parp->fontdesc qunad ca existe (les autres champs
  //     pouvant etre modifies ensuite)
  // -2- on ne change pas 'lscale' car deja fait au niveau du parent
  // (puisque dans ce cas [voir lignes preced.] scale = celui du parent)

  fontdesc = parp.fontdesc;

  // c'est un ajout de caracteristiques, pas forcement une recopie totale
  // ==> utiliser merge()

  if (style->font != &UFont::inherit)
    fontdesc.merge(style->font, lscale);  
}

/* ==================================================== [TheEnd] ======= */
/* ==================================================== [Elc:00] ======= */


