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

//<file>
//
// Name:        progress.C
//
// Purpose:     implementation of class Progress
//
// Created:     18 Jan 94   Michael Pichler
// Changed:     22 Apr 94   Michael Pichler
//
// $Id: progress.C,v 1.4 1996/03/05 09:57:07 bmarsch Exp $
//
//</file>
//
// $Log: progress.C,v $
// Revision 1.4  1996/03/05 09:57:07  bmarsch
// Round percentage when drawing label
//



#include "progress.h"

#include <InterViews/canvas.h>
#include <InterViews/color.h>
#include <InterViews/display.h>
#include <InterViews/font.h>
#include <InterViews/geometry.h>
#include <InterViews/style.h>
#include <InterViews/window.h>
#include <IV-look/kit.h>
#include <hyperg/OS/string.h>

#include <stdio.h>
#include <iostream.h>


 
Progress::Progress ()
: Patch (nil)
{
  p_ = 0.0;  // assert: 0.0 <= p_ <= 1.0 at any time

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

  fgcolor_ = kit.foreground ();
  Resource::ref (fgcolor_);

  bgcolor_ = kit.background ();
  Resource::ref (bgcolor_);

  Style* style = kit.style ();
  String v;  // default: showLabel
  int show_label = !style->find_attribute ("showLabel", v) || style->value_is_on ("showLabel");

  kit.end_style ();  // "Progress"

  kit.begin_style ("ProgressLabel");

  fntcolor_ = kit.foreground ();
  Resource::ref (fntcolor_);

  font_ = kit.font ();
  Resource::ref (font_);

  if (show_label)
  { FontBoundingBox fbb;
    font_->char_bbox ('%', fbb);
    charheight_ = fbb.ascent ();
  }
  else
    charheight_ = 0;  // no label

  kit.end_style ();  // "ProgressLabel"
}



Progress::~Progress ()
{
  Resource::unref (fgcolor_);
  Resource::unref (bgcolor_);
  Resource::unref (fntcolor_);
  Resource::unref (font_);
}

  

// set new progress
// p as fraction in range 0.0 to 1.0
// redraw only done when percentage changes
// repair flag causes immediate redraw if set

void Progress::set (float p, int repair)
{
  int oldp = (int) (100 * p_);

  if (p <= 0.0)
    p_ = 0.0;
  else if (p >= 1.0)
    p_ = 1.0;
  else
    p_ = p;

  if ((int) (100 * p_) == oldp)
    return;

  redraw ();  // Patch::redraw

  if (repair) {
    Window* win = nil;
    if (canvas () && (win = canvas ()->window ())) {
      win->repair ();
      win->display ()->flush ();
    }
  }
} // set



// draw
// draw progress indicator

void Progress::draw (Canvas* c, const Allocation& a) const
{
  if (!c->damaged (extension ()))
    return;
  // every glyph that has a complex draw function should do this, because
  // a box calls draw() on each component when the box is damaged anywhere;
  // a patch includes this functionality -- the body is drawn only if the exten-
  // sion and canvas damage intersect --, but here Patch::draw is overridden

  if (bgcolor_)
    c->fill_rect (a.left(), a.bottom(), a.right(), a.top(), bgcolor_);

  float width = a.right () - a.left ();
  float height = a.top () - a.bottom ();

  if (p_ > 0.0 && fgcolor_)
    c->fill_rect (a.left(), a.bottom(), a.left() + width * p_, a.top(), fgcolor_);

  if (charheight_)  // show percentage label
  {
    char str [6];  // "nnn %"
    sprintf (str, "%3d %%", (int) (100.0 * p_ + 0.5));
    float strwidth = 0;

    int i = 0;
    const char* s = str;

    float* cw = ((Progress*) this)->charwidths_;  // cast only for cxx
    for (;  i < 5;  i++)
      strwidth += (*cw++ = font_->width (*s++));

    float x = a.left () + width/2 - (strwidth / 2);
    float y = a.bottom () + (height - charheight_) / 2;

    const float* cws = charwidths_;
    for (i = 0, s = str, cws = charwidths_;  i < 5;  i++)
    { c->character (font_, *s++, *cws, fntcolor_, x, y);
      x += *cws++;
    }
  }

} // draw



// allocate

void Progress::allocate (Canvas* c, const Allocation& a, Extension& ext)
{
  ext.set (c, a);
  Patch::allocate (c, a, ext);   
}



// request
// want to stretch as far as possible


void Progress::request (Requisition& req) const
{
  Requirement rx (10.0, fil, 0, 0);
  Requirement ry (10.0, fil, 0, 0);

  req.require (Dimension_X, rx);
  req.require (Dimension_Y, ry);
}
