/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#include "status/status.hh"
#include "window/window.hh"
#include "window/style.hh"
#include "math/num_type.hh"
#include "window/wmanager.hh"
#include "memory/array.hh"
#include "window/style.hh"
#include "time/time.hh"
#include "window/win_evt.hh"
#include "gui/button.hh"
#include "gui/text.hh"
#include "gui/deco_win.hh"
#include "device/kernel.hh"
class i4_gui_stat_handle : public i4_status_class
{
int id;
public:
i4_gui_stat_handle(int id, int flags) : id(id) {}
virtual i4_bool update(float percent);
virtual ~i4_gui_stat_handle();
};
class i4_gui_stat_window : public i4_parent_window_class
{
i4_graphical_style_class *style;
i4_str *show_str;
int lx2;
i4_bool canceled;
int dir, flags;
public:
i4_float percent;
i4_gui_stat_window(float percent,
w16 w, w16 h,
i4_graphical_style_class *style,
const i4_const_str &str,
int flags) :
i4_parent_window_class(w,h), style(style),
percent(percent),
flags(flags)
{
show_str=new i4_str(str);
lx2=0;
canceled=0;
dir=1;
if (flags & I4_STATUS_ALLOW_CANCEL)
{
i4_button_class *b;
b=new i4_button_class(0, new i4_text_window_class(i4gets("cancel_operation"), style),
style, new i4_event_reaction_class(this, 1));
resize(width() < b->width() ? b->width() : width(), height() + b->height() + 6);
add_child(width()/2-b->width()/2, height()-b->height()-3, b);
}
}
void receive_event(i4_event *ev)
{
if (ev->type()==i4_event::USER_MESSAGE)
canceled=i4_T;
else i4_parent_window_class::receive_event(ev);
}
void parent_draw(i4_draw_context_class &context)
{
int x1=2, x2=width()-3;
int y=10;
int bx2=(sw32)(x1+(x2-x1+1)*percent);
if (undrawn_area.empty() && bx2==lx2)
return;
lx2=bx2;
i4_font_class *f=style->font_hint->normal_font;
int fh=f->height(*show_str);
if (!undrawn_area.empty())
{
local_image->clear(style->color_hint->neutral(), context);
f->set_color(style->color_hint->text_foreground);
int fw=f->width(*show_str);
f->put_string(local_image, width()/2-fw/2, y, *show_str, context);
}
y+=fh+10;
if (!undrawn_area.empty())
{
local_image->bar(x1-1, y-1, x2+1, y+6+1, 0, context);
local_image->bar(x1, y, x2, y+6, style->color_hint->window.active.dark, context);
}
x1++; x2--;
local_image->bar(x1, y, bx2, y+6,
style->color_hint->window.active.bright,
context);
}
i4_bool update_percent(float p)
{
if (flags & I4_STATUS_UNKNOWN_TOTAL)
{
if (dir>0)
{
percent+=0.05;
if (percent>1)
{
percent=1;
dir=-1;
}
}
else
{
percent-=0.05;
if (percent<0)
{
percent=0;
dir=1;
}
}
}
else
percent=p;
request_redraw();
return !canceled;
}
~i4_gui_stat_window()
{
delete show_str;
}
char *name() { return "gui_stat_window"; }
};
int show_blts=0;
class i4_gui_status_creator_class : public i4_event_handler_class
{
i4_window_manager_class *wm;
i4_display_class *display;
struct stat
{
i4_gui_stat_window *win;
i4_bool allocated;
i4_time_class start_time;
i4_str *desc;
int flags;
};
i4_array wins;
i4_time_class last_update_time;
sw32 grab_id;
int get_window_y(i4_window_class *w)
{
int y= wm->height() - w->height();
for (int i=0; iheight();
return y;
}
public:
char *name() { return "gui_status"; }
i4_gui_status_creator_class(i4_window_manager_class *wm,
i4_display_class *display)
: wins(2,10),
wm(wm), display(display)
{
grab_id=-1;
}
i4_status_class *create(const i4_const_str &description, int flags)
{
int id=0;
for (id=0; idget_parent();
i4_window_request_mouse_ungrab_class ungrab(wins[id].win);
i4_kernel.send_event(p, &ungrab);
grab_id=-1;
}
}
void grab_new_id()
{
for (int i=0; iget_parent(), &grab);
if (!grab.return_result)
grab_id=-1;
}
}
void receive_event(i4_event *ev)
{
if (ev->type()==i4_event::USER_MESSAGE)
{
CAST_PTR(uev, i4_user_message_event_class, ev);
int id=uev->sub_type;
if (id!=-1)
ungrab_id(id);
wins[id].win=0;
grab_new_id();
}
}
void delete_stat(int id)
{
wins[id].allocated=i4_F;
delete wins[id].desc;
if (wins[id].win)
{
if (id!=-1)
ungrab_id(id);
i4_kernel.delete_handler(wins[id].win->get_parent());
wins[id].win=0;
grab_new_id();
}
}
i4_bool update(int id, float percent)
{
I4_ASSERT(wins[id].allocated, "id not allocated");
i4_time_class now;
i4_bool ret=i4_T;
if (wins[id].win)
{
if (grab_id==-1)
grab_new_id();
if ((wins[id].flags & I4_STATUS_UNKNOWN_TOTAL) ||
percent-wins[id].win->percent>0.01)
ret=wins[id].win->update_percent(percent);
}
else if (now.milli_diff(wins[id].start_time)>500 || percent==1.0)
{
i4_graphical_style_class *s=wm->get_style();
i4_font_class *f=s->font_hint->normal_font;
int fw=f->width(*wins[id].desc)+4;
if (fw<200) fw=200;
int fh=f->height(*wins[id].desc) + 30;
i4_deco_window_class *w;
// i4_user_message_event_class *uev=new i4_user_message_event_class(id);
// i4_event_reaction_class *re=new i4_event_reaction_class(this, uev);
i4_gui_stat_window *gs=new i4_gui_stat_window(percent, fw, fh, s, *wins[id].desc,
wins[id].flags);
w=new i4_deco_window_class(gs->width(), gs->height(), i4_F, s);
w->add_child(w->get_x1(), w->get_y1(), gs);
int yp=get_window_y(w);
wm->add_child(wm->width()/2-w->width()/2, yp, w);
wins[id].win=gs;
if (grab_id==-1)
{
grab_id=id;
i4_window_request_mouse_grab_class grab(gs);
i4_kernel.send_event(w, &grab);
if (!grab.return_result)
grab_id=-1;
}
}
if (now.milli_diff(last_update_time)>100) // only refresh 10 fps so we don't slow down process
{
show_blts=1;
if (!display->display_busy())
wm->root_draw();
show_blts=0;
i4_kernel.process_events();
last_update_time.get();
}
return ret;
}
};
i4_gui_status_creator_class *i4_gui_status_creator=0;
i4_bool i4_gui_stat_handle::update(float percent)
{
for (i4_idle_class *p=i4_idle_class::first; p;p=p->next)
p->idle();
return i4_gui_status_creator->update(id, percent);
}
i4_gui_stat_handle::~i4_gui_stat_handle()
{
i4_gui_status_creator->delete_stat(id);
}
i4_status_class *i4_create_gui_stat(const i4_const_str &st, int flags)
{
return i4_gui_status_creator->create(st, flags);
}
void i4_init_gui_status(i4_window_manager_class *wm,
i4_display_class *display)
{
if (i4_gui_status_creator)
i4_error("4_gui_status creator already created");
i4_gui_status_creator=new i4_gui_status_creator_class(wm, display);
i4_set_status_create_function(i4_create_gui_stat);
}
void i4_set_status_create_function(i4_status_create_function_type fun);
void i4_uninit_gui_status()
{
if (i4_gui_status_creator)
{
delete i4_gui_status_creator;
i4_gui_status_creator=0;
}
}