//<copyright>
// 
// Copyright (c) 1993,94
// Institute for Information Processing and Computer Supported New Media (IICM),
// Graz University of Technology, Austria.
// 
//</copyright>

//<file>
//
// Name:        cursors.C
//
// Purpose:     implementation of class HgCursors
//
// Created:     20 Jul 93   Gaisbauer Mansuet Juergen
//
// Changed:     28 Mar 95   Michael Pichler
//
//
//</file>


#include "cursors.h"

#include <InterViews/bitmap.h>
#include <InterViews/color.h>
#include <InterViews/style.h>
#include <IV-look/kit.h>


#include "csr_bitmaps/hourglass.bmp"
#include "csr_bitmaps/hourglassmsk.bmp"
#include "csr_bitmaps/hourglass32.bmp"
#include "csr_bitmaps/hourglass32msk.bmp"
#include "csr_bitmaps/crosshair.bmp"
#include "csr_bitmaps/crosshairmsk.bmp"
#include "csr_bitmaps/crosshair32.bmp"
#include "csr_bitmaps/crosshair32msk.bmp"
#include "csr_bitmaps/aeroplane.bmp"
#include "csr_bitmaps/aeroplanemsk.bmp"
#include "csr_bitmaps/aeroplane32.bmp"
#include "csr_bitmaps/aeroplane32msk.bmp"
#include "csr_bitmaps/busy0.bmp"
#include "csr_bitmaps/busy0msk.bmp"
#include "csr_bitmaps/busy1.bmp"
#include "csr_bitmaps/busy1msk.bmp"
#include "csr_bitmaps/busy2.bmp"
#include "csr_bitmaps/busy2msk.bmp"
#include "csr_bitmaps/busy3.bmp"
#include "csr_bitmaps/busy3msk.bmp"


// when defining a new cursor make sure that it is initialized with nil in the constructor!


HgCursors* HgCursors::instance_ = nil;


HgCursors::HgCursors ()
{
  instance_ = this;

  WidgetKit& kit = *WidgetKit::instance ();
  kit.begin_style ("Cursor");

  long val = 16;
  kit.style ()->find_attribute ("size", val);
  size_ = (int) val;

  fillbusy_ = kit.style ()->value_is_on ("fillBusy");

  kit.end_style ();  // "Cursor"

  hourglass_ = nil;
  crosshair_ = nil;
  aeroplane_ = nil;

  curbusy_ = 0;
  for (int i = 0;  i < NumBusy;  i++)
    busy_ [i] = nil;

  busyforeground_ = nil;
  busybackground_ = nil;
}


HgCursors::~HgCursors ()
{
  instance_ = nil;
  delete hourglass_;
  delete crosshair_;
  delete aeroplane_;

  // as class Cursor is not derived from Resource,
  // you should not access the cursor with window->cursor afterwards

  for (int i = 0;  i < NumBusy;  i++)
    delete busy_ [i];

  Resource::unref (busyforeground_);
  Resource::unref (busybackground_);
}


HgCursors* HgCursors::instance ()
{
  if (!instance_)
    instance_ = new HgCursors;

  return instance_;
}


#if defined(__STDC__) || defined(__ANSI_CPP__)
#define __concat(first,second) first##second
#define __concat3(first,second,third) first##second##third
#else
#define __concat(first,second) first/**/second
#define __concat3(first,second,third) first/**/second/**/third
#endif

#define concat(first,second) __concat(first,second)
#define concat3(first,second,third) __concat3(first,second,third)

// load cursor "c" and store it in member variable c_
#define load_cursor( c, c_ ) \
if (size_ == 32) \
  c_ = new Cursor ( \
    new Bitmap (concat3 (c,32,_bits), concat3 (c,32,_width), concat3 (c,32,_height), \
                concat3 (c,32,_x_hot), concat3 (c,32,_y_hot)), \
    new Bitmap (concat3 (c,32,msk_bits), concat3 (c,32,msk_width), concat3 (c,32,msk_height)) \
  ); \
else  /* default: 16 */ \
  c_ = new Cursor ( \
    new Bitmap (concat (c,_bits), concat (c,_width), concat (c,_height), \
                concat (c,_x_hot), concat (c,_y_hot)), \
    new Bitmap (concat (c,msk_bits), concat (c,msk_width), concat (c,msk_height)) \
  );

// access cursor c - load it on first time
#define cursor_function( c, c_ ) \
Cursor* HgCursors::c () \
{ \
  if (!c_) \
  { \
    load_cursor (c, c_) \
  } \
  return c_; \
}

// load frame n of cursor c, store it in c_ [n]
// size_ is ignored
// to create a cursor without background use same fg and mask bitmaps
#define load_cursor_frame( c, c_, n ) \
{ \
  Bitmap* fgbitmap = new Bitmap (concat3 (c,n,_bits), \
    concat3 (c,n,_width), concat3 (c,n,_height), concat3 (c,n,_x_hot), concat3 (c,n,_y_hot)); \
  c_ [n] = new Cursor ( \
    fgbitmap, \
    fillbusy_ ? new Bitmap (concat3 (c,n,msk_bits), concat3 (c,n,msk_width), concat3 (c,n,msk_height)) \
              : fgbitmap, \
    busyforeground_, \
    busybackground_ \
  ); \
}

cursor_function (hourglass, hourglass_)
cursor_function (crosshair, crosshair_)
cursor_function (aeroplane, aeroplane_)


Cursor* HgCursors::animatedBusy ()
{
// background 7c2e88, foreground 0005ba - too dark
// background 9c38ff, foreground 2345fa (from Harmony colour map)

  if (!*busy_)
  { // cannot loop over macros

    busyforeground_ = new Color ((float) 0x23/0xff, (float) 0x45/0xff, (float) 0xfa/0xff);
    busybackground_ = new Color ((float) 0x9c/0xff, (float) 0x38/0xff, (float) 1);
    Resource::ref (busyforeground_);
    Resource::ref (busybackground_);

    load_cursor_frame (busy, busy_,0);
    load_cursor_frame (busy, busy_,1);
    load_cursor_frame (busy, busy_,2);
    load_cursor_frame (busy, busy_,3);
  }

  Cursor* csr = busy_ [curbusy_];
  if (++curbusy_ == NumBusy)  // for next call
    curbusy_ = 0;

  return csr;
}
