Commit 2055ec6e authored by Davis King's avatar Davis King

Removed the arrow_button widget and moved its functionality into the

button widget.  I also added 4 new button styles that correspond to
the 4 types of arrow button.  Lastly, I had to move some things around
so that is why there seem to be a lot of code changes in this commit.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402585
parent 1e103791
......@@ -11,6 +11,258 @@
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// button object methods
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void button::
set_size (
unsigned long width,
unsigned long height
)
{
auto_mutex M(m);
rectangle min_rect = style->get_min_size(name_,*mfont);
// only change the size if it isn't going to be too small to fit the name
if (height >= min_rect.height() &&
width >= min_rect.width())
{
rectangle old(rect);
rect = resize_rect(rect,width,height);
parent.invalidate_rectangle(rect+old);
btn_tooltip.set_size(width,height);
}
}
// ----------------------------------------------------------------------------------------
void button::
show (
)
{
button_action::show();
btn_tooltip.show();
}
// ----------------------------------------------------------------------------------------
void button::
hide (
)
{
button_action::hide();
btn_tooltip.hide();
}
// ----------------------------------------------------------------------------------------
void button::
enable (
)
{
button_action::enable();
btn_tooltip.enable();
}
// ----------------------------------------------------------------------------------------
void button::
disable (
)
{
button_action::disable();
btn_tooltip.disable();
}
// ----------------------------------------------------------------------------------------
void button::
set_tooltip_text (
const std::string& text
)
{
btn_tooltip.set_text(text);
}
// ----------------------------------------------------------------------------------------
void button::
set_tooltip_text (
const std::wstring& text
)
{
btn_tooltip.set_text(text);
}
// ----------------------------------------------------------------------------------------
void button::
set_tooltip_text (
const ustring& text
)
{
btn_tooltip.set_text(text);
}
// ----------------------------------------------------------------------------------------
const std::string button::
tooltip_text (
) const
{
return btn_tooltip.text();
}
const std::wstring button::
tooltip_wtext (
) const
{
return btn_tooltip.wtext();
}
const dlib::ustring button::
tooltip_utext (
) const
{
return btn_tooltip.utext();
}
// ----------------------------------------------------------------------------------------
void button::
set_main_font (
const shared_ptr_thread_safe<font>& f
)
{
auto_mutex M(m);
mfont = f;
set_name(name_);
}
// ----------------------------------------------------------------------------------------
void button::
set_pos (
long x,
long y
)
{
auto_mutex M(m);
button_action::set_pos(x,y);
btn_tooltip.set_pos(x,y);
}
// ----------------------------------------------------------------------------------------
void button::
set_name (
const std::string& name
)
{
set_name(convert_mbstring_to_wstring(name));
}
void button::
set_name (
const std::wstring& name
)
{
set_name(convert_wstring_to_utf32(name));
}
void button::
set_name (
const ustring& name
)
{
auto_mutex M(m);
name_ = name;
// do this to get rid of any reference counting that may be present in
// the std::string implementation.
name_[0] = name_[0];
rectangle old(rect);
rect = move_rect(style->get_min_size(name,*mfont),rect.left(),rect.top());
btn_tooltip.set_size(rect.width(),rect.height());
parent.invalidate_rectangle(rect+old);
}
// ----------------------------------------------------------------------------------------
const std::string button::
name (
) const
{
auto_mutex M(m);
std::string temp = convert_wstring_to_mbstring(wname());
// do this to get rid of any reference counting that may be present in
// the std::string implementation.
char c = temp[0];
temp[0] = c;
return temp;
}
const std::wstring button::
wname (
) const
{
auto_mutex M(m);
std::wstring temp = convert_utf32_to_wstring(uname());
// do this to get rid of any reference counting that may be present in
// the std::wstring implementation.
wchar_t w = temp[0];
temp[0] = w;
return temp;
}
const dlib::ustring button::
uname (
) const
{
auto_mutex M(m);
dlib::ustring temp = name_;
// do this to get rid of any reference counting that may be present in
// the dlib::ustring implementation.
temp[0] = name_[0];
return temp;
}
// ----------------------------------------------------------------------------------------
void button::
on_button_up (
bool mouse_over
)
{
if (mouse_over)
{
// this is a valid button click
if (event_handler.is_set())
event_handler();
if (event_handler_self.is_set())
event_handler_self(*this);
}
if (button_up_handler.is_set())
button_up_handler(mouse_over);
if (button_up_handler_self.is_set())
button_up_handler_self(mouse_over,*this);
}
// ----------------------------------------------------------------------------------------
void button::
on_button_down (
)
{
if (button_down_handler.is_set())
button_down_handler();
if (button_down_handler_self.is_set())
button_down_handler_self(*this);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// dragable object methods
......@@ -348,139 +600,6 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// arrow_button object methods
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void arrow_button::
set_size (
unsigned long width,
unsigned long height
)
{
auto_mutex M(m);
rectangle old(rect);
const unsigned long x = rect.left();
const unsigned long y = rect.top();
rect.set_right(x+width-1);
rect.set_bottom(y+height-1);
parent.invalidate_rectangle(rect+old);
}
// ----------------------------------------------------------------------------------------
void arrow_button::
draw (
const canvas& c
) const
{
rectangle area = rect.intersect(c);
if (area.is_empty())
return;
fill_rect(c,rect,rgb_pixel(212,208,200));
const long height = rect.height();
const long width = rect.width();
const long smallest = (width < height) ? width : height;
const long rows = (smallest+3)/4;
const long start = rows + rows/2-1;
long dep;
long tip_x = 0;
long tip_y = 0;
long wy = 0;
long hy = 0;
long wx = 0;
long hx = 0;
if (button_action::is_depressed())
{
dep = 0;
// draw the button's border
draw_button_down(c,rect);
}
else
{
dep = -1;
// draw the button's border
draw_button_up(c,rect);
}
switch (dir)
{
case UP:
tip_x = width/2 + rect.left() + dep;
tip_y = (height - start)/2 + rect.top() + dep + 1;
wy = 0;
hy = 1;
wx = 1;
hx = 0;
break;
case DOWN:
tip_x = width/2 + rect.left() + dep;
tip_y = rect.bottom() - (height - start)/2 + dep;
wy = 0;
hy = -1;
wx = 1;
hx = 0;
break;
case LEFT:
tip_x = rect.left() + (width - start)/2 + dep + 1;
tip_y = height/2 + rect.top() + dep;
wy = 1;
hy = 0;
wx = 0;
hx = 1;
break;
case RIGHT:
tip_x = rect.right() - (width - start)/2 + dep;
tip_y = height/2 + rect.top() + dep;
wy = 1;
hy = 0;
wx = 0;
hx = -1;
break;
}
rgb_pixel color;
if (enabled)
{
color.red = 0;
color.green = 0;
color.blue = 0;
}
else
{
color.red = 128;
color.green = 128;
color.blue = 128;
}
for (long i = 0; i < rows; ++i)
{
draw_line(c,point(tip_x + wx*i + hx*i, tip_y + wy*i + hy*i),
point(tip_x + wx*i*-1 + hx*i, tip_y + wy*i*-1 + hy*i),
color);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// scroll_bar object methods
......@@ -494,8 +613,8 @@ namespace dlib
) :
drawable(w),
width_(16),
b1(w,arrow_button::UP),
b2(w,arrow_button::DOWN),
b1(w),
b2(w),
slider(w,*this,&scroll_bar::on_slider_drag),
ori(orientation),
top_filler(w,*this,&scroll_bar::top_filler_down,&scroll_bar::top_filler_up),
......@@ -510,8 +629,13 @@ namespace dlib
{
if (ori == HORIZONTAL)
{
b1.set_direction(arrow_button::LEFT);
b2.set_direction(arrow_button::RIGHT);
b1.set_style(button_style_left_arrow());
b2.set_style(button_style_right_arrow());
}
else
{
b1.set_style(button_style_up_arrow());
b2.set_style(button_style_down_arrow());
}
// don't show the slider when there is no place it can move.
......@@ -575,16 +699,15 @@ namespace dlib
{
rect.set_right(rect.left() + length - 1 );
rect.set_bottom(rect.top() + width_ - 1 );
b1.set_direction(arrow_button::LEFT);
b2.set_direction(arrow_button::RIGHT);
b1.set_style(button_style_left_arrow());
b2.set_style(button_style_right_arrow());
}
else
{
rect.set_right(rect.left() + width_ - 1);
rect.set_bottom(rect.top() + length - 1);
b1.set_direction(arrow_button::UP);
b2.set_direction(arrow_button::DOWN);
b1.set_style(button_style_up_arrow());
b2.set_style(button_style_down_arrow());
}
ori = new_orientation;
......
......@@ -15,6 +15,7 @@
#include "../pixel.h"
#include "../image_transforms.h"
#include "../array.h"
#include "style.h"
#include "../smart_pointers.h"
#include "../unicode.h"
#include <cctype>
......@@ -258,594 +259,500 @@ namespace dlib
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class arrow_button
// class widget_group
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class arrow_button : public button_action
class widget_group : public drawable
{
/*!
INITIAL VALUE
dir == whatever is given to the constructor
widgets.size() == 0
CONVENTION
- dir == direction()
Widgets contains all the drawable objects and their relative positions
that are in *this.
!*/
public:
enum arrow_direction
struct relpos
{
UP,
DOWN,
LEFT,
RIGHT
unsigned long x;
unsigned long y;
};
arrow_button(
drawable_window& w,
arrow_direction dir_
) :
button_action(w),
dir(dir_)
{
enable_events();
}
public:
widget_group(
drawable_window& w
) : drawable(w) { rect = rectangle(0,0,-1,-1); enable_events();}
virtual ~arrow_button(
){ disable_events(); parent.invalidate_rectangle(rect); }
virtual ~widget_group(
){ disable_events(); }
arrow_direction direction (
) const
{
auto_mutex M(m);
return dir;
}
void empty (
);
void set_direction (
arrow_direction new_direction
)
{
auto_mutex M(m);
dir = new_direction;
parent.invalidate_rectangle(rect);
}
void add (
drawable& widget,
unsigned long x,
unsigned long y
);
void set_size (
unsigned long width,
unsigned long height
bool is_member (
const drawable& widget
) const;
void remove (
const drawable& widget
);
bool is_depressed (
) const
{
auto_mutex M(m);
return button_action::is_depressed();
}
unsigned long size (
) const;
template <
typename T
>
void set_button_down_handler (
T& object,
void (T::*event_handler)()
void set_pos (
long x,
long y
);
void set_z_order (
long order
);
void show (
);
void hide (
);
void enable (
);
void disable (
);
void fit_to_contents (
);
protected:
// this object doesn't draw anything but also isn't abstract
void draw (
const canvas& c
) const {}
private:
map<drawable*,relpos>::kernel_1a_c widgets;
// restricted functions
widget_group(widget_group&); // copy constructor
widget_group& operator=(widget_group&); // assignment operator
};
// ----------------------------------------------------------------------------------------
class image_widget : public dragable
{
/*!
INITIAL VALUE
- img.size() == 0
CONVENTION
- img == the image this object displays
!*/
public:
image_widget(
drawable_window& w
): dragable(w) { enable_events(); }
~image_widget(
)
{
auto_mutex M(m);
button_down_handler.set(object,event_handler);
disable_events();
parent.invalidate_rectangle(rect);
}
template <
typename T
typename image_type
>
void set_button_up_handler (
T& object,
void (T::*event_handler)(bool mouse_over)
void set_image (
const image_type& new_img
)
{
auto_mutex M(m);
button_up_handler.set(object,event_handler);
assign_image(img,new_img);
rectangle old(rect);
rect.set_right(rect.left()+img.nc()-1);
rect.set_bottom(rect.top()+img.nr()-1);
parent.invalidate_rectangle(rect+old);
}
protected:
private:
void draw (
const canvas& c
) const;
void on_button_down (
)
{
if (button_down_handler.is_set())
button_down_handler();
}
) const
{
rectangle area = rect.intersect(c);
if (area.is_empty())
return;
void on_button_up (
bool mouse_over
)
{
if (button_up_handler.is_set())
button_up_handler(mouse_over);
draw_image(c, point(rect.left(),rect.top()), img);
}
private:
arrow_direction dir;
member_function_pointer<>::kernel_1a button_down_handler;
member_function_pointer<bool>::kernel_1a button_up_handler;
array2d<rgb_alpha_pixel>::kernel_1a img;
// restricted functions
arrow_button(arrow_button&); // copy constructor
arrow_button& operator=(arrow_button&); // assignment operator
image_widget(image_widget&); // copy constructor
image_widget& operator=(image_widget&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class scroll_bar
// class tooltip
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class scroll_bar : public drawable
class tooltip : public mouse_over_event
{
/*!
INITIAL VALUE
- ori == a value given by the constructor
- width_ == 16
- pos == 0
- max_pos == 0
- js == 10
- stuff.get() == 0
- events_are_enabled() == false
CONVENTION
- ori == orientation()
- b1 == the button that is near the 0 end of the scroll bar
- b2 == the button that is near the max_pos() end of the scroll bar
- max_pos == max_slider_pos()
- pos == slider_pos()
- js == jump_size()
- if (events_are_enabled() == true) then
- stuff.get() != 0
!*/
public:
enum bar_orientation
{
HORIZONTAL,
VERTICAL
};
scroll_bar(
drawable_window& w,
bar_orientation orientation_
);
virtual ~scroll_bar(
);
bar_orientation orientation (
) const;
void set_orientation (
bar_orientation new_orientation
);
void set_length (
unsigned long length
);
long max_slider_pos (
) const;
void set_max_slider_pos (
long mpos
);
void set_slider_pos (
long pos
);
tooltip(
drawable_window& w
) :
mouse_over_event(w,MOUSE_CLICK)
{}
long slider_pos (
) const;
~tooltip(
){ disable_events();}
template <
typename T
>
void set_scroll_handler (
T& object,
void (T::*eh)()
) { scroll_handler.set(object,eh); }
void set_size (
long width,
long height
)
{
auto_mutex M(m);
rect = resize_rect(rect,width,height);
}
void set_pos (
long x,
long y
);
void enable (
void set_text (
const std::string& str
)
{
if (!hidden)
show_slider();
if (max_pos != 0)
{
b1.enable();
b2.enable();
}
drawable::enable();
set_text(convert_mbstring_to_wstring(str));
}
void disable (
void set_text (
const std::wstring& str
)
{
hide_slider();
b1.disable();
b2.disable();
drawable::disable();
set_text(convert_wstring_to_utf32(str));
}
void hide (
void set_text (
const ustring& str
)
{
hide_slider();
top_filler.hide();
bottom_filler.hide();
b1.hide();
b2.hide();
drawable::hide();
auto_mutex M(m);
if (!stuff)
{
stuff.reset(new data(*this));
enable_events();
}
stuff->win.set_text(str);
}
void show (
)
const std::string text (
) const
{
b1.show();
b2.show();
drawable::show();
top_filler.show();
if (enabled)
show_slider();
return convert_wstring_to_mbstring(wtext());
}
void set_z_order (
long order
)
const std::wstring wtext (
) const
{
slider.set_z_order(order);
top_filler.set_z_order(order);
bottom_filler.set_z_order(order);
b1.set_z_order(order);
b2.set_z_order(order);
drawable::set_z_order(order);
return convert_utf32_to_wstring(utext());
}
void set_jump_size (
long js
);
long jump_size (
) const;
private:
void hide_slider (
);
/*!
ensures
- hides the slider and makes any other changes needed so that the
scroll_bar still looks right.
!*/
void show_slider (
);
/*!
ensures
- shows the slider and makes any other changes needed so that the
scroll_bar still looks right.
!*/
void on_slider_drag (
);
/*!
requires
- is called whenever the user drags the slider
!*/
void draw (
const canvas& c
) const;
void b1_down (
);
void b1_up (
bool mouse_over
);
void b2_down (
);
void b2_up (
bool mouse_over
);
void top_filler_down (
);
void top_filler_up (
bool mouse_over
);
void bottom_filler_down (
);
void bottom_filler_up (
bool mouse_over
);
const dlib::ustring utext (
) const
{
auto_mutex M(m);
dlib::ustring temp;
if (stuff)
{
temp = stuff->win.text;
}
return temp.c_str();
}
void on_user_event (
int i
void hide (
)
{
switch (i)
auto_mutex M(m);
mouse_over_event::hide();
if (stuff)
{
case 0:
b1_down();
break;
case 1:
b2_down();
break;
case 2:
top_filler_down();
break;
case 3:
bottom_filler_down();
break;
case 4:
// if the position we are supposed to switch the slider too isn't
// already set
if (delayed_pos != pos)
{
set_slider_pos(delayed_pos);
if (scroll_handler.is_set())
scroll_handler();
}
break;
default:
break;
stuff->tt_timer.stop();
stuff->win.hide();
}
}
void delayed_set_slider_pos (
unsigned long dpos
)
void disable (
)
{
delayed_pos = dpos;
parent.trigger_user_event(this,4);
auto_mutex M(m);
mouse_over_event::disable();
if (stuff)
{
stuff->tt_timer.stop();
stuff->win.hide();
}
}
void b1_down_t (
) { parent.trigger_user_event(this,0); }
protected:
void b2_down_t (
) { parent.trigger_user_event(this,1); }
void on_mouse_over()
{
stuff->x = lastx;
stuff->y = lasty;
stuff->tt_timer.start();
}
void top_filler_down_t (
) { parent.trigger_user_event(this,2); }
void on_mouse_not_over ()
{
stuff->tt_timer.stop();
stuff->win.hide();
}
void bottom_filler_down_t (
) { parent.trigger_user_event(this,3); }
void on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
)
{
mouse_over_event::on_mouse_down(btn,state,x,y,is_double_click);
stuff->tt_timer.stop();
stuff->win.hide();
}
void draw (
const canvas&
) const{}
private:
class filler : public button_action
class tooltip_window : public base_window
{
friend class scroll_bar;
public:
filler (
drawable_window& w,
scroll_bar& object,
void (scroll_bar::*down)(),
void (scroll_bar::*up)(bool)
):
button_action(w)
tooltip_window (const shared_ptr_thread_safe<font>& f) : base_window(false,true), pad(3), mfont(f)
{
bup.set(object,up);
bdown.set(object,down);
enable_events();
}
~filler (
ustring text;
rectangle rect_all;
rectangle rect_text;
const unsigned long pad;
const shared_ptr_thread_safe<font> mfont;
void set_text (
const std::string& str
)
{
disable_events();
set_text(convert_mbstring_to_wstring(str));
}
void set_size (
unsigned long width,
unsigned long height
void set_text (
const std::wstring& str
)
{
rectangle old(rect);
const unsigned long x = rect.left();
const unsigned long y = rect.top();
rect.set_right(x+width-1);
rect.set_bottom(y+height-1);
parent.invalidate_rectangle(rect+old);
}
private:
void draw (
const canvas& c
) const
{
if (is_depressed())
draw_checkered(c, rect,rgb_pixel(0,0,0),rgb_pixel(43,47,55));
else
draw_checkered(c, rect,rgb_pixel(255,255,255),rgb_pixel(212,208,200));
}
void on_button_down (
) { bdown(); }
void on_button_up (
bool mouse_over
) { bup(mouse_over); }
member_function_pointer<>::kernel_1a bdown;
member_function_pointer<bool>::kernel_1a bup;
};
class slider_class : public dragable
{
friend class scroll_bar;
public:
slider_class (
drawable_window& w,
scroll_bar& object,
void (scroll_bar::*handler)()
) :
dragable(w)
{
mfp.set(object,handler);
enable_events();
set_text(convert_wstring_to_utf32(str));
}
~slider_class (
void set_text (
const dlib::ustring& str
)
{
disable_events();
}
text = str.c_str();
void set_size (
unsigned long width,
unsigned long height
)
{
rectangle old(rect);
const unsigned long x = rect.left();
const unsigned long y = rect.top();
rect.set_right(x+width-1);
rect.set_bottom(y+height-1);
unsigned long width, height;
mfont->compute_size(text,width,height);
parent.invalidate_rectangle(rect+old);
set_size(width+pad*2, height+pad*2);
rect_all.set_left(0);
rect_all.set_top(0);
rect_all.set_right(width+pad*2-1);
rect_all.set_bottom(height+pad*2-1);
rect_text = move_rect(rectangle(width,height),pad,pad);
}
private:
void on_drag (
)
void paint(const canvas& c)
{
mfp();
c.fill(255,255,150);
draw_rectangle(c, rect_all);
mfont->draw_string(c,rect_text,text);
}
};
void draw (
const canvas& c
) const
void show_tooltip (
)
{
auto_mutex M(m);
long x, y;
// if the mouse has moved since we started the timer then
// keep waiting until the user stops moving it
if (lastx != stuff->x || lasty != stuff->y)
{
fill_rect(c, rect, rgb_pixel(212,208,200));
draw_button_up(c, rect);
stuff->x = lastx;
stuff->y = lasty;
return;
}
member_function_pointer<>::kernel_1a mfp;
};
unsigned long display_width, display_height;
// stop the timer
stuff->tt_timer.stop();
parent.get_pos(x,y);
x += lastx+15;
y += lasty+15;
// make sure the tooltip isn't going to be off the screen
parent.get_display_size(display_width, display_height);
rectangle wrect(move_rect(stuff->win.rect_all,x,y));
rectangle srect(display_width, display_height);
if (srect.contains(wrect) == false)
{
rectangle temp(srect.intersect(wrect));
x -= wrect.width()-temp.width();
y -= wrect.height()-temp.height();
}
void adjust_fillers (
);
/*!
ensures
- top_filler and bottom_filler appear in their correct positions
relative to the current positions of the slider and the b1 and
b2 buttons
!*/
stuff->win.set_pos(x,y);
stuff->win.show();
}
unsigned long get_slider_size (
) const;
/*!
ensures
- returns the length in pixels the slider should have based on the current
state of this scroll bar
!*/
// put all this stuff in data so we can arrange to only
// construct it when someone is actually using the tooltip widget
// rather than just instantiating it.
struct data
{
data(
tooltip& self
) :
x(-1),
y(-1),
win(self.mfont),
tt_timer(self,&tooltip::show_tooltip)
{
tt_timer.set_delay_time(400);
}
long x, y;
tooltip_window win;
timer<tooltip>::kernel_2a tt_timer;
const unsigned long width_;
arrow_button b1, b2;
slider_class slider;
bar_orientation ori;
filler top_filler, bottom_filler;
member_function_pointer<>::kernel_1a scroll_handler;
};
friend struct data;
scoped_ptr<data> stuff;
long pos;
long max_pos;
long js;
timer<scroll_bar>::kernel_2a b1_timer;
timer<scroll_bar>::kernel_2a b2_timer;
timer<scroll_bar>::kernel_2a top_filler_timer;
timer<scroll_bar>::kernel_2a bottom_filler_timer;
long delayed_pos;
// restricted functions
scroll_bar(scroll_bar&); // copy constructor
scroll_bar& operator=(scroll_bar&); // assignment operator
tooltip(tooltip&); // copy constructor
tooltip& operator=(tooltip&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class widget_group
// class button
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class widget_group : public drawable
class button : public button_action
{
/*!
INITIAL VALUE
widgets.size() == 0
CONVENTION
Widgets contains all the drawable objects and their relative positions
that are in *this.
!*/
struct relpos
{
unsigned long x;
unsigned long y;
};
public:
widget_group(
button(
drawable_window& w
) : drawable(w) { rect = rectangle(0,0,-1,-1); enable_events();}
) :
button_action(w),
btn_tooltip(w)
{
style.reset(new button_style_default());
enable_events();
}
~button() { disable_events(); parent.invalidate_rectangle(rect); }
virtual ~widget_group(
){ disable_events(); }
void set_size (
unsigned long width,
unsigned long height
);
void empty (
void set_name (
const std::string& name_
);
void add (
drawable& widget,
unsigned long x,
unsigned long y
void set_name (
const std::wstring& name_
);
bool is_member (
const drawable& widget
void set_name (
const dlib::ustring& name_
);
const std::string name (
) const;
void remove (
const drawable& widget
const std::wstring wname (
) const;
const dlib::ustring uname (
) const;
void set_tooltip_text (
const std::string& text
);
unsigned long size (
) const;
void set_tooltip_text (
const std::wstring& text
);
void set_pos (
void set_tooltip_text (
const dlib::ustring& text
);
void set_pos(
long x,
long y
);
void set_z_order (
long order
const std::string tooltip_text (
) const;
const std::wstring tooltip_wtext (
) const;
const dlib::ustring tooltip_utext (
) const;
void set_main_font (
const shared_ptr_thread_safe<font>& f
);
void show (
......@@ -860,353 +767,546 @@ namespace dlib
void disable (
);
void fit_to_contents (
);
protected:
// this object doesn't draw anything but also isn't abstract
void draw (
const canvas& c
) const {}
private:
map<drawable*,relpos>::kernel_1a_c widgets;
// restricted functions
widget_group(widget_group&); // copy constructor
widget_group& operator=(widget_group&); // assignment operator
};
template <
typename style_type
>
void set_style (
const style_type& style_
)
{
auto_mutex M(m);
style.reset(new style_type(style_));
rect = move_rect(style->get_min_size(name_,*mfont), rect.left(), rect.top());
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler_)()
)
{
auto_mutex M(m);
event_handler.set(object,event_handler_);
event_handler_self.clear();
}
class image_widget : public dragable
{
/*!
INITIAL VALUE
- img.size() == 0
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler_)(button&)
)
{
auto_mutex M(m);
event_handler_self.set(object,event_handler_);
event_handler.clear();
}
CONVENTION
- img == the image this object displays
!*/
bool is_depressed (
) const
{
auto_mutex M(m);
return button_action::is_depressed();
}
public:
template <
typename T
>
void set_button_down_handler (
T& object,
void (T::*event_handler)()
)
{
auto_mutex M(m);
button_down_handler.set(object,event_handler);
}
image_widget(
drawable_window& w
): dragable(w) { enable_events(); }
template <
typename T
>
void set_button_up_handler (
T& object,
void (T::*event_handler)(bool mouse_over)
)
{
auto_mutex M(m);
button_up_handler.set(object,event_handler);
}
~image_widget(
template <
typename T
>
void set_button_down_handler (
T& object,
void (T::*event_handler)(button&)
)
{
disable_events();
parent.invalidate_rectangle(rect);
auto_mutex M(m);
button_down_handler_self.set(object,event_handler);
}
template <
typename image_type
typename T
>
void set_image (
const image_type& new_img
void set_button_up_handler (
T& object,
void (T::*event_handler)(bool mouse_over, button&)
)
{
auto_mutex M(m);
assign_image(img,new_img);
rectangle old(rect);
rect.set_right(rect.left()+img.nc()-1);
rect.set_bottom(rect.top()+img.nr()-1);
parent.invalidate_rectangle(rect+old);
button_up_handler_self.set(object,event_handler);
}
private:
// restricted functions
button(button&); // copy constructor
button& operator=(button&); // assignment operator
dlib::ustring name_;
tooltip btn_tooltip;
member_function_pointer<>::kernel_1a event_handler;
member_function_pointer<button&>::kernel_1a event_handler_self;
member_function_pointer<>::kernel_1a button_down_handler;
member_function_pointer<bool>::kernel_1a button_up_handler;
member_function_pointer<button&>::kernel_1a button_down_handler_self;
member_function_pointer<bool,button&>::kernel_1a button_up_handler_self;
scoped_ptr<button_style> style;
protected:
void draw (
const canvas& c
) const
{
rectangle area = rect.intersect(c);
if (area.is_empty())
return;
) const { style->draw_button(c,rect,hidden,enabled,*mfont,lastx,lasty,name_,is_depressed()); }
draw_image(c, point(rect.left(),rect.top()), img);
}
void on_button_up (
bool mouse_over
);
array2d<rgb_alpha_pixel>::kernel_1a img;
void on_button_down (
);
// restricted functions
image_widget(image_widget&); // copy constructor
image_widget& operator=(image_widget&); // assignment operator
void on_mouse_over (
){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); }
void on_mouse_not_over (
){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); }
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class tooltip
// class scroll_bar
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class tooltip : public mouse_over_event
class scroll_bar : public drawable
{
/*!
INITIAL VALUE
- stuff.get() == 0
- events_are_enabled() == false
- ori == a value given by the constructor
- width_ == 16
- pos == 0
- max_pos == 0
- js == 10
CONVENTION
- if (events_are_enabled() == true) then
- stuff.get() != 0
- ori == orientation()
- b1 == the button that is near the 0 end of the scroll bar
- b2 == the button that is near the max_pos() end of the scroll bar
- max_pos == max_slider_pos()
- pos == slider_pos()
- js == jump_size()
!*/
public:
enum bar_orientation
{
HORIZONTAL,
VERTICAL
};
tooltip(
drawable_window& w
) :
mouse_over_event(w,MOUSE_CLICK)
{}
scroll_bar(
drawable_window& w,
bar_orientation orientation_
);
~tooltip(
){ disable_events();}
virtual ~scroll_bar(
);
void set_size (
long width,
long height
)
{
auto_mutex M(m);
rect = resize_rect(rect,width,height);
}
bar_orientation orientation (
) const;
void set_orientation (
bar_orientation new_orientation
);
void set_text (
const std::string& str
void set_length (
unsigned long length
);
long max_slider_pos (
) const;
void set_max_slider_pos (
long mpos
);
void set_slider_pos (
long pos
);
long slider_pos (
) const;
template <
typename T
>
void set_scroll_handler (
T& object,
void (T::*eh)()
) { scroll_handler.set(object,eh); }
void set_pos (
long x,
long y
);
void enable (
)
{
set_text(convert_mbstring_to_wstring(str));
if (!hidden)
show_slider();
if (max_pos != 0)
{
b1.enable();
b2.enable();
}
drawable::enable();
}
void set_text (
const std::wstring& str
void disable (
)
{
set_text(convert_wstring_to_utf32(str));
hide_slider();
b1.disable();
b2.disable();
drawable::disable();
}
void set_text (
const ustring& str
void hide (
)
{
auto_mutex M(m);
if (!stuff)
{
stuff.reset(new data(*this));
enable_events();
}
stuff->win.set_text(str);
hide_slider();
top_filler.hide();
bottom_filler.hide();
b1.hide();
b2.hide();
drawable::hide();
}
const std::string text (
) const
void show (
)
{
return convert_wstring_to_mbstring(wtext());
b1.show();
b2.show();
drawable::show();
top_filler.show();
if (enabled)
show_slider();
}
const std::wstring wtext (
) const
void set_z_order (
long order
)
{
return convert_utf32_to_wstring(utext());
slider.set_z_order(order);
top_filler.set_z_order(order);
bottom_filler.set_z_order(order);
b1.set_z_order(order);
b2.set_z_order(order);
drawable::set_z_order(order);
}
const dlib::ustring utext (
) const
{
auto_mutex M(m);
dlib::ustring temp;
if (stuff)
{
temp = stuff->win.text;
}
return temp.c_str();
}
void set_jump_size (
long js
);
void hide (
long jump_size (
) const;
private:
void hide_slider (
);
/*!
ensures
- hides the slider and makes any other changes needed so that the
scroll_bar still looks right.
!*/
void show_slider (
);
/*!
ensures
- shows the slider and makes any other changes needed so that the
scroll_bar still looks right.
!*/
void on_slider_drag (
);
/*!
requires
- is called whenever the user drags the slider
!*/
void draw (
const canvas& c
) const;
void b1_down (
);
void b1_up (
bool mouse_over
);
void b2_down (
);
void b2_up (
bool mouse_over
);
void top_filler_down (
);
void top_filler_up (
bool mouse_over
);
void bottom_filler_down (
);
void bottom_filler_up (
bool mouse_over
);
void on_user_event (
int i
)
{
auto_mutex M(m);
mouse_over_event::hide();
if (stuff)
switch (i)
{
stuff->tt_timer.stop();
stuff->win.hide();
case 0:
b1_down();
break;
case 1:
b2_down();
break;
case 2:
top_filler_down();
break;
case 3:
bottom_filler_down();
break;
case 4:
// if the position we are supposed to switch the slider too isn't
// already set
if (delayed_pos != pos)
{
set_slider_pos(delayed_pos);
if (scroll_handler.is_set())
scroll_handler();
}
break;
default:
break;
}
}
void disable (
)
void delayed_set_slider_pos (
unsigned long dpos
)
{
auto_mutex M(m);
mouse_over_event::disable();
if (stuff)
{
stuff->tt_timer.stop();
stuff->win.hide();
}
delayed_pos = dpos;
parent.trigger_user_event(this,4);
}
protected:
void on_mouse_over()
{
stuff->x = lastx;
stuff->y = lasty;
stuff->tt_timer.start();
}
void b1_down_t (
) { parent.trigger_user_event(this,0); }
void on_mouse_not_over ()
{
stuff->tt_timer.stop();
stuff->win.hide();
}
void b2_down_t (
) { parent.trigger_user_event(this,1); }
void on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
)
{
mouse_over_event::on_mouse_down(btn,state,x,y,is_double_click);
stuff->tt_timer.stop();
stuff->win.hide();
}
void top_filler_down_t (
) { parent.trigger_user_event(this,2); }
void draw (
const canvas&
) const{}
void bottom_filler_down_t (
) { parent.trigger_user_event(this,3); }
private:
class tooltip_window : public base_window
class filler : public button_action
{
friend class scroll_bar;
public:
tooltip_window (const shared_ptr_thread_safe<font>& f) : base_window(false,true), pad(3), mfont(f)
filler (
drawable_window& w,
scroll_bar& object,
void (scroll_bar::*down)(),
void (scroll_bar::*up)(bool)
):
button_action(w)
{
bup.set(object,up);
bdown.set(object,down);
enable_events();
}
ustring text;
rectangle rect_all;
rectangle rect_text;
const unsigned long pad;
const shared_ptr_thread_safe<font> mfont;
void set_text (
const std::string& str
~filler (
)
{
set_text(convert_mbstring_to_wstring(str));
disable_events();
}
void set_text (
const std::wstring& str
void set_size (
unsigned long width,
unsigned long height
)
{
set_text(convert_wstring_to_utf32(str));
rectangle old(rect);
const unsigned long x = rect.left();
const unsigned long y = rect.top();
rect.set_right(x+width-1);
rect.set_bottom(y+height-1);
parent.invalidate_rectangle(rect+old);
}
void set_text (
const dlib::ustring& str
)
private:
void draw (
const canvas& c
) const
{
text = str.c_str();
if (is_depressed())
draw_checkered(c, rect,rgb_pixel(0,0,0),rgb_pixel(43,47,55));
else
draw_checkered(c, rect,rgb_pixel(255,255,255),rgb_pixel(212,208,200));
}
unsigned long width, height;
mfont->compute_size(text,width,height);
void on_button_down (
) { bdown(); }
set_size(width+pad*2, height+pad*2);
rect_all.set_left(0);
rect_all.set_top(0);
rect_all.set_right(width+pad*2-1);
rect_all.set_bottom(height+pad*2-1);
void on_button_up (
bool mouse_over
) { bup(mouse_over); }
rect_text = move_rect(rectangle(width,height),pad,pad);
member_function_pointer<>::kernel_1a bdown;
member_function_pointer<bool>::kernel_1a bup;
};
class slider_class : public dragable
{
friend class scroll_bar;
public:
slider_class (
drawable_window& w,
scroll_bar& object,
void (scroll_bar::*handler)()
) :
dragable(w)
{
mfp.set(object,handler);
enable_events();
}
void paint(const canvas& c)
~slider_class (
)
{
c.fill(255,255,150);
draw_rectangle(c, rect_all);
mfont->draw_string(c,rect_text,text);
disable_events();
}
};
void show_tooltip (
)
{
auto_mutex M(m);
long x, y;
// if the mouse has moved since we started the timer then
// keep waiting until the user stops moving it
if (lastx != stuff->x || lasty != stuff->y)
void set_size (
unsigned long width,
unsigned long height
)
{
stuff->x = lastx;
stuff->y = lasty;
return;
rectangle old(rect);
const unsigned long x = rect.left();
const unsigned long y = rect.top();
rect.set_right(x+width-1);
rect.set_bottom(y+height-1);
parent.invalidate_rectangle(rect+old);
}
unsigned long display_width, display_height;
// stop the timer
stuff->tt_timer.stop();
parent.get_pos(x,y);
x += lastx+15;
y += lasty+15;
private:
void on_drag (
)
{
mfp();
}
// make sure the tooltip isn't going to be off the screen
parent.get_display_size(display_width, display_height);
rectangle wrect(move_rect(stuff->win.rect_all,x,y));
rectangle srect(display_width, display_height);
if (srect.contains(wrect) == false)
void draw (
const canvas& c
) const
{
rectangle temp(srect.intersect(wrect));
x -= wrect.width()-temp.width();
y -= wrect.height()-temp.height();
fill_rect(c, rect, rgb_pixel(212,208,200));
draw_button_up(c, rect);
}
stuff->win.set_pos(x,y);
stuff->win.show();
}
member_function_pointer<>::kernel_1a mfp;
};
// put all this stuff in data so we can arrange to only
// construct it when someone is actually using the tooltip widget
// rather than just instantiating it.
struct data
{
data(
tooltip& self
) :
x(-1),
y(-1),
win(self.mfont),
tt_timer(self,&tooltip::show_tooltip)
{
tt_timer.set_delay_time(400);
}
long x, y;
tooltip_window win;
timer<tooltip>::kernel_2a tt_timer;
void adjust_fillers (
);
/*!
ensures
- top_filler and bottom_filler appear in their correct positions
relative to the current positions of the slider and the b1 and
b2 buttons
!*/
};
friend struct data;
scoped_ptr<data> stuff;
unsigned long get_slider_size (
) const;
/*!
ensures
- returns the length in pixels the slider should have based on the current
state of this scroll bar
!*/
const unsigned long width_;
button b1, b2;
slider_class slider;
bar_orientation ori;
filler top_filler, bottom_filler;
member_function_pointer<>::kernel_1a scroll_handler;
long pos;
long max_pos;
long js;
timer<scroll_bar>::kernel_2a b1_timer;
timer<scroll_bar>::kernel_2a b2_timer;
timer<scroll_bar>::kernel_2a top_filler_timer;
timer<scroll_bar>::kernel_2a bottom_filler_timer;
long delayed_pos;
// restricted functions
tooltip(tooltip&); // copy constructor
tooltip& operator=(tooltip&); // assignment operator
scroll_bar(scroll_bar&); // copy constructor
scroll_bar& operator=(scroll_bar&); // assignment operator
};
// ----------------------------------------------------------------------------------------
......
......@@ -329,80 +329,103 @@ namespace dlib
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class arrow_button
// class button
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class arrow_button : public button_action
class button : public button_action
{
/*!
INITIAL VALUE
direction() == a value given to the constructor.
name() == ""
tooltip_text() == "" (i.e. there is no tooltip by default)
WHAT THIS OBJECT REPRESENTS
This object represents a push button with an arrow in the middle.
This object represents a simple button.
When this object is disabled it means it will not respond to user clicks.
!*/
public:
enum arrow_direction
{
UP,
DOWN,
LEFT,
RIGHT
};
arrow_button(
drawable_window& w,
arrow_direction dir
button(
drawable_window& w
);
/*!
ensures
- #*this is properly initialized
- #*this has been added to window w
- #direction() == dir
- #parent_window() == w
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~arrow_button(
virtual ~button(
);
/*!
ensures
- all resources associated with *this have been released
!*/
arrow_direction direction (
void set_size (
unsigned long width_,
unsigned long height_
);
/*!
ensures
- if (width and height are big enough to contain the name of this button) then
- #width() == width_
- #height() == height_
- #top() == top()
- #left() == left()
- i.e. The location of the upper left corner of this button stays the
same but its width and height are modified
!*/
void set_name (const std::wstring& name);
void set_name (const dlib::ustring& name);
void set_name (
const std::string& name
);
/*!
ensures
- #name() == name
- this button has been resized such that it is big enough to contain
the new name.
throws
- std::bad_alloc
!*/
const std::wstring wname () const;
const dlib::string uname () const;
const std::string name (
) const;
/*!
ensures
- returns the direction that this arrow_button's arrow points
- returns the name of this button
throws
- std::bad_alloc
!*/
void set_direction (
arrow_direction new_direction
void set_tooltip_text (const std::wstring& text);
void set_tooltip_text (const dlib::ustring& text);
void set_tooltip_text (
const std::string& text
);
/*!
ensures
- #direction() == new_direction
- #tooltip_text() == text
- enables the tooltip for this button
!*/
void set_size (
unsigned long width_,
unsigned long height_
);
/*!
const dlib::ustring tooltip_utext () const;
const std::wstring tooltip_wtext () const;
const std::string tooltip_text (
) const;
/*!
ensures
- #width() == width_
- #height() == height_
- #top() == top()
- #left() == left()
- i.e. The location of the upper left corner of this button stays the
same but its width and height are modified
- returns the text that is displayed in the tooltip for this button
!*/
bool is_depressed (
......@@ -410,13 +433,68 @@ namespace dlib
/*!
ensures
- if (this button is currently in a depressed state) then
- the user has left clicked on this drawable and is still
- the user has left clicked on this widget and is still
holding the left mouse button down over it.
- returns true
- else
- returns false
!*/
template <
typename style_type
>
void set_style (
const style_type& style
);
/*!
requires
- style_type == a type that inherits from button_style
ensures
- this button object will draw itself using the given
button style
!*/
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler)()
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- the event_handler function is called on object when the button is
clicked by the user.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler)(button& self)
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- &self == this
- the event_handler function is called on object when the button is
clicked by the user.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
......@@ -426,10 +504,10 @@ namespace dlib
);
/*!
requires
- event_handler is a valid pointer to a member function in T
- event_handler is a valid pointer to a member function in T
ensures
- The event_handler function is called whenever this object transitions
from the state where is_depressed() == false to is_depressed() == true
- the event_handler function is called on object when the user causes
the button to go into its depressed state.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
......@@ -446,15 +524,60 @@ namespace dlib
);
/*!
requires
- event_handler is a valid pointer to a member function in T
- event_handler is a valid pointer to a member function in T
ensures
- the event_handler function is called on object when the user causes
the button to go into its non-depressed state.
- if (the mouse is over this button when this event occurs) then
- mouse_over == true
- else
- mouse_over == false
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_button_down_handler (
T& object,
void (T::*event_handler)(button& self)
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- The event_handler function is called whenever this object transitions
from the state where is_depressed() == true to is_depressed() == false.
furthermore:
- if (the mouse was over this button when this event occurred) then
- mouse_over == true
- else
- mouse_over == false
- &self == this
- the event_handler function is called on object when the user causes
the button to go into its depressed state.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_button_up_handler (
T& object,
void (T::*event_handler)(bool mouse_over, button& self)
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- &self == this
- the event_handler function is called on object when the user causes
the button to go into its non-depressed state.
- if (the mouse is over this button when this event occurs) then
- mouse_over == true
- else
- mouse_over == false
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
......@@ -465,8 +588,8 @@ namespace dlib
private:
// restricted functions
arrow_button(arrow_button&); // copy constructor
arrow_button& operator=(arrow_button&); // assignment operator
button(button&); // copy constructor
button& operator=(button&); // assignment operator
};
// ----------------------------------------------------------------------------------------
......
......@@ -275,6 +275,212 @@ namespace dlib
return rectangle(img_normal.nc()+2*padding, img_normal.nr()+2*padding);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
namespace arrow_button_style_helper
{
enum arrow_direction
{
UP,
DOWN,
LEFT,
RIGHT
};
void draw_arrow_button (
const canvas& c,
const rectangle& rect,
const bool enabled,
const bool is_depressed,
const arrow_direction dir
)
{
rectangle area = rect.intersect(c);
if (area.is_empty())
return;
fill_rect(c,rect,rgb_pixel(212,208,200));
const long height = rect.height();
const long width = rect.width();
const long smallest = (width < height) ? width : height;
const long rows = (smallest+3)/4;
const long start = rows + rows/2-1;
long dep;
long tip_x = 0;
long tip_y = 0;
long wy = 0;
long hy = 0;
long wx = 0;
long hx = 0;
if (is_depressed)
{
dep = 0;
// draw the button's border
draw_button_down(c,rect);
}
else
{
dep = -1;
// draw the button's border
draw_button_up(c,rect);
}
switch (dir)
{
case UP:
tip_x = width/2 + rect.left() + dep;
tip_y = (height - start)/2 + rect.top() + dep + 1;
wy = 0;
hy = 1;
wx = 1;
hx = 0;
break;
case DOWN:
tip_x = width/2 + rect.left() + dep;
tip_y = rect.bottom() - (height - start)/2 + dep;
wy = 0;
hy = -1;
wx = 1;
hx = 0;
break;
case LEFT:
tip_x = rect.left() + (width - start)/2 + dep + 1;
tip_y = height/2 + rect.top() + dep;
wy = 1;
hy = 0;
wx = 0;
hx = 1;
break;
case RIGHT:
tip_x = rect.right() - (width - start)/2 + dep;
tip_y = height/2 + rect.top() + dep;
wy = 1;
hy = 0;
wx = 0;
hx = -1;
break;
}
rgb_pixel color;
if (enabled)
{
color.red = 0;
color.green = 0;
color.blue = 0;
}
else
{
color.red = 128;
color.green = 128;
color.blue = 128;
}
for (long i = 0; i < rows; ++i)
{
draw_line(c,point(tip_x + wx*i + hx*i, tip_y + wy*i + hy*i),
point(tip_x + wx*i*-1 + hx*i, tip_y + wy*i*-1 + hy*i),
color);
}
}
}
void button_style_left_arrow::
draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const
{
using namespace arrow_button_style_helper;
draw_arrow_button(c, rect, enabled, is_depressed, LEFT);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void button_style_right_arrow::
draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const
{
using namespace arrow_button_style_helper;
draw_arrow_button(c, rect, enabled, is_depressed, RIGHT);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void button_style_up_arrow::
draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const
{
using namespace arrow_button_style_helper;
draw_arrow_button(c, rect, enabled, is_depressed, UP);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void button_style_down_arrow::
draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const
{
using namespace arrow_button_style_helper;
draw_arrow_button(c, rect, enabled, is_depressed, DOWN);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// toggle button style stuff
......
......@@ -215,6 +215,98 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
class button_style_left_arrow : public button_style
{
public:
virtual void draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const;
virtual rectangle get_min_size (
const ustring& name,
const font& mfont
) const { return rectangle(); }
};
// ----------------------------------------------------------------------------------------
class button_style_right_arrow : public button_style
{
public:
virtual void draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const;
virtual rectangle get_min_size (
const ustring& name,
const font& mfont
) const { return rectangle(); }
};
// ----------------------------------------------------------------------------------------
class button_style_up_arrow : public button_style
{
public:
virtual void draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const;
virtual rectangle get_min_size (
const ustring& name,
const font& mfont
) const { return rectangle(); }
};
// ----------------------------------------------------------------------------------------
class button_style_down_arrow : public button_style
{
public:
virtual void draw_button (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const font& mfont,
const long lastx,
const long lasty,
const ustring& name,
const bool is_depressed
) const;
virtual rectangle get_min_size (
const ustring& name,
const font& mfont
) const { return rectangle(); }
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// toggle button styles
......
......@@ -122,6 +122,42 @@ namespace dlib
!*/
};
// ----------------------------------------------------------------------------------------
class button_style_left_arrow : public button_style
{
/*!
This draws a simple button with a left pointing arrow in it
!*/
};
// ----------------------------------------------------------------------------------------
class button_style_right_arrow : public button_style
{
/*!
This draws a simple button with a right pointing arrow in it
!*/
};
// ----------------------------------------------------------------------------------------
class button_style_up_arrow : public button_style
{
/*!
This draws a simple button with an up pointing arrow in it
!*/
};
// ----------------------------------------------------------------------------------------
class button_style_down_arrow : public button_style
{
/*!
This draws a simple button with a down pointing arrow in it
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// toggle button styles
......
......@@ -9,242 +9,6 @@
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// button object methods
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void button::
set_size (
unsigned long width,
unsigned long height
)
{
auto_mutex M(m);
rectangle min_rect = style->get_min_size(name_,*mfont);
// only change the size if it isn't going to be too small to fit the name
if (height >= min_rect.height() &&
width >= min_rect.width())
{
rectangle old(rect);
rect = resize_rect(rect,width,height);
parent.invalidate_rectangle(rect+old);
btn_tooltip.set_size(width,height);
}
}
// ----------------------------------------------------------------------------------------
void button::
show (
)
{
button_action::show();
btn_tooltip.show();
}
// ----------------------------------------------------------------------------------------
void button::
hide (
)
{
button_action::hide();
btn_tooltip.hide();
}
// ----------------------------------------------------------------------------------------
void button::
enable (
)
{
button_action::enable();
btn_tooltip.enable();
}
// ----------------------------------------------------------------------------------------
void button::
disable (
)
{
button_action::disable();
btn_tooltip.disable();
}
// ----------------------------------------------------------------------------------------
void button::
set_tooltip_text (
const std::string& text
)
{
btn_tooltip.set_text(text);
}
// ----------------------------------------------------------------------------------------
void button::
set_tooltip_text (
const std::wstring& text
)
{
btn_tooltip.set_text(text);
}
// ----------------------------------------------------------------------------------------
void button::
set_tooltip_text (
const ustring& text
)
{
btn_tooltip.set_text(text);
}
// ----------------------------------------------------------------------------------------
const std::string button::
tooltip_text (
) const
{
return btn_tooltip.text();
}
const std::wstring button::
tooltip_wtext (
) const
{
return btn_tooltip.wtext();
}
const dlib::ustring button::
tooltip_utext (
) const
{
return btn_tooltip.utext();
}
// ----------------------------------------------------------------------------------------
void button::
set_main_font (
const shared_ptr_thread_safe<font>& f
)
{
auto_mutex M(m);
mfont = f;
set_name(name_);
}
// ----------------------------------------------------------------------------------------
void button::
set_pos (
long x,
long y
)
{
auto_mutex M(m);
button_action::set_pos(x,y);
btn_tooltip.set_pos(x,y);
}
// ----------------------------------------------------------------------------------------
void button::
set_name (
const std::string& name
)
{
set_name(convert_mbstring_to_wstring(name));
}
void button::
set_name (
const std::wstring& name
)
{
set_name(convert_wstring_to_utf32(name));
}
void button::
set_name (
const ustring& name
)
{
auto_mutex M(m);
name_ = name;
// do this to get rid of any reference counting that may be present in
// the std::string implementation.
name_[0] = name_[0];
rectangle old(rect);
rect = move_rect(style->get_min_size(name,*mfont),rect.left(),rect.top());
btn_tooltip.set_size(rect.width(),rect.height());
parent.invalidate_rectangle(rect+old);
}
// ----------------------------------------------------------------------------------------
const std::string button::
name (
) const
{
auto_mutex M(m);
std::string temp = convert_wstring_to_mbstring(wname());
// do this to get rid of any reference counting that may be present in
// the std::string implementation.
char c = temp[0];
temp[0] = c;
return temp;
}
const std::wstring button::
wname (
) const
{
auto_mutex M(m);
std::wstring temp = convert_utf32_to_wstring(uname());
// do this to get rid of any reference counting that may be present in
// the std::wstring implementation.
wchar_t w = temp[0];
temp[0] = w;
return temp;
}
const dlib::ustring button::
uname (
) const
{
auto_mutex M(m);
dlib::ustring temp = name_;
// do this to get rid of any reference counting that may be present in
// the dlib::ustring implementation.
temp[0] = name_[0];
return temp;
}
// ----------------------------------------------------------------------------------------
void button::
on_button_up (
bool mouse_over
)
{
if (mouse_over)
{
// this is a valid button click
if (event_handler.is_set())
event_handler();
else if (event_handler_self.is_set())
event_handler_self(*this);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// toggle_button object methods
......
......@@ -108,165 +108,6 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class button
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class button : public button_action
{
public:
button(
drawable_window& w
) :
button_action(w),
btn_tooltip(w)
{
style.reset(new button_style_default());
enable_events();
}
~button() { disable_events(); parent.invalidate_rectangle(rect); }
void set_size (
unsigned long width,
unsigned long height
);
void set_name (
const std::string& name_
);
void set_name (
const std::wstring& name_
);
void set_name (
const dlib::ustring& name_
);
const std::string name (
) const;
const std::wstring wname (
) const;
const dlib::ustring uname (
) const;
void set_tooltip_text (
const std::string& text
);
void set_tooltip_text (
const std::wstring& text
);
void set_tooltip_text (
const dlib::ustring& text
);
void set_pos(
long x,
long y
);
const std::string tooltip_text (
) const;
const std::wstring tooltip_wtext (
) const;
const dlib::ustring tooltip_utext (
) const;
void set_main_font (
const shared_ptr_thread_safe<font>& f
);
void show (
);
void hide (
);
void enable (
);
void disable (
);
template <
typename style_type
>
void set_style (
const style_type& style_
)
{
auto_mutex M(m);
style.reset(new style_type(style_));
rect = move_rect(style->get_min_size(name_,*mfont), rect.left(), rect.top());
parent.invalidate_rectangle(rect);
}
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler_)()
)
{
auto_mutex M(m);
event_handler.set(object,event_handler_);
event_handler_self.clear();
}
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler_)(button&)
)
{
auto_mutex M(m);
event_handler_self.set(object,event_handler_);
event_handler.clear();
}
private:
// restricted functions
button(button&); // copy constructor
button& operator=(button&); // assignment operator
dlib::ustring name_;
tooltip btn_tooltip;
member_function_pointer<>::kernel_1a event_handler;
member_function_pointer<button&>::kernel_1a event_handler_self;
scoped_ptr<button_style> style;
protected:
void draw (
const canvas& c
) const { style->draw_button(c,rect,hidden,enabled,*mfont,lastx,lasty,name_,is_depressed()); }
void on_button_up (
bool mouse_over
);
void on_mouse_over (
){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); }
void on_mouse_not_over (
){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); }
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class toggle_button
......
......@@ -239,169 +239,6 @@ namespace dlib
label& operator=(label&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class button
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class button : public button_action
{
/*!
INITIAL VALUE
name() == ""
tooltip_text() == "" (i.e. there is no tooltip by default)
WHAT THIS OBJECT REPRESENTS
This object represents a simple button.
When this object is disabled it means it will not respond to user clicks.
!*/
public:
button(
drawable_window& w
);
/*!
ensures
- #*this is properly initialized
- #*this has been added to window w
- #parent_window() == w
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~button(
);
/*!
ensures
- all resources associated with *this have been released
!*/
void set_size (
unsigned long width_,
unsigned long height_
);
/*!
ensures
- if (width and height are big enough to contain the name of this button) then
- #width() == width_
- #height() == height_
- #top() == top()
- #left() == left()
- i.e. The location of the upper left corner of this button stays the
same but its width and height are modified
!*/
void set_name (const std::wstring& name);
void set_name (const dlib::ustring& name);
void set_name (
const std::string& name
);
/*!
ensures
- #name() == name
- this button has been resized such that it is big enough to contain
the new name.
throws
- std::bad_alloc
!*/
const std::wstring wname () const;
const dlib::string uname () const;
const std::string name (
) const;
/*!
ensures
- returns the name of this button
throws
- std::bad_alloc
!*/
void set_tooltip_text (const std::wstring& text);
void set_tooltip_text (const dlib::ustring& text);
void set_tooltip_text (
const std::string& text
);
/*!
ensures
- #tooltip_text() == text
- enables the tooltip for this button
!*/
const dlib::ustring tooltip_utext () const;
const std::wstring tooltip_wtext () const;
const std::string tooltip_text (
) const;
/*!
ensures
- returns the text that is displayed in the tooltip for this button
!*/
template <
typename style_type
>
void set_style (
const style_type& style
);
/*!
requires
- style_type == a type that inherits from button_style
ensures
- this button object will draw itself using the given
button style
!*/
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler)()
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- the event_handler function is called on object when the button is
clicked by the user.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler)(button& self)
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- &self == this
- the event_handler function is called on object when the button is
clicked by the user.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
private:
// restricted functions
button(button&); // copy constructor
button& operator=(button&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class toggle_button
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment