Commit 9db0ca77 authored by Davis King's avatar Davis King

Cleaned up the list_box's objects code by making it use the scrollable_region widget.

Also gave the list_box a user settable style.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402598
parent 1fc2b4e1
......@@ -577,6 +577,139 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// list_box styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class list_box_style
{
public:
virtual ~list_box_style() {}
virtual void draw_list_box_background (
const canvas& c,
const rectangle& display_rect,
const bool enabled
) const = 0;
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const std::string& text,
const bool is_selected
) const = 0;
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const std::wstring& text,
const bool is_selected
) const = 0;
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const bool is_selected
) const = 0;
};
// ----------------------------------------------------------------------------------------
class list_box_style_default : public list_box_style
{
public:
scrollable_region_style_default get_scrollable_region_style (
) const { return scrollable_region_style_default(); }
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const std::string& text,
const bool is_selected
) const { draw_list_box_item_template(c,rect,display_rect, enabled, mfont, text, is_selected); }
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const std::wstring& text,
const bool is_selected
) const { draw_list_box_item_template(c,rect,display_rect, enabled, mfont, text, is_selected); }
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const bool is_selected
) const { draw_list_box_item_template(c,rect,display_rect, enabled, mfont, text, is_selected); }
template <typename string_type>
void draw_list_box_item_template (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const string_type& text,
const bool is_selected
) const
{
if (is_selected)
{
if (enabled)
fill_rect_with_vertical_gradient(c,rect,rgb_pixel(110,160,255), rgb_pixel(100,130,250),display_rect);
else
fill_rect_with_vertical_gradient(c,rect,rgb_pixel(140,190,255), rgb_pixel(130,160,250),display_rect);
}
if (enabled)
mfont.draw_string(c,rect,text,rgb_pixel(0,0,0),0,std::string::npos,display_rect);
else
mfont.draw_string(c,rect,text,rgb_pixel(128,128,128),0,std::string::npos,display_rect);
}
virtual void draw_list_box_background (
const canvas& c,
const rectangle& display_rect,
const bool enabled
) const
{
if (enabled)
{
// first fill our area with white
fill_rect(c, display_rect,rgb_pixel(255,255,255));
}
else
{
// first fill our area with gray
fill_rect(c, display_rect,rgb_pixel(212,208,200));
}
}
};
// ----------------------------------------------------------------------------------------
}
......
......@@ -499,6 +499,110 @@ namespace dlib
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// list_box styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class list_box_style
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an abstract class that defines the interface a
list_box style object must implement.
Note that derived classes must be copyable via
their copy constructors.
!*/
public:
virtual ~list_box_style() {}
virtual void draw_list_box_background (
const canvas& c,
const rectangle& display_rect,
const bool enabled
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- c == the canvas to draw on
- display_rect == the display_rect for the list_box. This is the area
in which list box items are drawn (see display_rect in the scrollable_region
widget for more info)
- enabled == true if the list box is enabled
ensures
- draws the background of a list box on the canvas c at the location given
by display_rect.
!*/
scrollable_region_style_type get_scrollable_region_style (
) const;
/*!
ensures
- returns the style of scrollable_region to use for the
list_box.
!*/
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const std::string& text,
const bool is_selected
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- c == the canvas to draw on
- rect == the rectangle that defines where on the screen this list box item is.
- display_rect == the display_rect for the list_box. This is the area
in which list box items are drawn (see display_rect in the scrollable_region
widget for more info)
- mfont == the font to use to draw the list box item
- text == the text of the list box item to be drawn
- enabled == true if the list box is enabled
- is_selected == true if the item is to be drawn in a selected state
ensures
- draws the list box item on the canvas c at the location given by rect.
!*/
// wide character overloads
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const std::wstring& text,
const bool is_selected
) const = 0;
virtual void draw_list_box_item (
const canvas& c,
const rectangle& rect,
const rectangle& display_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const bool is_selected
) const = 0;
};
// ----------------------------------------------------------------------------------------
class list_box_style_default : public list_box_style
{
public:
/*!
This is the default style for list_box objects.
!*/
};
// ----------------------------------------------------------------------------------------
}
......
......@@ -2109,17 +2109,13 @@ namespace dlib
list_box(
drawable_window& w
) :
drawable(w,MOUSE_WHEEL|MOUSE_CLICK),
scrollable_region(w,MOUSE_WHEEL|MOUSE_CLICK),
ms_enabled(false),
pos(0),
text_start(0),
last_selected(0),
sbv(w,scroll_bar::VERTICAL),
sbh(w,scroll_bar::HORIZONTAL)
{
adjust_sliders();
sbv.set_scroll_handler(*this,&list_box::sbv_handler);
sbh.set_scroll_handler(*this,&list_box::sbh_handler);
last_selected(0)
{
set_vertical_scroll_increment(mfont->height());
style.reset(new list_box_style_default());
enable_events();
}
......@@ -2149,30 +2145,10 @@ namespace dlib
{
mfont->compute_size(items[i].name,items[i].width, items[i].height);
}
adjust_sliders();
set_vertical_scroll_increment(mfont->height());
parent.invalidate_rectangle(rect);
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
set_size (
unsigned long width_,
unsigned long height_
)
{
auto_mutex M(m);
rectangle old(rect);
const long x = rect.left();
const long y = rect.top();
rect.set_right(x+width_-1);
rect.set_bottom(y+height_-1);
adjust_sliders();
parent.invalidate_rectangle(rect+old);
}
// ----------------------------------------------------------------------------------------
template <typename S>
......@@ -2364,242 +2340,32 @@ namespace dlib
const canvas& c
) const
{
rectangle area = rect.intersect(c);
scrollable_region::draw(c);
rectangle area = display_rect().intersect(c);
if (area.is_empty())
return;
if (enabled)
{
// first fill our area with white
fill_rect(c, area,rgb_pixel(255,255,255));
}
else
{
// first fill our area with gray
fill_rect(c, area,rgb_pixel(212,208,200));
}
draw_sunken_rectangle(c, rect);
long y = text_area.top();
long x = text_area.left();
for (unsigned long i = pos; i < items.size(); ++i)
{
rectangle r(x-(long)text_start,y,text_area.right(),y+items[i].height);
rectangle draw_area(x,y,text_area.right(),y+items[i].height);
draw_area = draw_area.intersect(text_area);
if (draw_area.is_empty())
break;
if (items[i].is_selected)
{
if (enabled)
fill_rect_with_vertical_gradient(c,draw_area,rgb_pixel(110,160,255), rgb_pixel(100,130,250));
else
fill_rect_with_vertical_gradient(c,draw_area,rgb_pixel(140,190,255), rgb_pixel(130,160,250));
}
if (enabled)
mfont->draw_string(c,r,items[i].name,rgb_pixel(0,0,0),0,std::string::npos,draw_area);
else
mfont->draw_string(c,r,items[i].name,rgb_pixel(128,128,128),0,std::string::npos,draw_area);
y += items[i].height;
if (y > area.bottom())
break;
}
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
hide (
)
{
auto_mutex M(m);
sbv.hide();
sbh.hide();
drawable::hide();
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
show (
)
{
auto_mutex M(m);
hidden = false;
adjust_sliders();
drawable::show();
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
disable (
)
{
sbv.disable();
sbh.disable();
drawable::disable();
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
enable (
)
{
sbv.enable();
sbh.enable();
drawable::enable();
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
set_pos (
long x,
long y
)
{
auto_mutex M(m);
drawable::set_pos(x,y);
adjust_sliders();
}
style->draw_list_box_background(c, display_rect(), enabled);
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
adjust_sliders (
)
{
text_area = rectangle(rect.left()+2,rect.top()+2,rect.right()-1,rect.bottom()-1);
int extra_count = 0;
// find the max width and height of our text
unsigned long maxw = 0, maxh = 0;
long y = total_rect().top();
for (unsigned long i = 0; i < items.size(); ++i)
{
maxh += items[i].height;
if (maxh > text_area.height())
++extra_count;
if (items[i].width > maxw )
maxw = items[i].width;
}
if (maxh > text_area.height() && text_area.is_empty() == false)
{
if (!hidden)
sbv.show();
sbv.set_pos(rect.right()-sbv.width()-pad+1,rect.top()+pad);
sbv.set_length(rect.height()-pad*2);
text_area.set_right(text_area.right()-sbv.width()-1);
if (maxw > text_area.width())
{
if (!hidden)
sbh.show();
sbh.set_pos(rect.left()+pad,rect.bottom()-sbh.height()-pad+1);
sbh.set_length(rect.width()-pad*2 - sbv.width());
text_area.set_bottom(text_area.bottom()-sbh.height()-1);
sbh.set_max_slider_pos(maxw - text_area.width());
++extra_count;
}
else
{
sbh.hide();
}
sbv.set_max_slider_pos(extra_count);
}
else
{
sbv.hide();
pos = 0;
sbv.set_max_slider_pos(0);
if (maxw > text_area.width() && text_area.is_empty() == false)
{
if (!hidden)
sbh.show();
sbh.set_pos(rect.left()+pad,rect.bottom()-sbh.height()-pad+1);
sbh.set_length(rect.width()-pad*2);
text_area.set_bottom(text_area.bottom()-sbh.height()-1);
sbh.set_max_slider_pos(maxw - text_area.width());
}
else
{
sbh.hide();
}
}
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
sbh_handler (
)
if (y+(long)items[i].height <= area.top())
{
text_start = sbh.slider_pos();
parent.invalidate_rectangle(rect);
y += items[i].height;
continue;
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
sbv_handler (
)
{
pos = sbv.slider_pos();
parent.invalidate_rectangle(rect);
}
rectangle r(total_rect().left(), y, display_rect().right(), y+items[i].height-1);
// ----------------------------------------------------------------------------------------
style->draw_list_box_item(c,r, display_rect(), enabled, *mfont, items[i].name, items[i].is_selected);
template <typename S>
void list_box<S>::
on_wheel_up (
unsigned long state
)
{
if (rect.contains(lastx,lasty) && enabled && !hidden)
{
long new_pos = sbv.slider_pos();
if (new_pos > 0)
{
pos = new_pos-1;
sbv.set_slider_pos(pos);
parent.invalidate_rectangle(rect);
}
}
}
// ----------------------------------------------------------------------------------------
y += items[i].height;
template <typename S>
void list_box<S>::
on_wheel_down (
unsigned long state
)
{
if (rect.contains(lastx,lasty) && enabled && !hidden)
{
long new_pos = sbv.slider_pos();
if (new_pos < sbv.max_slider_pos())
{
pos = new_pos+1;
sbv.set_slider_pos(pos);
parent.invalidate_rectangle(rect);
}
if (y > area.bottom())
break;
}
}
......@@ -2615,7 +2381,7 @@ namespace dlib
bool is_double_click
)
{
if (text_area.contains(x,y) && btn == base_window::LEFT && enabled && !hidden )
if (display_rect().contains(x,y) && btn == base_window::LEFT && enabled && !hidden )
{
if ( ms_enabled == false ||
(!(state&base_window::CONTROL)) && !(state&base_window::SHIFT))
......@@ -2627,9 +2393,9 @@ namespace dlib
}
}
y -= text_area.top();
y -= total_rect().top();
long h = 0;
for (unsigned long i = pos; i < items.size(); ++i)
for (unsigned long i = 0; i < items.size(); ++i)
{
h += items[i].height;
if (h >= y)
......@@ -2679,19 +2445,6 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template <typename S>
void list_box<S>::
set_z_order (
long order
)
{
sbv.set_z_order(order);
sbh.set_z_order(order);
drawable::set_z_order(order);
}
// ----------------------------------------------------------------------------------------
template <typename S>
......
......@@ -1105,34 +1105,24 @@ namespace dlib
namespace list_box_helper{
template <typename S = std::string>
class list_box : public drawable,
class list_box : public scrollable_region,
public enumerable<const S>
{
/*!
INITIAL VALUE
- ms_enabled == false
- items.size() == 0
- pos == 0
- text_start = 0
- last_selected = 0
CONVENTION
- size() == items.size()
- (*this)[i] == items[i].name
- is_selected(i) == items[i].is_selected
- ms_enabled == multiple_select_enabled()
- items[i].width == the width of items[i].name as given by font::compute_size()
- items[i].height == the height of items[i].name as given by font::compute_size()
- items[pos] == the item currently being displayed at the top of the list box
- sbv == our vertical scroll bar
- sbh == our horizontal scroll bar
- text_area == the area that is free to be used for text display (e.g. not occluded
by scroll bars or anything)
- text_start == the amount of pixels the text should be shifted to the left (but the
part outside this widget should be clipped). This is used by the horizontal
scroll bar.
- pos == the first line that is shown in the list box
- last_selected == the last item the user selected
!*/
......@@ -1145,16 +1135,6 @@ namespace dlib
~list_box(
);
void set_size (
unsigned long width_,
unsigned long height_
);
void set_pos (
long x,
long y
);
bool is_selected (
unsigned long index
) const;
......@@ -1167,6 +1147,19 @@ namespace dlib
unsigned long index
);
template <
typename style_type
>
void set_style (
const style_type& style_
)
{
auto_mutex M(m);
style.reset(new style_type(style_));
scrollable_region::set_style(style_.get_scrollable_region_style());
parent.invalidate_rectangle(rect);
}
template <typename T>
void get_selected (
T& list
......@@ -1195,15 +1188,22 @@ namespace dlib
items.set_max_size(list.size());
items.set_size(list.size());
list.reset();
unsigned long max_width = 0;
unsigned long total_height = 0;
while (list.move_next())
{
items[i].is_selected = false;
items[i].name = list.element();
mfont->compute_size(items[i].name,items[i].width, items[i].height);
if (items[i].width > max_width)
max_width = items[i].width;
total_height += items[i].height;
++i;
}
pos = 0;
adjust_sliders();
set_total_rect_size(max_width, total_height);
parent.invalidate_rectangle(rect);
last_selected = 0;
}
......@@ -1258,22 +1258,6 @@ namespace dlib
unsigned long size (
) const;
void show(
);
void hide (
);
void enable (
);
void disable (
);
void set_z_order (
long order
);
unsigned long get_selected (
) const;
......@@ -1283,29 +1267,6 @@ namespace dlib
private:
void sbv_handler (
);
void sbh_handler (
);
void adjust_sliders (
);
/*!
requires
- m is locked
ensures
- adjusts the scroll bars so that they are properly displayed
!*/
void on_wheel_up (
unsigned long state
);
void on_wheel_down (
unsigned long state
);
void on_mouse_down (
unsigned long btn,
unsigned long state,
......@@ -1327,19 +1288,13 @@ namespace dlib
unsigned long height;
};
const static long pad = 2;
bool ms_enabled;
typename array<data<S> >::kernel_2a_c items;
member_function_pointer<unsigned long>::kernel_1a event_handler;
member_function_pointer<unsigned long>::kernel_1a single_click_event_handler;
unsigned long pos;
unsigned long text_start;
unsigned long last_selected;
scroll_bar sbv;
scroll_bar sbh;
rectangle text_area;
scoped_ptr<list_box_style> style;
// restricted functions
list_box(list_box&); // copy constructor
......
......@@ -956,7 +956,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class list_box : public drawable,
class list_box : public scrollable_region,
public enumerable<const std::string>
{
/*!
......@@ -996,6 +996,19 @@ namespace dlib
- all resources associated with *this have been released
!*/
template <
typename style_type
>
void set_style (
const style_type& style
);
/*!
requires
- style_type == a type that inherits from list_box_style
ensures
- this list_box object will draw itself using the given style
!*/
void set_size (
unsigned long width_,
unsigned long height_
......@@ -1165,13 +1178,13 @@ namespace dlib
list_box& operator=(list_box&); // assignment operator
};
class wlist_box : public drawable,
class wlist_box : public scrollable_region,
public enumerable<const std::wstring>;
/*!
same as list_box except for std::wstring instead of std::string
!*/
class ulist_box : public drawable,
class ulist_box : public scrollable_region,
public enumerable<const dlib::ustring>;
/*!
same as list_box except for dlib::ustring instead of std::string
......
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