///////////////////////////////////////////////////////////////////////////////
// $Id: BasicWidget.cxx,v 1.1 1995/01/12 02:09:06 bmott Exp $
///////////////////////////////////////////////////////////////////////////////
//
// BasicWidget.cxx - Abstract base class for all widgets
//
//
// Bradford W. Mott
// Copyright (C) 1994
// December 11,1994
//
///////////////////////////////////////////////////////////////////////////////
// $Log: BasicWidget.cxx,v $
// Revision 1.1  1995/01/12  02:09:06  bmott
// Initial revision
//
///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <assert.h>
#include "BasicWidget.hxx"
#include "UIApplication.hxx"
#include "ContainerWidget.hxx"

///////////////////////////////////////////////////////////////////////////////
// Protected constructor to prevent instantiation
///////////////////////////////////////////////////////////////////////////////
BasicWidget::BasicWidget(ContainerWidget *const parent, const char *const name,
    int x, int y, int width, int height)
    : myName(name),
      myParent(parent),
      myX(x),
      myY(y),
      myWidth(width),
      myHeight(height)
{
  assert(name != NULL);

  // If I have a parent then tell him about myself
  if(myParent != NULL)
  {
    myParent->addChild(this);
  }

  // Invalidate my window
  myWindow = 0;

  // I start off unmanaged
  myManageState = Unmanaged;

  // Setup my default foreground and background colors
  myForeground = application->blackPixel();
  myBackground = application->whitePixel();
}

///////////////////////////////////////////////////////////////////////////////
// Destructor
///////////////////////////////////////////////////////////////////////////////
BasicWidget::~BasicWidget()
{
  // If I have a parent then tell him I'm going away
  if(myParent != NULL)
  {
    myParent->removeChild(this);
  }

  // Close myWindow
  if(myWindow)
    XDestroyWindow(application->display(), myWindow);
}

///////////////////////////////////////////////////////////////////////////////
// Manage the entire widget subtree that I represented
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::manage()
{
  assert(myWindow != 0);

  // Manage myself
  XMapWindow(application->display(), myWindow);
  myManageState = Managed;
}

///////////////////////////////////////////////////////////////////////////////
// Unmanage the entire widget subtree that I represented
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::unmanage()
{
  assert(myWindow != 0);

  // Unmanage myself
  XUnmapWindow(application->display(), myWindow);
  myManageState = Unmanaged;
}

///////////////////////////////////////////////////////////////////////////////
// Set my background to the named color
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::background(const char* name)
{
  XColor desiredColor, color;
  int r,g,b;
  const int delta = 7680;

  XAllocNamedColor(application->display(), application->colormap(),
      name, &color, &desiredColor);
  myBackground = color.pixel;
  XSetWindowBackground(application->display(), myWindow, color.pixel);

  if ((r = desiredColor.red - delta) < 0)
    r = 0;
  if ((g = desiredColor.green - delta) < 0)
    g = 0;
  if ((b = desiredColor.blue - delta) < 0)
    b = 0;
  color.red = r;
  color.green = g;
  color.blue = b;
  XAllocColor(application->display(), application->colormap(), &color);

  myBackgroundLow = color.pixel;
  if ((r = desiredColor.red + delta) > 65535)
    r = 65535;
  if ((g = desiredColor.green + delta) > 65535)
    g = 65535;
  if ((b = desiredColor.blue + delta) > 65535)
    b = 65535;
  color.red = r;
  color.green = g;
  color.blue = b;
  XAllocColor(application->display(), application->colormap(), &color);
  myBackgroundHigh = color.pixel;

  // Make sure the window refreshes
  XClearWindow(application->display(), myWindow);
}

///////////////////////////////////////////////////////////////////////////////
// Set my background to the given sprite
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::background(const Sprite *const sprite)
{
  // Create pixmap 
  Pixmap pixmap = XCreatePixmap(application->display(), myWindow,
      sprite->width(), sprite->height(), 8);

  // Copy image into pixmap
  XPutImage(application->display(), pixmap, application->gc(), 
      sprite->image(), 0, 0, 0, 0, sprite->width(), sprite->height());

  // Install the pixmap on myself
  XSetWindowBackgroundPixmap(application->display(), myWindow, pixmap);

  // Free the pixmap
  XFreePixmap(application->display(), pixmap);

  // Make sure the window refreshes
  XClearWindow(application->display(), myWindow);
}

///////////////////////////////////////////////////////////////////////////////
// Set my foreground to the named color
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::foreground(const char* name)
{
  XColor color;

  XAllocNamedColor(application->display(), application->colormap(),
      name, &color, &color);

  myForeground = color.pixel;
}

///////////////////////////////////////////////////////////////////////////////
// Called whenever an event arrives for me
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::handleEvent(XEvent* event)
{
  // The default action is to do nothing
}

///////////////////////////////////////////////////////////////////////////////
// If I manage the given window then answer myself
///////////////////////////////////////////////////////////////////////////////
BasicWidget* BasicWidget::findWidget(Window window)
{
  if (myWindow == window)
    return(this);
  else
    return((BasicWidget*)0);
}

///////////////////////////////////////////////////////////////////////////////
// Resize myself to the given width and height
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::resize(int width, int height)
{
  myWidth = width;
  myHeight = height;

  // Tell X to resize the widget
  XResizeWindow(application->display(), myWindow, width, height);
}

///////////////////////////////////////////////////////////////////////////////
// Move myself to the given x and y location
///////////////////////////////////////////////////////////////////////////////
void BasicWidget::move(int x, int y)
{
  myX = x;
  myY = y;

  // Tell X to resize the widget
  XMoveWindow(application->display(), myWindow, x, y);
}

