// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_WIDGETs_
#define DLIB_WIDGETs_
#include "../algs.h"
#include "widgets_abstract.h"
#include "drawable.h"
#include "../gui_core.h"
#include "fonts.h"
#include <string>
#include <sstream>
#include "../timer.h"
#include "base_widgets.h"
#include "../member_function_pointer.h"
#include "../array.h"
#include "../sequence.h"
#include "../dir_nav.h"
#include "../queue.h"
#include "../smart_pointers.h"
#include "style.h"
#include "../string.h"
#include "../misc_api.h"
#include <cctype>
#ifdef _MSC_VER
// This #pragma directive is also located in the algs.h file but for whatever
// reason visual studio 9 just ignores it when it is only there.
// this is to disable the "'this' : used in base member initializer list"
// warning you get from some of the GUI objects since all the objects
// require that their parent class be passed into their constructor.
// In this case though it is totally safe so it is ok to disable this warning.
#pragma warning(disable : 4355)
#endif
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class label
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class label : public drawable
{
public:
label(
drawable_window& w
) :
drawable(w),
text_color_(0,0,0)
{
enable_events();
}
~label()
{ disable_events(); parent.invalidate_rectangle(rect); }
void set_text (
const std::string& text
);
void set_text (
const std::wstring& text
);
void set_text (
const dlib::ustring& text
);
const std::string text (
) const;
const std::wstring wtext (
) const;
const dlib::ustring utext (
) const;
void set_text_color (
const rgb_pixel color
);
const rgb_pixel text_color (
) const;
void set_main_font (
const font* f
);
private:
dlib::ustring text_;
rgb_pixel text_color_;
// restricted functions
label(label&); // copy constructor
label& operator=(label&); // assignment operator
protected:
void draw (
const canvas& c
) const;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// 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 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 : public button_action
{
/*!
INITIAL VALUE
- checked == false
CONVENTION
- is_checked() == checked
!*/
public:
toggle_button(
drawable_window& w
) :
button_action(w),
btn_tooltip(w),
checked(false)
{
style.reset(new toggle_button_style_default());
enable_events();
}
~toggle_button() { disable_events(); parent.invalidate_rectangle(rect); }
void set_name (
const std::string& name
);
void set_name (
const std::wstring& name
);
void set_name (
const dlib::ustring& name
);
void set_size (
unsigned long width_,
unsigned long height_
);
void set_tooltip_text (
const std::string& text
);
void set_tooltip_text (
const std::wstring& text
);
void set_tooltip_text (
const ustring& text
);
const std::string tooltip_text (
) const;
const std::wstring tooltip_wtext (
) const;
const dlib::ustring tooltip_utext (
) const;
bool is_checked (
) const;
const std::string name (
) const;
const std::wstring wname (
) const;
const dlib::ustring uname (
) const;
void set_checked (
);
void set_unchecked (
);
void show (
);
void hide (
);
void enable (
);
void disable (
);
void set_main_font (
const font* f
);
void set_pos (
long x,
long y
);
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_)(toggle_button&)
)
{
auto_mutex M(m);
event_handler_self.set(object,event_handler_);
event_handler.clear();
}
private:
// restricted functions
toggle_button(toggle_button&); // copy constructor
toggle_button& operator=(toggle_button&); // assignment operator
dlib::ustring name_;
tooltip btn_tooltip;
bool checked;
member_function_pointer<>::kernel_1a event_handler;
member_function_pointer<toggle_button&>::kernel_1a event_handler_self;
scoped_ptr<toggle_button_style> style;
protected:
void draw (
const canvas& c
) const { style->draw_toggle_button(c,rect,hidden,enabled,*mfont,lastx,lasty,name_,is_depressed(),checked); }
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 text_field
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class text_field : public drawable
{
/*!
INITIAL VALUE
text_color_ == rgb_pixel(0,0,0)
bg_color_ == rgb_pixel(255,255,255)
cursor_pos == 0
text_width == 0
text_ == ""
has_focus == false
cursor_visible == false
recent_movement == false
highlight_start == 0
highlight_end == -1
shift_pos == -1
text_pos == 0
CONVENTION
- cursor_pos == the position of the cursor in the string text_. The
cursor appears before the letter text_[cursor_pos]
- cursor_x == the x coordinate of the cursor relative to the left side
of rect. i.e. the number of pixels that separate the cursor from the
left side of the text_field.
- has_focus == true if this text field has keyboard input focus
- cursor_visible == true if the cursor should be painted
- text_ == text()
- text_pos == the index of the first letter in text_ that appears in
this text field.
- text_width == the width of text_[text_pos] though text_[text.size()-1]
- if (has_focus && the user has recently moved the cursor) then
- recent_movement == true
- else
- recent_movement == false
- if (highlight_start <= highlight_end) then
- text[highlight_start] though text[highlight_end] should be
highlighted
- if (shift_pos != -1) then
- has_focus == true
- the shift key is being held down or the left mouse button is
being held down.
- shift_pos == the position of the cursor when the shift or mouse key
was first pressed.
- text_color() == text_color_
- background_color() == bg_color_
!*/
public:
text_field(
drawable_window& w
) :
drawable(w,MOUSE_CLICK | KEYBOARD_EVENTS | MOUSE_MOVE | STRING_PUT),
text_color_(0,0,0),
bg_color_(255,255,255),
text_width(0),
text_pos(0),
recent_movement(false),
has_focus(false),
cursor_visible(false),
cursor_pos(0),
highlight_start(0),
highlight_end(-1),
shift_pos(-1),
t(*this,&text_field::timer_action)
{
rect.set_bottom(mfont->height()+ (mfont->height()-mfont->ascender())*2);
rect.set_right(9);
cursor_x = (mfont->height()-mfont->ascender());
enable_events();
t.set_delay_time(500);
}
~text_field (
)
{
disable_events();
parent.invalidate_rectangle(rect);
t.stop_and_wait();
}
void set_text (
const std::string& text_
);
void set_text (
const std::wstring& text_
);
void set_text (
const dlib::ustring& text_
);
const std::string text (
) const;
const std::wstring wtext (
) const;
const dlib::ustring utext (
) const;
void set_text_color (
const rgb_pixel color
);
const rgb_pixel text_color (
) const;
void set_background_color (
const rgb_pixel color
);
const rgb_pixel background_color (
) const;
void set_width (
unsigned long width
);
void set_main_font (
const font* f
);
int next_free_user_event_number (
) const
{
return drawable::next_free_user_event_number()+1;
}
void disable (
);
void hide (
);
template <
typename T
>
void set_text_modified_handler (
T& object,
void (T::*event_handler)()
)
{
auto_mutex M(m);
text_modified_handler.set(object,event_handler);
}
template <
typename T
>
void set_enter_key_handler (
T& object,
void (T::*event_handler)()
)
{
auto_mutex M(m);
enter_key_handler.set(object,event_handler);
}
template <
typename T
>
void set_focus_lost_handler (
T& object,
void (T::*event_handler)()
)
{
auto_mutex M(m);
focus_lost_handler.set(object,event_handler);
}
private:
void on_user_event (
int num
)
{
// ignore this user event if it isn't for us
if (num != drawable::next_free_user_event_number())
return;
if (recent_movement == false)
{
cursor_visible = !cursor_visible;
parent.invalidate_rectangle(rect);
}
else
{
if (cursor_visible == false)
{
cursor_visible = true;
parent.invalidate_rectangle(rect);
}
recent_movement = false;
}
}
void timer_action (
) { parent.trigger_user_event(this,drawable::next_free_user_event_number()); }
/*!
ensures
- flips the state of cursor_visible
!*/
void move_cursor (
unsigned long pos
);
/*!
requires
- pos <= text_.size()
ensures
- moves the cursor to the position given by pos and moves the text
in the text box if necessary
- if the position changes then the parent window will be updated
!*/
rectangle get_text_rect (
) const;
/*!
ensures
- returns the rectangle that should contain the text in this widget
!*/
dlib::ustring text_;
rgb_pixel text_color_;
rgb_pixel bg_color_;
unsigned long text_width;
unsigned long text_pos;
bool recent_movement;
bool has_focus;
bool cursor_visible;
long cursor_pos;
unsigned long cursor_x;
// this tells you what part of the text is highlighted
long highlight_start;
long highlight_end;
long shift_pos;
member_function_pointer<>::kernel_1a_c text_modified_handler;
member_function_pointer<>::kernel_1a_c enter_key_handler;
member_function_pointer<>::kernel_1a_c focus_lost_handler;
timer<text_field>::kernel_2a t;
// restricted functions
text_field(text_field&); // copy constructor
text_field& operator=(text_field&); // assignment operator
protected:
void draw (
const canvas& c
) const;
void on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
);
void on_mouse_up (
unsigned long btn,
unsigned long state,
long x,
long y
);
void on_mouse_move (
unsigned long state,
long x,
long y
);
void on_keydown (
unsigned long key,
bool is_printable,
unsigned long state
);
void on_string_put (
const std::wstring &str
);
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class check_box
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class check_box : public toggle_button
{
public:
check_box(
drawable_window& w
) : toggle_button(w)
{
set_style(toggle_button_style_check_box());
}
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class radio_button
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class radio_button : public toggle_button
{
public:
radio_button (
drawable_window& w
) : toggle_button(w)
{
set_style(toggle_button_style_radio_button());
}
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class tabbed_display
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class tabbed_display : public drawable
{
/*!
INITIAL VALUE
- tabs.size() == 0
- selected_tab_ == 0
CONVENTION
- number_of_tabs() == tabs.size()
- tab_name(idx) == tabs[idx]
- if (tabs.size() > 0) then
- selected_tab_ == the index of the tab that is currently selected
- for all valid i:
- tabs[i].width == mfont->compute_size(tabs[i].name)
- tabs[i].rect == the rectangle that defines where this tab is
- if (tabs[i].group != 0) then
- tabs[i].group == a pointer to the widget_group for this tab.
- left_pad == the amount of padding in a tab to the left of the name string.
- right_pad == the amount of padding in a tab to the right of the name string.
- top_pad == the amount of padding in a tab to the top of the name string.
- bottom_pad == the amount of padding in a tab to the bottom of the name string.
- if (event_handler.is_set()) then
- event_handler() is what is called to process click events
on this object.
!*/
public:
tabbed_display(
drawable_window& w
);
virtual ~tabbed_display(
);
void set_size (
unsigned long width,
unsigned long height
);
void set_number_of_tabs (
unsigned long num
);
unsigned long number_of_tabs (
) const;
const std::string tab_name (
unsigned long idx
) const;
const std::wstring tab_wname (
unsigned long idx
) const;
const dlib::ustring& tab_uname (
unsigned long idx
) const;
void set_tab_name (
unsigned long idx,
const std::string& new_name
);
void set_tab_name (
unsigned long idx,
const std::wstring& new_name
);
void set_tab_name (
unsigned long idx,
const dlib::ustring& new_name
);
void set_pos (
long x,
long y
);
template <
typename T
>
void set_click_handler (
T& object,
void (T::*eh)(unsigned long new_idx,unsigned long old_idx)
)
{
auto_mutex M(m);
event_handler.set(object,eh);
}
void set_tab_group (
unsigned long idx,
widget_group& group
);
void show (
);
void hide (
);
void enable (
);
void disable (
);
void set_main_font (
const font* f
);
void fit_to_contents (
);
protected:
void on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
);
void draw (
const canvas& c
) const;
private:
void recompute_tabs (
);
/*!
ensures
- recomputes the rectangles for all the tabs and makes this object
wider if needed
!*/
void draw_tab (
const rectangle& tab,
const canvas& c
) const;
/*!
ensures
- draws the outline of a tab as given by the rectangle onto c
!*/
struct tab_data
{
tab_data() : width(0), group(0) {}
dlib::ustring name;
unsigned long width;
rectangle rect;
widget_group* group;
};
unsigned long selected_tab_;
array<tab_data>::kernel_2a_c tabs;
const long left_pad;
const long right_pad;
const long top_pad;
const long bottom_pad;
member_function_pointer<unsigned long,unsigned long>::kernel_1a event_handler;
// restricted functions
tabbed_display(tabbed_display&); // copy constructor
tabbed_display& operator=(tabbed_display&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class named_rectangle
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class named_rectangle : public drawable
{
/*!
INITIAL VALUE
name == ""
CONVENTION
name_ == name()
!*/
public:
named_rectangle(
drawable_window& w
);
virtual ~named_rectangle(
);
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 wrap_around (
const rectangle& rect
);
void set_main_font (
const font* f
);
protected:
void draw (
const canvas& c
) const;
private:
void make_name_fit_in_rect (
);
dlib::ustring name_;
unsigned long name_width;
unsigned long name_height;
// restricted functions
named_rectangle(named_rectangle&); // copy constructor
named_rectangle& operator=(named_rectangle&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class mouse_tracker
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class mouse_tracker : public dragable
{
public:
mouse_tracker(
drawable_window& w
);
~mouse_tracker(
);
void show (
);
void hide (
);
void enable (
);
void disable (
);
void set_pos (
long x,
long y
);
void set_main_font (
const font* f
);
protected:
void on_mouse_move (
unsigned long state,
long x,
long y
);
void on_drag (
);
void draw (
const canvas& c
) const;
void on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
);
private:
const long offset;
named_rectangle nr;
label x_label;
label y_label;
std::ostringstream sout;
long click_x, click_y;
// restricted functions
mouse_tracker(mouse_tracker&); // copy constructor
mouse_tracker& operator=(mouse_tracker&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// function message_box()
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
namespace message_box_helper
{
class box_win : public drawable_window
{
void initialize (
)
{
msg.set_pos(20,20);
msg.set_text(message);
rectangle msg_rect = msg.get_rect();
btn_ok.set_name("OK");
btn_ok.set_size(60,btn_ok.height());
if (msg_rect.width() >= 60)
btn_ok.set_pos(msg_rect.width()/2+msg_rect.left()-btn_ok.width()/2,msg_rect.bottom()+15);
else
btn_ok.set_pos(20,msg_rect.bottom()+15);
btn_ok.set_click_handler(*this,&box_win::on_click);
rectangle size = btn_ok.get_rect() + msg_rect;
set_size(size.right()+20,size.bottom()+20);
show();
set_title(title);
}
public:
box_win (
const std::string& title_,
const std::string& message_
) :
drawable_window(false),
title(convert_mbstring_to_wstring(title_)),
message(convert_mbstring_to_wstring(message_)),
msg(*this),
btn_ok(*this)
{
initialize();
}
box_win (
const std::wstring& title_,
const std::wstring& message_
) :
drawable_window(false),
title(title_),
message(message_),
msg(*this),
btn_ok(*this)
{
initialize();
}
box_win (
const dlib::ustring& title_,
const dlib::ustring& message_
) :
drawable_window(false),
title(convert_utf32_to_wstring(title_)),
message(convert_utf32_to_wstring(message_)),
msg(*this),
btn_ok(*this)
{
initialize();
}
~box_win (
)
{
close_window();
}
template <
typename T
>
void set_click_handler (
T& object,
void (T::*event_handler_)()
)
{
auto_mutex M(wm);
event_handler.set(object,event_handler_);
}
private:
static void deleter_thread (
void* param
)
{
// The point of this extra member function pointer stuff is to allow the user
// to end the program from within the callback. So we want to destroy the
// window *before* we call their callback.
box_win& w = *reinterpret_cast<box_win*>(param);
w.close_window();
member_function_pointer<>::kernel_1a event_handler(w.event_handler);
delete &w;
if (event_handler.is_set())
event_handler();
}
void on_click (
)
{
hide();
create_new_thread(&deleter_thread,this);
}
on_close_return_code on_window_close (
)
{
// The point of this extra member function pointer stuff is to allow the user
// to end the program within the callback. So we want to destroy the
// window *before* we call their callback.
member_function_pointer<>::kernel_1a event_handler_copy(event_handler);
delete this;
if (event_handler_copy.is_set())
event_handler_copy();
return CLOSE_WINDOW;
}
const std::wstring title;
const std::wstring message;
label msg;
button btn_ok;
member_function_pointer<>::kernel_1a event_handler;
};
class blocking_box_win : public drawable_window
{
void initialize (
)
{
msg.set_pos(20,20);
msg.set_text(message);
rectangle msg_rect = msg.get_rect();
btn_ok.set_name("OK");
btn_ok.set_size(60,btn_ok.height());
if (msg_rect.width() >= 60)
btn_ok.set_pos(msg_rect.width()/2+msg_rect.left()-btn_ok.width()/2,msg_rect.bottom()+15);
else
btn_ok.set_pos(20,msg_rect.bottom()+15);
btn_ok.set_click_handler(*this,&blocking_box_win::on_click);
rectangle size = btn_ok.get_rect() + msg_rect;
set_size(size.right()+20,size.bottom()+20);
set_title(title);
show();
}
public:
blocking_box_win (
const std::string& title_,
const std::string& message_
) :
drawable_window(false),
title(convert_mbstring_to_wstring(title_)),
message(convert_mbstring_to_wstring(message_)),
msg(*this),
btn_ok(*this)
{
initialize();
}
blocking_box_win (
const std::wstring& title_,
const std::wstring& message_
) :
drawable_window(false),
title(title_),
message(message_),
msg(*this),
btn_ok(*this)
{
initialize();
}
blocking_box_win (
const dlib::ustring& title_,
const dlib::ustring& message_
) :
drawable_window(false),
title(convert_utf32_to_wstring(title_)),
message(convert_utf32_to_wstring(message_)),
msg(*this),
btn_ok(*this)
{
initialize();
}
~blocking_box_win (
)
{
close_window();
}
private:
void on_click (
)
{
close_window();
}
const std::wstring title;
const std::wstring message;
label msg;
button btn_ok;
};
}
template <
typename T
>
void message_box (
const std::string& title,
const std::string& message,
T& object,
void (T::*event_handler)()
)
{
using namespace message_box_helper;
box_win* win = new box_win(title,message);
win->set_click_handler(object,event_handler);
}
inline void message_box (
const std::string& title,
const std::string& message
)
{
using namespace message_box_helper;
new box_win(title,message);
}
inline void message_box_blocking (
const std::string& title,
const std::string& message
)
{
using namespace message_box_helper;
blocking_box_win w(title,message);
w.wait_until_closed();
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class list_box
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
namespace list_box_helper{
template <typename S = std::string>
class list_box : public drawable,
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
- 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
!*/
public:
list_box(
drawable_window& w
);
~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;
void select (
unsigned long index
);
void unselect (
unsigned long index
);
template <typename T>
void get_selected (
T& list
) const
{
auto_mutex M(m);
list.clear();
for (unsigned long i = 0; i < items.size(); ++i)
{
if (items[i].is_selected)
{
unsigned long idx = i;
list.enqueue(idx);
}
}
}
template <typename T>
void load (
const T& list
)
{
auto_mutex M(m);
items.clear();
unsigned long i = 0;
items.set_max_size(list.size());
items.set_size(list.size());
list.reset();
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);
++i;
}
pos = 0;
adjust_sliders();
parent.invalidate_rectangle(rect);
last_selected = 0;
}
const S& operator[] (
unsigned long index
) const;
bool multiple_select_enabled (
) const;
void enable_multiple_select (
);
void disable_multiple_select (
);
template <
typename T
>
void set_double_click_handler (
T& object,
void (T::*eh)(unsigned long index)
) { auto_mutex M(m); event_handler.set(object,eh); }
template <
typename T
>
void set_click_handler (
T& object,
void (T::*eh)(unsigned long index)
) { auto_mutex M(m); single_click_event_handler.set(object,eh); }
bool at_start (
) const;
void reset (
) const;
bool current_element_valid (
) const;
const S& element (
) const;
const S& element (
);
bool move_next (
) const;
unsigned long size (
) const;
void show(
);
void hide (
);
void enable (
);
void disable (
);
void set_z_order (
long order
);
unsigned long get_selected (
) const;
void set_main_font (
const font* f
);
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 (
);
void on_wheel_down (
);
void on_mouse_down (
unsigned long btn,
unsigned long state,
long x,
long y,
bool is_double_click
);
void draw (
const canvas& c
) const;
template <typename SS>
struct data
{
SS name;
bool is_selected;
unsigned long width;
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;
// restricted functions
list_box(list_box&); // copy constructor
list_box& operator=(list_box&); // assignment operator
};
}
typedef list_box_helper::list_box<std::string> list_box;
typedef list_box_helper::list_box<std::wstring> wlist_box;
typedef list_box_helper::list_box<dlib::ustring> ulist_box;
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// function open_file_box()
// -----------------------------------------------------------------------------------