Commit 32ca94c9 authored by Davis King's avatar Davis King

- removed scroll_bar::set_orientation()

- added the dragable::on_drag_stop() event
- added the dragable::is_being_dragged() function
- Made the scroll_bar have a user settable style and made a default
  style
- Added some missing mutex locks to the scroll_bar widget

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402587
parent 2ad5e749
......@@ -320,6 +320,24 @@ namespace dlib
else
{
drag = false;
on_drag_stop();
}
}
// ----------------------------------------------------------------------------------------
void dragable::
on_mouse_up (
unsigned long btn,
unsigned long state,
long x,
long y
)
{
if (drag && (state & base_window::LEFT) == 0)
{
drag = false;
on_drag_stop();
}
}
......@@ -612,7 +630,6 @@ namespace dlib
bar_orientation orientation
) :
drawable(w),
width_(16),
b1(w),
b2(w),
slider(w,*this,&scroll_bar::on_slider_drag),
......@@ -627,16 +644,7 @@ namespace dlib
top_filler_timer(*this,&scroll_bar::top_filler_down_t),
bottom_filler_timer(*this,&scroll_bar::bottom_filler_down_t)
{
if (ori == HORIZONTAL)
{
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());
}
set_style(scroll_bar_style_default());
// don't show the slider when there is no place it can move.
slider.hide();
......@@ -678,46 +686,6 @@ namespace dlib
return ori;
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
set_orientation (
bar_orientation new_orientation
)
{
auto_mutex M(m);
unsigned long length;
if (ori == HORIZONTAL)
length = rect.width();
else
length = rect.height();
rectangle old_rect = rect;
if (new_orientation == HORIZONTAL)
{
rect.set_right(rect.left() + length - 1 );
rect.set_bottom(rect.top() + width_ - 1 );
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_style(button_style_up_arrow());
b2.set_style(button_style_down_arrow());
}
ori = new_orientation;
parent.invalidate_rectangle(old_rect);
parent.invalidate_rectangle(rect);
// call this to put everything is in the right spot.
set_pos (rect.left(),rect.top());
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
......@@ -725,67 +693,39 @@ namespace dlib
unsigned long length
)
{
auto_mutex M(m);
// make the min length be at least 1
if (length == 0)
{
length = 1;
}
auto_mutex M(m);
parent.invalidate_rectangle(rect);
if (ori == HORIZONTAL)
{
rect.set_right(rect.left() + length - 1);
rect.set_bottom(rect.top() + width_ - 1);
rect.set_bottom(rect.top() + style->get_width() - 1);
// if the length is too small then we have to smash up the arrow buttons
// and hide the slider.
if (length <= width_*2)
{
b1.set_size(length/2,width_);
b2.set_size(length/2,width_);
}
else
{
b1.set_size(width_,width_);
b2.set_size(width_,width_);
const long btn_size = style->get_button_length(rect.width(), max_pos);
// now adjust the slider
if (max_pos != 0)
{
slider.set_size(get_slider_size(),width_);
}
}
b1.set_size(btn_size,style->get_width());
b2.set_size(btn_size,style->get_width());
slider.set_size(get_slider_size(),style->get_width());
}
else
{
rect.set_right(rect.left() + width_ - 1);
rect.set_right(rect.left() + style->get_width() - 1);
rect.set_bottom(rect.top() + length - 1);
// if the length is too small then we have to smush up the arrow buttons
// and hide the slider.
if (length <= width_*2)
{
b1.set_size(width_,length/2);
b2.set_size(width_,length/2);
}
else
{
b1.set_size(width_,width_);
b2.set_size(width_,width_);
// now adjust the slider
if (max_pos != 0)
{
slider.set_size(width_,get_slider_size());
}
}
const long btn_size = style->get_button_length(rect.height(), max_pos);
b1.set_size(style->get_width(),btn_size);
b2.set_size(style->get_width(),btn_size);
slider.set_size(style->get_width(),get_slider_size());
}
// call this to put everything is in the right spot.
......@@ -833,8 +773,8 @@ namespace dlib
// move the dragable area for the slider to the new location
rectangle area = rect;
area.set_left(area.left() + width_);
area.set_right(area.right() - width_);
area.set_left(area.left() + style->get_width());
area.set_right(area.right() - style->get_width());
slider.set_dragable_area(area);
}
......@@ -859,8 +799,8 @@ namespace dlib
// move the dragable area for the slider to the new location
rectangle area = rect;
area.set_top(area.top() + width_);
area.set_bottom(area.bottom() - width_);
area.set_top(area.top() + style->get_width());
area.set_bottom(area.bottom() - style->get_width());
slider.set_dragable_area(area);
}
}
......@@ -874,28 +814,10 @@ namespace dlib
get_slider_size (
) const
{
double range;
if (ori == HORIZONTAL)
{
range = rect.width() - b2.get_rect().width() - b1.get_rect().width();
}
return style->get_slider_length(rect.width(),max_pos);
else
{
range = rect.height() - b2.get_rect().height() - b1.get_rect().height();
}
double scale_factor = 30.0/(max_pos + 30.0);
if (scale_factor < 0.1)
scale_factor = 0.1;
double fraction = range/(max_pos + range)*scale_factor;
double result = fraction * range;
unsigned long res = static_cast<unsigned long>(result);
if (res < 8)
res = 8;
return res;
return style->get_slider_length(rect.height(),max_pos);
}
// ----------------------------------------------------------------------------------------
......@@ -1005,6 +927,7 @@ namespace dlib
}
// ----------------------------------------------------------------------------------------
long scroll_bar::
max_slider_pos (
) const
......@@ -1288,6 +1211,89 @@ namespace dlib
return js;
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
on_user_event (
int i
)
{
switch (i)
{
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 scroll_bar::
delayed_set_slider_pos (
unsigned long dpos
)
{
delayed_pos = dpos;
parent.trigger_user_event(this,4);
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
b1_down_t (
)
{
parent.trigger_user_event(this,0);
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
b2_down_t (
)
{
parent.trigger_user_event(this,1);
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
top_filler_down_t (
)
{
parent.trigger_user_event(this,2);
}
// ----------------------------------------------------------------------------------------
void scroll_bar::
bottom_filler_down_t (
)
{
parent.trigger_user_event(this,3);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// widget_group object methods
......
......@@ -70,9 +70,15 @@ namespace dlib
protected:
bool is_being_dragged (
) const { return drag; }
virtual void on_drag (
){}
virtual void on_drag_stop (
){}
void on_mouse_move (
unsigned long state,
long x,
......@@ -87,6 +93,13 @@ namespace dlib
bool
);
void on_mouse_up (
unsigned long btn,
unsigned long state,
long x,
long y
);
private:
rectangle area;
......@@ -910,7 +923,7 @@ namespace dlib
/*!
INITIAL VALUE
- ori == a value given by the constructor
- width_ == 16
- style == a scroll_bar_style_default object
- pos == 0
- max_pos == 0
- js == 10
......@@ -943,10 +956,6 @@ namespace dlib
bar_orientation orientation (
) const;
void set_orientation (
bar_orientation new_orientation
);
void set_length (
unsigned long length
);
......@@ -971,7 +980,7 @@ namespace dlib
void set_scroll_handler (
T& object,
void (T::*eh)()
) { scroll_handler.set(object,eh); }
) { auto_mutex M(m); scroll_handler.set(object,eh); }
void set_pos (
long x,
......@@ -981,6 +990,7 @@ namespace dlib
void enable (
)
{
auto_mutex M(m);
if (!hidden)
show_slider();
if (max_pos != 0)
......@@ -994,6 +1004,7 @@ namespace dlib
void disable (
)
{
auto_mutex M(m);
hide_slider();
b1.disable();
b2.disable();
......@@ -1003,6 +1014,7 @@ namespace dlib
void hide (
)
{
auto_mutex M(m);
hide_slider();
top_filler.hide();
bottom_filler.hide();
......@@ -1014,6 +1026,7 @@ namespace dlib
void show (
)
{
auto_mutex M(m);
b1.show();
b2.show();
drawable::show();
......@@ -1026,6 +1039,7 @@ namespace dlib
long order
)
{
auto_mutex M(m);
slider.set_z_order(order);
top_filler.set_z_order(order);
bottom_filler.set_z_order(order);
......@@ -1041,6 +1055,30 @@ namespace dlib
long jump_size (
) const;
template <
typename style_type
>
void set_style (
const style_type& style_
)
{
auto_mutex M(m);
style.reset(new style_type(style_));
if (ori == HORIZONTAL)
{
b1.set_style(style_.get_left_button_style());
b2.set_style(style_.get_right_button_style());
set_length(rect.width());
}
else
{
b1.set_style(style_.get_up_button_style());
b2.set_style(style_.get_down_button_style());
set_length(rect.height());
}
}
private:
......@@ -1102,58 +1140,25 @@ namespace dlib
void on_user_event (
int i
)
{
switch (i)
{
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 delayed_set_slider_pos (
unsigned long dpos
)
{
delayed_pos = dpos;
parent.trigger_user_event(this,4);
}
);
void b1_down_t (
) { parent.trigger_user_event(this,0); }
);
void b2_down_t (
) { parent.trigger_user_event(this,1); }
);
void top_filler_down_t (
) { parent.trigger_user_event(this,2); }
);
void bottom_filler_down_t (
) { parent.trigger_user_event(this,3); }
);
friend class filler;
class filler : public button_action
{
friend class scroll_bar;
......@@ -1164,7 +1169,8 @@ namespace dlib
void (scroll_bar::*down)(),
void (scroll_bar::*up)(bool)
):
button_action(w)
button_action(w),
my_scroll_bar(object)
{
bup.set(object,up);
bdown.set(object,down);
......@@ -1198,10 +1204,7 @@ namespace dlib
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));
my_scroll_bar.style->draw_scroll_bar_background(c,rect,hidden,enabled,lastx,lasty,is_depressed());
}
void on_button_down (
......@@ -1211,10 +1214,12 @@ namespace dlib
bool mouse_over
) { bup(mouse_over); }
scroll_bar& my_scroll_bar;
member_function_pointer<>::kernel_1a bdown;
member_function_pointer<bool>::kernel_1a bup;
};
friend class slider_class;
class slider_class : public dragable
{
friend class scroll_bar;
......@@ -1224,7 +1229,9 @@ namespace dlib
scroll_bar& object,
void (scroll_bar::*handler)()
) :
dragable(w)
dragable(w, MOUSE_MOVE),
mouse_in_widget(false),
my_scroll_bar(object)
{
mfp.set(object,handler);
enable_events();
......@@ -1251,6 +1258,45 @@ namespace dlib
}
private:
virtual void on_mouse_move (
unsigned long state,
long x,
long y
)
{
dragable::on_mouse_move(state,x,y);
if (!hidden && my_scroll_bar.style->redraw_on_mouse_over_slider())
{
if (rect.contains(x,y) && !mouse_in_widget)
{
mouse_in_widget = true;
parent.invalidate_rectangle(rect);
}
else if (rect.contains(x,y) == false && mouse_in_widget)
{
mouse_in_widget = false;
parent.invalidate_rectangle(rect);
}
}
}
void on_mouse_leave (
)
{
if (mouse_in_widget && my_scroll_bar.style->redraw_on_mouse_over_slider())
{
mouse_in_widget = false;
parent.invalidate_rectangle(rect);
}
}
void on_drag_stop (
)
{
if (my_scroll_bar.style->redraw_on_mouse_over_slider())
parent.invalidate_rectangle(rect);
}
void on_drag (
)
{
......@@ -1261,10 +1307,11 @@ namespace dlib
const canvas& c
) const
{
fill_rect(c, rect, rgb_pixel(212,208,200));
draw_button_up(c, rect);
my_scroll_bar.style->draw_scroll_bar_slider(c,rect,hidden,enabled,lastx,lasty, is_being_dragged());
}
bool mouse_in_widget;
scroll_bar& my_scroll_bar;
member_function_pointer<>::kernel_1a mfp;
};
......@@ -1287,7 +1334,6 @@ namespace dlib
!*/
const unsigned long width_;
button b1, b2;
slider_class slider;
bar_orientation ori;
......@@ -1303,6 +1349,7 @@ namespace dlib
timer<scroll_bar>::kernel_2a top_filler_timer;
timer<scroll_bar>::kernel_2a bottom_filler_timer;
long delayed_pos;
scoped_ptr<scroll_bar_style> style;
// restricted functions
scroll_bar(scroll_bar&); // copy constructor
......
......@@ -96,6 +96,18 @@ namespace dlib
protected:
bool is_being_dragged (
) const;
/*!
requires
- mutex drawable::m is locked
ensures
- if (this widget is currently being dragged by the user) then
- returns true
- else
- returns false
!*/
// does nothing by default
virtual void on_drag (
){}
......@@ -108,6 +120,20 @@ namespace dlib
- is called when the user drags this object
- get_rect() == the rectangle that defines the new position
of this object.
- is_being_dragged() == true
ensures
- does not change the state of mutex drawable::m.
!*/
// does nothing by default
virtual void on_drag_stop (
){}
/*!
requires
- enable_events() has been called
- mutex drawable::m is locked
- is called when the user stops dragging this object
- is_being_dragged() == false
ensures
- does not change the state of mutex drawable::m.
!*/
......@@ -651,14 +677,6 @@ namespace dlib
- returns the orientation of this scroll_bar
!*/
void set_orientation (
bar_orientation new_orientation
);
/*!
ensures
- #orientation() == new_orientation
!*/
void set_length (
unsigned long length,
);
......
......@@ -787,6 +787,99 @@ namespace dlib
return rectangle(width + 17 -1, height -1);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// scroll bar style stuff
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
long scroll_bar_style_default::
get_slider_length (
long total_length,
long max_pos
) const
{
// if the length is too small then we have to smash up the arrow buttons
// and hide the slider.
if (total_length <= get_width()*2)
{
return 0;
}
else
{
double range = total_length - get_button_length(total_length, max_pos)*2;
double scale_factor = 30.0/(max_pos + 30.0);
if (scale_factor < 0.1)
scale_factor = 0.1;
double fraction = range/(max_pos + range)*scale_factor;
double result = fraction * range;
long res = static_cast<long>(result);
if (res < 8)
res = 8;
return res;
}
}
// ----------------------------------------------------------------------------------------
long scroll_bar_style_default::
get_button_length (
long total_length,
long max_pos
) const
{
// if the length is too small then we have to smash up the arrow buttons
// and hide the slider.
if (total_length <= get_width()*2)
{
return total_length/2;
}
else
{
return get_width();
}
}
// ----------------------------------------------------------------------------------------
void scroll_bar_style_default::
draw_scroll_bar_background (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_depressed
) 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 scroll_bar_style_default::
draw_scroll_bar_slider (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_being_dragged
) const
{
fill_rect(c, rect, rgb_pixel(212,208,200));
draw_button_up(c, rect);
}
// ----------------------------------------------------------------------------------------
}
......
......@@ -432,6 +432,108 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// scroll_bar styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class scroll_bar_style
{
public:
virtual ~scroll_bar_style() {}
virtual bool redraw_on_mouse_over_slider (
) const { return false; }
virtual long get_width (
) const = 0;
virtual long get_slider_length (
long total_length,
long max_pos
) const = 0;
virtual long get_button_length (
long total_length,
long max_pos
) const = 0;
virtual void draw_scroll_bar_background (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_depressed
) const = 0;
virtual void draw_scroll_bar_slider (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_being_dragged
) const = 0;
};
// ----------------------------------------------------------------------------------------
class scroll_bar_style_default : public scroll_bar_style
{
public:
button_style_up_arrow get_up_button_style (
) const { return button_style_up_arrow(); }
button_style_down_arrow get_down_button_style (
) const { return button_style_down_arrow(); }
button_style_left_arrow get_left_button_style (
) const { return button_style_left_arrow(); }
button_style_right_arrow get_right_button_style (
) const { return button_style_right_arrow(); }
virtual long get_width (
) const { return 16; }
virtual long get_slider_length (
long total_length,
long max_pos
) const;
virtual long get_button_length (
long total_length,
long max_pos
) const;
virtual void draw_scroll_bar_background (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_depressed
) const;
virtual void draw_scroll_bar_slider (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_being_dragged
) const;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
......
......@@ -257,6 +257,167 @@ namespace dlib
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// scroll_bar styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class scroll_bar_style
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an abstract class that defines the interface a
scroll_bar style object must implement.
Note that derived classes must be copyable via
their copy constructors.
There are three parts of a scroll bar, the slider, the background,
and the two buttons on its ends. The "slider" is the thing that you
drag around on the scroll bar and the "background" is the part
in between the slider and the buttons on the ends.
!*/
public:
virtual ~scroll_bar_style() {}
virtual bool redraw_on_mouse_over_slider (
) const { return false; }
/*!
ensures
- if (this style draws a scroll_bar's slider differently when a mouse is over it
or it is being dragged) then
- returns true
- else
- returns false
!*/
virtual long get_width (
) const = 0;
/*!
requires
- the mutex drawable::m is locked
ensures
- returns the width in pixels of the scroll bar
!*/
virtual long get_slider_length (
long total_length,
long max_pos
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- total_length == the total length in pixels of the scroll bar
- max_pos == the value of scroll_bar::max_slider_pos() for this
scroll bar
ensures
- returns the length in pixels of the scroll bar's slider
!*/
virtual long get_button_length (
long total_length,
long max_pos
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- total_length == the total length in pixels of the scroll bar
- max_pos == the value of scroll_bar::max_slider_pos() for this
scroll bar
ensures
- returns the length in pixels of each of the scroll bar's
buttons
!*/
virtual void draw_scroll_bar_background (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_depressed
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- c == the canvas to draw on
- rect, hidden, enabled, lastx, and lasty are the variables
defined in the protected section of the drawable class.
- is_depressed == true if the background area of the scroll_bar is to
be drawn in a depressed state (because the user is clicking on it)
ensures
- draws the background part of the scroll_bar on the canvas c at the
location given by rect.
!*/
virtual void draw_scroll_bar_slider (
const canvas& c,
const rectangle& rect,
const bool hidden,
const bool enabled,
const long lastx,
const long lasty,
const bool is_being_dragged
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- c == the canvas to draw on
- rect, hidden, enabled, lastx, and lasty are the variables
defined in the protected section of the drawable class
- is_being_dragged == true if the user is dragging the slider
ensures
- draws the slider part of the scroll_bar on the canvas c at the
location given by rect.
!*/
button_style_type get_up_button_style (
) const;
/*!
ensures
- returns the type of button_style to use for a button on the
top side of a vertical scroll bar.
!*/
button_style_type get_down_button_style (
) const;
/*!
ensures
- returns the type of button_style to use for a button on the
bottom side of a vertical scroll bar.
!*/
button_style_type get_left_button_style (
) const;
/*!
ensures
- returns the type of button_style to use for a button on the
left side of a horizontal scroll bar.
!*/
button_style_type get_right_button_style (
) const;
/*!
ensures
- returns the type of button_style to use for a button on the
right side of a horizontal scroll bar.
!*/
};
// ----------------------------------------------------------------------------------------
class scroll_bar_style_default : public scroll_bar_style
{
/*!
This is the default style for scroll_bar objects. It will cause
a scroll_bar to appear as the simple MS Windows 2000 scroll_bar style.
!*/
};
// ----------------------------------------------------------------------------------------
}
......
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