/**********************************************************************
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 "gui/button.hh"
#include "device/kernel.hh"
#include "device/keys.hh"
#include "window/win_evt.hh"
i4_button_class::i4_button_class(const i4_const_str *idle_context_help, // can be null
i4_window_class *child,
i4_graphical_style_class *hint,
i4_event_reaction_class *press,
i4_event_reaction_class *depress,
i4_event_reaction_class *activate,
i4_event_reaction_class *deactivate) :
i4_menu_item_class(idle_context_help,
hint,
child ? child->width()+4 : 0,
child ? child->height()+4 : 0,
press,depress,
activate,
deactivate),
decore(child)
{
popup=i4_F;
state=WAIT_CLICK;
repeat_down=i4_F;
repeat_event=0;
grabbing=i4_F;
if (child)
add_child(2,2,child);
}
i4_button_class::~i4_button_class()
{
if (decore)
{
remove_child(decore);
delete decore;
if (grabbing)
{
I4_ASSERT(parent, "~button/grab/and no parent");
i4_window_request_mouse_ungrab_class ungrab(this);
i4_kernel.send_event(parent,&ungrab);
}
}
}
void i4_button_class::reparent(i4_image_class *draw_area, i4_parent_window_class *par)
{
if (grabbing && !draw_area)
{
grabbing=i4_F;
i4_window_request_mouse_ungrab_class ungrab(this);
i4_kernel.send_event(parent,&ungrab);
}
i4_menu_item_class::reparent(draw_area, par);
}
void i4_button_class::receive_event(i4_event *ev)
{
if (!disabled)
{
if (ev->type()==i4_event::OBJECT_MESSAGE)
{
CAST_PTR(oev,i4_object_message_event_class,ev);
if (oev->object==this)
{
i4_kernel.not_idle();
if (repeat_event)
send_event(repeat_event, PRESSED);
else
send_event(send.press, PRESSED);
time_id=i4_time_dev.request_event(this,
new i4_object_message_event_class(this),
hint->time_hint->button_repeat);
state=WAIT_REPEAT;
} else i4_menu_item_class::receive_event(ev);
}
else if (ev->type()==i4_event::MOUSE_BUTTON_DOWN)
{
CAST_PTR(b,i4_mouse_button_down_event_class,ev);
if (b->but==i4_mouse_button_down_event_class::LEFT)
{
if (pressed)
{
do_depress();
send_event(send.depress, DEPRESSED);
}
else
{
do_press();
send_event(send.press, PRESSED);
if (!grabbing)
{
i4_window_request_mouse_grab_class grab(this);
i4_kernel.send_event(parent,&grab);
grabbing=i4_T;
}
if (repeat_down)
{
i4_kernel.not_idle();
time_id=i4_time_dev.request_event(this,
new i4_object_message_event_class(this),
hint->time_hint->button_delay);
state=WAIT_DELAY;
}
}
}
} else if (ev->type()==i4_event::MOUSE_BUTTON_UP)
{
CAST_PTR(b,i4_mouse_button_down_event_class,ev);
if (b->but==i4_mouse_button_down_event_class::LEFT)
{
if (grabbing)
{
grabbing=i4_F;
i4_window_request_mouse_ungrab_class ungrab(this);
i4_kernel.send_event(parent,&ungrab);
}
if (state==WAIT_DELAY || state==WAIT_REPEAT)
{
i4_time_dev.cancel_event(time_id);
state=WAIT_CLICK;
}
if (pressed && popup)
{
do_depress();
send_event(send.depress, DEPRESSED);
}
}
}
else if (ev->type()==i4_event::KEY_PRESS)
{
CAST_PTR(k,i4_key_press_event_class,ev);
if (k->key==I4_ENTER)
{
if (pressed)
{
do_depress();
send_event(send.depress, DEPRESSED);
}
else
{
do_press();
send_event(send.press, PRESSED);
}
} else if (k->key==I4_TAB)
{
i4_window_message_class t(i4_window_message_class::REQUEST_NEXT_KEY_FOCUS,this);
i4_kernel.send_event(parent, &t);
}
else if (k->key==I4_LEFT)
{
i4_window_message_class l(i4_window_message_class::REQUEST_LEFT_KEY_FOCUS,this);
i4_kernel.send_event(parent, &l);
}
else if (k->key==I4_RIGHT)
{
i4_window_message_class r(i4_window_message_class::REQUEST_RIGHT_KEY_FOCUS,this);
i4_kernel.send_event(parent, &r);
}
else if (k->key==I4_UP)
{
i4_window_message_class u(i4_window_message_class::REQUEST_UP_KEY_FOCUS,this);
i4_kernel.send_event(parent, &u);
}
else if (k->key==I4_DOWN)
{
i4_window_message_class d(i4_window_message_class::REQUEST_DOWN_KEY_FOCUS,this);
i4_kernel.send_event(parent, &d);
}
} else
i4_menu_item_class::receive_event(ev);
} else i4_menu_item_class::receive_event(ev);
}
void i4_button_class::parent_draw(i4_draw_context_class &context)
{
local_image->add_dirty(0,0,width()-1,height()-1,context);
i4_color_hint_class::bevel *color;
if (active)
color=&hint->color_hint->button.active;
else
color=&hint->color_hint->button.passive;
i4_color b,d,m=color->medium;
if (!pressed)
{
b=color->bright;
d=color->dark;
} else
{
b=color->dark;
d=color->bright;
}
local_image->bar(0,0,width()-1,0,b,context);
local_image->bar(0,0,0,height()-1,b,context);
local_image->bar(1,1,width()-2,1,m,context);
local_image->bar(1,1,1,height()-2,m,context);
local_image->bar(2,height()-2,width()-2,height()-2,d,context);
local_image->bar(width()-2,2,width()-2,height()-2,d,context);
local_image->bar(0,height()-1,width()-1,height()-1,hint->color_hint->black,context);
local_image->bar(width()-1,0,width()-1,height()-1,hint->color_hint->black,context);
local_image->bar(2,2,width()-3,height()-3,color->medium,context);
}
void i4_button_class::set_popup(i4_bool value)
{
popup=value;
}
void i4_button_class::set_repeat_down(i4_bool value, i4_event_reaction_class *_repeat_event)
{
if (!value && (state==WAIT_DELAY || state==WAIT_REPEAT))
i4_time_dev.cancel_event(time_id);
state=WAIT_CLICK;
repeat_down=value;
if (repeat_event) delete repeat_event;
repeat_event=_repeat_event;
}