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 @@ ...@@ -11,6 +11,258 @@
namespace dlib 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 // dragable object methods
...@@ -348,139 +600,6 @@ namespace dlib ...@@ -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 // scroll_bar object methods
...@@ -494,8 +613,8 @@ namespace dlib ...@@ -494,8 +613,8 @@ namespace dlib
) : ) :
drawable(w), drawable(w),
width_(16), width_(16),
b1(w,arrow_button::UP), b1(w),
b2(w,arrow_button::DOWN), b2(w),
slider(w,*this,&scroll_bar::on_slider_drag), slider(w,*this,&scroll_bar::on_slider_drag),
ori(orientation), ori(orientation),
top_filler(w,*this,&scroll_bar::top_filler_down,&scroll_bar::top_filler_up), top_filler(w,*this,&scroll_bar::top_filler_down,&scroll_bar::top_filler_up),
...@@ -510,8 +629,13 @@ namespace dlib ...@@ -510,8 +629,13 @@ namespace dlib
{ {
if (ori == HORIZONTAL) if (ori == HORIZONTAL)
{ {
b1.set_direction(arrow_button::LEFT); b1.set_style(button_style_left_arrow());
b2.set_direction(arrow_button::RIGHT); 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. // don't show the slider when there is no place it can move.
...@@ -575,16 +699,15 @@ namespace dlib ...@@ -575,16 +699,15 @@ namespace dlib
{ {
rect.set_right(rect.left() + length - 1 ); rect.set_right(rect.left() + length - 1 );
rect.set_bottom(rect.top() + width_ - 1 ); rect.set_bottom(rect.top() + width_ - 1 );
b1.set_direction(arrow_button::LEFT); b1.set_style(button_style_left_arrow());
b2.set_direction(arrow_button::RIGHT); b2.set_style(button_style_right_arrow());
} }
else else
{ {
rect.set_right(rect.left() + width_ - 1); rect.set_right(rect.left() + width_ - 1);
rect.set_bottom(rect.top() + length - 1); rect.set_bottom(rect.top() + length - 1);
b1.set_direction(arrow_button::UP); b1.set_style(button_style_up_arrow());
b2.set_direction(arrow_button::DOWN); b2.set_style(button_style_down_arrow());
} }
ori = new_orientation; ori = new_orientation;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "../pixel.h" #include "../pixel.h"
#include "../image_transforms.h" #include "../image_transforms.h"
#include "../array.h" #include "../array.h"
#include "style.h"
#include "../smart_pointers.h" #include "../smart_pointers.h"
#include "../unicode.h" #include "../unicode.h"
#include <cctype> #include <cctype>
...@@ -258,594 +259,500 @@ namespace dlib ...@@ -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 INITIAL VALUE
dir == whatever is given to the constructor widgets.size() == 0
CONVENTION CONVENTION
- dir == direction() Widgets contains all the drawable objects and their relative positions
that are in *this.
!*/ !*/
public: struct relpos
enum arrow_direction
{ {
UP, unsigned long x;
DOWN, unsigned long y;
LEFT,
RIGHT
}; };
arrow_button( public:
drawable_window& w, widget_group(
arrow_direction dir_ drawable_window& w
) : ) : drawable(w) { rect = rectangle(0,0,-1,-1); enable_events();}
button_action(w),
dir(dir_)
{
enable_events();
}
virtual ~arrow_button( virtual ~widget_group(
){ disable_events(); parent.invalidate_rectangle(rect); } ){ disable_events(); }
arrow_direction direction ( void empty (
) const );
{
auto_mutex M(m);
return dir;
}
void set_direction ( void add (
arrow_direction new_direction drawable& widget,
) unsigned long x,
{ unsigned long y
auto_mutex M(m); );
dir = new_direction;
parent.invalidate_rectangle(rect);
}
void set_size ( bool is_member (
unsigned long width, const drawable& widget
unsigned long height ) const;
void remove (
const drawable& widget
); );
bool is_depressed ( unsigned long size (
) const ) const;
{
auto_mutex M(m);
return button_action::is_depressed();
}
template < void set_pos (
typename T long x,
> long y
void set_button_down_handler ( );
T& object,
void (T::*event_handler)() 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); disable_events();
button_down_handler.set(object,event_handler); parent.invalidate_rectangle(rect);
} }
template < template <
typename T typename image_type
> >
void set_button_up_handler ( void set_image (
T& object, const image_type& new_img
void (T::*event_handler)(bool mouse_over)
) )
{ {
auto_mutex M(m); 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 ( void draw (
const canvas& c const canvas& c
) const; ) const
{
void on_button_down ( rectangle area = rect.intersect(c);
) if (area.is_empty())
{ return;
if (button_down_handler.is_set())
button_down_handler();
}
void on_button_up ( draw_image(c, point(rect.left(),rect.top()), img);
bool mouse_over
)
{
if (button_up_handler.is_set())
button_up_handler(mouse_over);
} }
private: array2d<rgb_alpha_pixel>::kernel_1a img;
arrow_direction dir;
member_function_pointer<>::kernel_1a button_down_handler;
member_function_pointer<bool>::kernel_1a button_up_handler;
// restricted functions // restricted functions
arrow_button(arrow_button&); // copy constructor image_widget(image_widget&); // copy constructor
arrow_button& operator=(arrow_button&); // assignment operator 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 INITIAL VALUE
- ori == a value given by the constructor - stuff.get() == 0
- width_ == 16 - events_are_enabled() == false
- pos == 0
- max_pos == 0
- js == 10
CONVENTION CONVENTION
- ori == orientation() - if (events_are_enabled() == true) then
- b1 == the button that is near the 0 end of the scroll bar - stuff.get() != 0
- 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: 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 ( tooltip(
long pos drawable_window& w
); ) :
mouse_over_event(w,MOUSE_CLICK)
{}
long slider_pos ( ~tooltip(
) const; ){ disable_events();}
template < void set_size (
typename T long width,
> long height
void set_scroll_handler ( )
T& object, {
void (T::*eh)() auto_mutex M(m);
) { scroll_handler.set(object,eh); } rect = resize_rect(rect,width,height);
}
void set_pos (
long x,
long y
);
void enable ( void set_text (
const std::string& str
) )
{ {
if (!hidden) set_text(convert_mbstring_to_wstring(str));
show_slider();
if (max_pos != 0)
{
b1.enable();
b2.enable();
}
drawable::enable();
} }
void disable ( void set_text (
const std::wstring& str
) )
{ {
hide_slider(); set_text(convert_wstring_to_utf32(str));
b1.disable();
b2.disable();
drawable::disable();
} }
void hide ( void set_text (
const ustring& str
) )
{ {
hide_slider(); auto_mutex M(m);
top_filler.hide(); if (!stuff)
bottom_filler.hide(); {
b1.hide(); stuff.reset(new data(*this));
b2.hide(); enable_events();
drawable::hide(); }
stuff->win.set_text(str);
} }
void show ( const std::string text (
) ) const
{ {
b1.show(); return convert_wstring_to_mbstring(wtext());
b2.show();
drawable::show();
top_filler.show();
if (enabled)
show_slider();
} }
void set_z_order ( const std::wstring wtext (
long order ) const
)
{ {
slider.set_z_order(order); return convert_utf32_to_wstring(utext());
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);
} }
void set_jump_size ( const dlib::ustring utext (
long js ) const
); {
auto_mutex M(m);
long jump_size ( dlib::ustring temp;
) const; if (stuff)
{
temp = stuff->win.text;
private: }
return temp.c_str();
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 ( void hide (
int i
) )
{ {
switch (i) auto_mutex M(m);
mouse_over_event::hide();
if (stuff)
{ {
case 0: stuff->tt_timer.stop();
b1_down(); stuff->win.hide();
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 delayed_set_slider_pos ( void disable (
unsigned long dpos )
)
{ {
delayed_pos = dpos; auto_mutex M(m);
parent.trigger_user_event(this,4); mouse_over_event::disable();
if (stuff)
{
stuff->tt_timer.stop();
stuff->win.hide();
}
} }
void b1_down_t ( protected:
) { parent.trigger_user_event(this,0); }
void b2_down_t ( void on_mouse_over()
) { parent.trigger_user_event(this,1); } {
stuff->x = lastx;
stuff->y = lasty;
stuff->tt_timer.start();
}
void top_filler_down_t ( void on_mouse_not_over ()
) { parent.trigger_user_event(this,2); } {
stuff->tt_timer.stop();
stuff->win.hide();
}
void bottom_filler_down_t ( void on_mouse_down (
) { parent.trigger_user_event(this,3); } 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: public:
filler ( tooltip_window (const shared_ptr_thread_safe<font>& f) : base_window(false,true), pad(3), mfont(f)
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();
} }
~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 ( void set_text (
unsigned long width, const std::wstring& str
unsigned long height
) )
{ {
rectangle old(rect); set_text(convert_wstring_to_utf32(str));
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();
} }
~slider_class ( void set_text (
const dlib::ustring& str
) )
{ {
disable_events(); text = str.c_str();
}
void set_size ( unsigned long width, height;
unsigned long width, mfont->compute_size(text,width,height);
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);
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 paint(const canvas& c)
void on_drag (
)
{ {
mfp(); c.fill(255,255,150);
draw_rectangle(c, rect_all);
mfont->draw_string(c,rect_text,text);
} }
};
void draw ( void show_tooltip (
const canvas& c )
) const {
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)); stuff->x = lastx;
draw_button_up(c, rect); 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 ( stuff->win.set_pos(x,y);
); stuff->win.show();
/*! }
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
!*/
unsigned long get_slider_size ( // put all this stuff in data so we can arrange to only
) const; // construct it when someone is actually using the tooltip widget
/*! // rather than just instantiating it.
ensures struct data
- returns the length in pixels the slider should have based on the current {
state of this scroll bar 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; friend struct data;
slider_class slider; scoped_ptr<data> stuff;
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 // restricted functions
scroll_bar(scroll_bar&); // copy constructor tooltip(tooltip&); // copy constructor
scroll_bar& operator=(scroll_bar&); // assignment operator 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: public:
widget_group( button(
drawable_window& w 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( void set_size (
){ disable_events(); } unsigned long width,
unsigned long height
);
void empty ( void set_name (
const std::string& name_
); );
void add ( void set_name (
drawable& widget, const std::wstring& name_
unsigned long x,
unsigned long y
); );
bool is_member ( void set_name (
const drawable& widget const dlib::ustring& name_
);
const std::string name (
) const; ) const;
void remove ( const std::wstring wname (
const drawable& widget ) const;
const dlib::ustring uname (
) const;
void set_tooltip_text (
const std::string& text
); );
unsigned long size ( void set_tooltip_text (
) const; const std::wstring& text
);
void set_pos ( void set_tooltip_text (
const dlib::ustring& text
);
void set_pos(
long x, long x,
long y long y
); );
void set_z_order ( const std::string tooltip_text (
long order ) 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 show (
...@@ -860,353 +767,546 @@ namespace dlib ...@@ -860,353 +767,546 @@ namespace dlib
void disable ( void disable (
); );
void fit_to_contents ( template <
); typename style_type
>
protected: void set_style (
const style_type& style_
// this object doesn't draw anything but also isn't abstract )
void draw ( {
const canvas& c auto_mutex M(m);
) const {} style.reset(new style_type(style_));
rect = move_rect(style->get_min_size(name_,*mfont), rect.left(), rect.top());
private: parent.invalidate_rectangle(rect);
}
map<drawable*,relpos>::kernel_1a_c widgets;
// restricted functions
widget_group(widget_group&); // copy constructor
widget_group& operator=(widget_group&); // assignment operator
};
// ---------------------------------------------------------------------------------------- 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 template <
{ typename T
/*! >
INITIAL VALUE void set_click_handler (
- img.size() == 0 T& object,
void (T::*event_handler_)(button&)
)
{
auto_mutex M(m);
event_handler_self.set(object,event_handler_);
event_handler.clear();
}
CONVENTION bool is_depressed (
- img == the image this object displays ) 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( template <
drawable_window& w typename T
): dragable(w) { enable_events(); } >
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(); auto_mutex M(m);
parent.invalidate_rectangle(rect); button_down_handler_self.set(object,event_handler);
} }
template < template <
typename image_type typename T
> >
void set_image ( void set_button_up_handler (
const image_type& new_img T& object,
void (T::*event_handler)(bool mouse_over, button&)
) )
{ {
auto_mutex M(m); auto_mutex M(m);
assign_image(img,new_img); button_up_handler_self.set(object,event_handler);
rectangle old(rect);
rect.set_right(rect.left()+img.nc()-1);
rect.set_bottom(rect.top()+img.nr()-1);
parent.invalidate_rectangle(rect+old);
} }
private: 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 ( void draw (
const canvas& c const canvas& c
) const ) const { style->draw_button(c,rect,hidden,enabled,*mfont,lastx,lasty,name_,is_depressed()); }
{
rectangle area = rect.intersect(c);
if (area.is_empty())
return;
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 void on_mouse_over (
image_widget(image_widget&); // copy constructor ){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); }
image_widget& operator=(image_widget&); // assignment operator
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 INITIAL VALUE
- stuff.get() == 0 - ori == a value given by the constructor
- events_are_enabled() == false - width_ == 16
- pos == 0
- max_pos == 0
- js == 10
CONVENTION CONVENTION
- if (events_are_enabled() == true) then - ori == orientation()
- stuff.get() != 0 - 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: public:
enum bar_orientation
{
HORIZONTAL,
VERTICAL
};
tooltip( scroll_bar(
drawable_window& w drawable_window& w,
) : bar_orientation orientation_
mouse_over_event(w,MOUSE_CLICK) );
{}
~tooltip( virtual ~scroll_bar(
){ disable_events();} );
void set_size ( bar_orientation orientation (
long width, ) const;
long height
)
{
auto_mutex M(m);
rect = resize_rect(rect,width,height);
}
void set_orientation (
bar_orientation new_orientation
);
void set_text ( void set_length (
const std::string& str 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 ( void disable (
const std::wstring& str
) )
{ {
set_text(convert_wstring_to_utf32(str)); hide_slider();
b1.disable();
b2.disable();
drawable::disable();
} }
void set_text ( void hide (
const ustring& str
) )
{ {
auto_mutex M(m); hide_slider();
if (!stuff) top_filler.hide();
{ bottom_filler.hide();
stuff.reset(new data(*this)); b1.hide();
enable_events(); b2.hide();
} drawable::hide();
stuff->win.set_text(str);
} }
const std::string text ( void show (
) const )
{ {
return convert_wstring_to_mbstring(wtext()); b1.show();
b2.show();
drawable::show();
top_filler.show();
if (enabled)
show_slider();
} }
const std::wstring wtext ( void set_z_order (
) const 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 ( void set_jump_size (
) const long js
{ );
auto_mutex M(m);
dlib::ustring temp;
if (stuff)
{
temp = stuff->win.text;
}
return temp.c_str();
}
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); switch (i)
mouse_over_event::hide();
if (stuff)
{ {
stuff->tt_timer.stop(); case 0:
stuff->win.hide(); 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); delayed_pos = dpos;
mouse_over_event::disable(); parent.trigger_user_event(this,4);
if (stuff)
{
stuff->tt_timer.stop();
stuff->win.hide();
}
} }
protected: void b1_down_t (
) { parent.trigger_user_event(this,0); }
void on_mouse_over()
{
stuff->x = lastx;
stuff->y = lasty;
stuff->tt_timer.start();
}
void on_mouse_not_over () void b2_down_t (
{ ) { parent.trigger_user_event(this,1); }
stuff->tt_timer.stop();
stuff->win.hide();
}
void on_mouse_down ( void top_filler_down_t (
unsigned long btn, ) { parent.trigger_user_event(this,2); }
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 ( void bottom_filler_down_t (
const canvas& ) { parent.trigger_user_event(this,3); }
) const{}
private:
class tooltip_window : public base_window class filler : public button_action
{ {
friend class scroll_bar;
public: 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; ~filler (
rectangle rect_all;
rectangle rect_text;
const unsigned long pad;
const shared_ptr_thread_safe<font> mfont;
void set_text (
const std::string& str
) )
{ {
set_text(convert_mbstring_to_wstring(str)); disable_events();
} }
void set_text ( void set_size (
const std::wstring& str 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 ( private:
const dlib::ustring& str
) 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; void on_button_down (
mfont->compute_size(text,width,height); ) { bdown(); }
set_size(width+pad*2, height+pad*2); void on_button_up (
rect_all.set_left(0); bool mouse_over
rect_all.set_top(0); ) { bup(mouse_over); }
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); 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); disable_events();
draw_rectangle(c, rect_all);
mfont->draw_string(c,rect_text,text);
} }
};
void show_tooltip ( void set_size (
) unsigned long width,
{ unsigned long height
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)
{ {
stuff->x = lastx; rectangle old(rect);
stuff->y = lasty; const unsigned long x = rect.left();
return; 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; private:
// stop the timer void on_drag (
stuff->tt_timer.stop(); )
parent.get_pos(x,y); {
x += lastx+15; mfp();
y += lasty+15; }
// make sure the tooltip isn't going to be off the screen void draw (
parent.get_display_size(display_width, display_height); const canvas& c
rectangle wrect(move_rect(stuff->win.rect_all,x,y)); ) const
rectangle srect(display_width, display_height);
if (srect.contains(wrect) == false)
{ {
rectangle temp(srect.intersect(wrect)); fill_rect(c, rect, rgb_pixel(212,208,200));
x -= wrect.width()-temp.width(); draw_button_up(c, rect);
y -= wrect.height()-temp.height();
} }
stuff->win.set_pos(x,y); member_function_pointer<>::kernel_1a mfp;
stuff->win.show(); };
}
// 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; void adjust_fillers (
tooltip_window win; );
timer<tooltip>::kernel_2a tt_timer; /*!
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
!*/
}; unsigned long get_slider_size (
friend struct data; ) const;
scoped_ptr<data> stuff; /*!
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 // restricted functions
tooltip(tooltip&); // copy constructor scroll_bar(scroll_bar&); // copy constructor
tooltip& operator=(tooltip&); // assignment operator scroll_bar& operator=(scroll_bar&); // assignment operator
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -329,80 +329,103 @@ namespace dlib ...@@ -329,80 +329,103 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// class arrow_button // class button
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
class arrow_button : public button_action class button : public button_action
{ {
/*! /*!
INITIAL VALUE INITIAL VALUE
direction() == a value given to the constructor. name() == ""
tooltip_text() == "" (i.e. there is no tooltip by default)
WHAT THIS OBJECT REPRESENTS 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. When this object is disabled it means it will not respond to user clicks.
!*/ !*/
public: public:
enum arrow_direction
{
UP,
DOWN,
LEFT,
RIGHT
};
arrow_button( button(
drawable_window& w, drawable_window& w
arrow_direction dir
); );
/*! /*!
ensures ensures
- #*this is properly initialized - #*this is properly initialized
- #*this has been added to window w - #*this has been added to window w
- #direction() == dir
- #parent_window() == w - #parent_window() == w
throws throws
- std::bad_alloc - std::bad_alloc
- dlib::thread_error - dlib::thread_error
!*/ !*/
virtual ~arrow_button( virtual ~button(
); );
/*! /*!
ensures ensures
- all resources associated with *this have been released - 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; ) const;
/*! /*!
ensures ensures
- returns the direction that this arrow_button's arrow points - returns the name of this button
throws
- std::bad_alloc
!*/ !*/
void set_direction ( void set_tooltip_text (const std::wstring& text);
arrow_direction new_direction void set_tooltip_text (const dlib::ustring& text);
void set_tooltip_text (
const std::string& text
); );
/*! /*!
ensures ensures
- #direction() == new_direction - #tooltip_text() == text
- enables the tooltip for this button
!*/ !*/
void set_size ( const dlib::ustring tooltip_utext () const;
unsigned long width_, const std::wstring tooltip_wtext () const;
unsigned long height_ const std::string tooltip_text (
); ) const;
/*! /*!
ensures ensures
- #width() == width_ - returns the text that is displayed in the tooltip for this button
- #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
!*/ !*/
bool is_depressed ( bool is_depressed (
...@@ -410,13 +433,68 @@ namespace dlib ...@@ -410,13 +433,68 @@ namespace dlib
/*! /*!
ensures ensures
- if (this button is currently in a depressed state) then - 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. holding the left mouse button down over it.
- returns true - returns true
- else - else
- returns false - 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 < template <
typename T typename T
> >
...@@ -426,10 +504,10 @@ namespace dlib ...@@ -426,10 +504,10 @@ namespace dlib
); );
/*! /*!
requires 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 ensures
- The event_handler function is called whenever this object transitions - the event_handler function is called on object when the user causes
from the state where is_depressed() == false to is_depressed() == true the button to go into its depressed state.
- any previous calls to this function are overridden by this new call. - any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this (i.e. you can only have one event handler associated with this
event at a time) event at a time)
...@@ -446,15 +524,60 @@ namespace dlib ...@@ -446,15 +524,60 @@ namespace dlib
); );
/*! /*!
requires 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 ensures
- The event_handler function is called whenever this object transitions - &self == this
from the state where is_depressed() == true to is_depressed() == false. - the event_handler function is called on object when the user causes
furthermore: the button to go into its depressed state.
- if (the mouse was over this button when this event occurred) then - any previous calls to this function are overridden by this new call.
- mouse_over == true (i.e. you can only have one event handler associated with this
- else event at a time)
- mouse_over == false 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. - any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this (i.e. you can only have one event handler associated with this
event at a time) event at a time)
...@@ -465,8 +588,8 @@ namespace dlib ...@@ -465,8 +588,8 @@ namespace dlib
private: private:
// restricted functions // restricted functions
arrow_button(arrow_button&); // copy constructor button(button&); // copy constructor
arrow_button& operator=(arrow_button&); // assignment operator button& operator=(button&); // assignment operator
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -275,6 +275,212 @@ namespace dlib ...@@ -275,6 +275,212 @@ namespace dlib
return rectangle(img_normal.nc()+2*padding, img_normal.nr()+2*padding); 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 // toggle button style stuff
......
...@@ -215,6 +215,98 @@ namespace dlib ...@@ -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 // toggle button styles
......
...@@ -122,6 +122,42 @@ namespace dlib ...@@ -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 // toggle button styles
......
...@@ -9,242 +9,6 @@ ...@@ -9,242 +9,6 @@
namespace dlib 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 // toggle_button object methods
......
...@@ -108,165 +108,6 @@ namespace dlib ...@@ -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 // class toggle_button
......
...@@ -239,169 +239,6 @@ namespace dlib ...@@ -239,169 +239,6 @@ namespace dlib
label& operator=(label&); // assignment operator 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 // 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