|
|
|
|
|
#ifndef DLIB_BASE_WIDGETs_CPP_ |
|
#define DLIB_BASE_WIDGETs_CPP_ |
|
|
|
#include <iostream> |
|
#include <memory> |
|
|
|
#include "base_widgets.h" |
|
#include "../assert.h" |
|
|
|
namespace dlib |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void button:: |
|
set_size ( |
|
unsigned long width, |
|
unsigned long height |
|
) |
|
{ |
|
auto_mutex M(m); |
|
rectangle min_rect = style->get_min_size(name_,*mfont); |
|
|
|
if (height >= min_rect.height() && |
|
width >= min_rect.width()) |
|
{ |
|
rectangle old(rect); |
|
rect = resize_rect(rect,width,height); |
|
parent.invalidate_rectangle(style->get_invalidation_rect(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 std::shared_ptr<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; |
|
|
|
|
|
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(style->get_invalidation_rect(rect+old)); |
|
} |
|
|
|
|
|
|
|
const std::string button:: |
|
name ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
std::string temp = convert_wstring_to_mbstring(wname()); |
|
|
|
|
|
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()); |
|
|
|
|
|
wchar_t w = temp[0]; |
|
temp[0] = w; |
|
return temp; |
|
} |
|
|
|
const dlib::ustring button:: |
|
uname ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
dlib::ustring temp = name_; |
|
|
|
|
|
temp[0] = name_[0]; |
|
return temp; |
|
} |
|
|
|
|
|
|
|
void button:: |
|
on_button_up ( |
|
bool mouse_over |
|
) |
|
{ |
|
if (mouse_over) |
|
{ |
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
draggable::~draggable() {} |
|
|
|
|
|
|
|
void draggable:: |
|
on_mouse_move ( |
|
unsigned long state, |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (drag && (state & base_window::LEFT) && enabled && !hidden) |
|
{ |
|
|
|
|
|
|
|
long new_x = x - this->x; |
|
long new_y = y - this->y; |
|
|
|
|
|
if (new_x < area.left()) |
|
new_x = area.left(); |
|
if (new_x + static_cast<long>(rect.width()) - 1 > area.right()) |
|
new_x = area.right() - rect.width() + 1; |
|
|
|
if (new_y + static_cast<long>(rect.height()) - 1 > area.bottom()) |
|
new_y = area.bottom() - rect.height() + 1; |
|
if (new_y < area.top()) |
|
new_y = area.top(); |
|
|
|
|
|
rectangle new_rect( |
|
new_x, |
|
new_y, |
|
new_x + rect.width() - 1, |
|
new_y + rect.height() - 1 |
|
); |
|
|
|
|
|
if (new_rect != rect && area.intersect(new_rect) == new_rect) |
|
{ |
|
parent.invalidate_rectangle(new_rect + rect); |
|
rect = new_rect; |
|
|
|
|
|
on_drag(); |
|
} |
|
} |
|
else |
|
{ |
|
drag = false; |
|
on_drag_stop(); |
|
} |
|
} |
|
|
|
|
|
|
|
void draggable:: |
|
on_mouse_up ( |
|
unsigned long , |
|
unsigned long state, |
|
long , |
|
long |
|
) |
|
{ |
|
if (drag && (state & base_window::LEFT) == 0) |
|
{ |
|
drag = false; |
|
on_drag_stop(); |
|
} |
|
} |
|
|
|
|
|
|
|
void draggable:: |
|
on_mouse_down ( |
|
unsigned long btn, |
|
unsigned long , |
|
long x, |
|
long y, |
|
bool |
|
) |
|
{ |
|
if (enabled && !hidden && rect.contains(x,y) && btn == base_window::LEFT) |
|
{ |
|
drag = true; |
|
this->x = x - rect.left(); |
|
this->y = y - rect.top(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mouse_over_event::~mouse_over_event() {} |
|
|
|
|
|
|
|
void mouse_over_event:: |
|
on_mouse_leave ( |
|
) |
|
{ |
|
if (is_mouse_over_) |
|
{ |
|
is_mouse_over_ = false; |
|
on_mouse_not_over(); |
|
} |
|
} |
|
|
|
|
|
|
|
void mouse_over_event:: |
|
on_mouse_move ( |
|
unsigned long , |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (rect.contains(x,y) == false) |
|
{ |
|
if (is_mouse_over_) |
|
{ |
|
is_mouse_over_ = false; |
|
on_mouse_not_over(); |
|
} |
|
} |
|
else if (is_mouse_over_ == false) |
|
{ |
|
is_mouse_over_ = true; |
|
if (enabled && !hidden) |
|
on_mouse_over(); |
|
} |
|
} |
|
|
|
|
|
|
|
bool mouse_over_event:: |
|
is_mouse_over ( |
|
) const |
|
{ |
|
|
|
if (is_mouse_over_ && rect.contains(lastx,lasty) == false) |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
parent.trigger_user_event((void*)this,drawable::next_free_user_event_number()); |
|
return false; |
|
} |
|
|
|
return is_mouse_over_; |
|
} |
|
|
|
|
|
|
|
void mouse_over_event:: |
|
on_user_event ( |
|
int num |
|
) |
|
{ |
|
if (is_mouse_over_ && num == drawable::next_free_user_event_number()) |
|
{ |
|
is_mouse_over_ = false; |
|
on_mouse_not_over(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
button_action::~button_action() {} |
|
|
|
|
|
|
|
void button_action:: |
|
on_mouse_down ( |
|
unsigned long btn, |
|
unsigned long , |
|
long x, |
|
long y, |
|
bool |
|
) |
|
{ |
|
if (enabled && !hidden && btn == base_window::LEFT && rect.contains(x,y)) |
|
{ |
|
is_depressed_ = true; |
|
seen_click = true; |
|
parent.invalidate_rectangle(rect); |
|
on_button_down(); |
|
} |
|
} |
|
|
|
|
|
|
|
void button_action:: |
|
on_mouse_not_over ( |
|
) |
|
{ |
|
if (is_depressed_) |
|
{ |
|
is_depressed_ = false; |
|
parent.invalidate_rectangle(rect); |
|
on_button_up(false); |
|
} |
|
} |
|
|
|
|
|
|
|
void button_action:: |
|
on_mouse_move ( |
|
unsigned long state, |
|
long x, |
|
long y |
|
) |
|
{ |
|
|
|
mouse_over_event::on_mouse_move(state,x,y); |
|
|
|
if (enabled == false || hidden == true) |
|
return; |
|
|
|
|
|
if ((state & base_window::LEFT) == 0) |
|
{ |
|
seen_click = false; |
|
if (is_depressed_) |
|
{ |
|
is_depressed_ = false; |
|
parent.invalidate_rectangle(rect); |
|
on_button_up(false); |
|
} |
|
|
|
|
|
return; |
|
} |
|
|
|
if (rect.contains(x,y) == false) |
|
{ |
|
if (is_depressed_) |
|
{ |
|
is_depressed_ = false; |
|
parent.invalidate_rectangle(rect); |
|
on_button_up(false); |
|
} |
|
} |
|
else if (is_depressed_ == false && seen_click) |
|
{ |
|
is_depressed_ = true; |
|
parent.invalidate_rectangle(rect); |
|
on_button_down(); |
|
} |
|
} |
|
|
|
|
|
|
|
void button_action:: |
|
on_mouse_up ( |
|
unsigned long btn, |
|
unsigned long, |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (enabled && !hidden && btn == base_window::LEFT) |
|
{ |
|
if (is_depressed_) |
|
{ |
|
is_depressed_ = false; |
|
parent.invalidate_rectangle(rect); |
|
|
|
if (rect.contains(x,y)) |
|
{ |
|
on_button_up(true); |
|
} |
|
else |
|
{ |
|
on_button_up(false); |
|
} |
|
} |
|
else if (seen_click && rect.contains(x,y)) |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parent.invalidate_rectangle(rect); |
|
|
|
on_button_down(); |
|
on_button_up(true); |
|
} |
|
|
|
seen_click = false; |
|
} |
|
} |
|
|
|
|
|
|
|
bool button_action:: |
|
is_depressed ( |
|
) const |
|
{ |
|
|
|
if (enabled && !hidden && is_depressed_ && rect.contains(lastx,lasty) == false) |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
parent.trigger_user_event((void*)this,mouse_over_event::next_free_user_event_number()); |
|
return false; |
|
} |
|
|
|
return is_depressed_; |
|
} |
|
|
|
|
|
|
|
void button_action:: |
|
on_user_event ( |
|
int num |
|
) |
|
{ |
|
|
|
mouse_over_event::on_user_event(num); |
|
|
|
if (is_depressed_ && num == mouse_over_event::next_free_user_event_number()) |
|
{ |
|
is_depressed_ = false; |
|
parent.invalidate_rectangle(rect); |
|
on_button_up(false); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scroll_bar:: |
|
scroll_bar( |
|
drawable_window& w, |
|
bar_orientation orientation |
|
) : |
|
drawable(w), |
|
b1(w), |
|
b2(w), |
|
slider(w,*this,&scroll_bar::on_slider_drag), |
|
ori(orientation), |
|
top_filler(w,*this,&scroll_bar::top_filler_down,&scroll_bar::top_filler_up), |
|
bottom_filler(w,*this,&scroll_bar::bottom_filler_down,&scroll_bar::bottom_filler_up), |
|
pos(0), |
|
max_pos(0), |
|
js(10), |
|
b1_timer(*this,&scroll_bar::b1_down_t), |
|
b2_timer(*this,&scroll_bar::b2_down_t), |
|
top_filler_timer(*this,&scroll_bar::top_filler_down_t), |
|
bottom_filler_timer(*this,&scroll_bar::bottom_filler_down_t) |
|
{ |
|
set_style(scroll_bar_style_default()); |
|
|
|
|
|
slider.hide(); |
|
|
|
set_length(100); |
|
|
|
b1.set_button_down_handler(*this,&scroll_bar::b1_down); |
|
b2.set_button_down_handler(*this,&scroll_bar::b2_down); |
|
|
|
b1.set_button_up_handler(*this,&scroll_bar::b1_up); |
|
b2.set_button_up_handler(*this,&scroll_bar::b2_up); |
|
b1.disable(); |
|
b2.disable(); |
|
enable_events(); |
|
} |
|
|
|
|
|
|
|
scroll_bar:: |
|
~scroll_bar( |
|
) |
|
{ |
|
disable_events(); |
|
parent.invalidate_rectangle(rect); |
|
|
|
b1_timer.stop_and_wait(); |
|
b2_timer.stop_and_wait(); |
|
top_filler_timer.stop_and_wait(); |
|
bottom_filler_timer.stop_and_wait(); |
|
} |
|
|
|
|
|
|
|
scroll_bar::bar_orientation scroll_bar:: |
|
orientation ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return ori; |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
set_length ( |
|
unsigned long length |
|
) |
|
{ |
|
auto_mutex M(m); |
|
|
|
if (length == 0) |
|
{ |
|
length = 1; |
|
} |
|
|
|
|
|
parent.invalidate_rectangle(rect); |
|
|
|
if (ori == HORIZONTAL) |
|
{ |
|
rect.set_right(rect.left() + length - 1); |
|
rect.set_bottom(rect.top() + style->get_width() - 1); |
|
|
|
const long btn_size = style->get_button_length(rect.width(), max_pos); |
|
|
|
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() + style->get_width() - 1); |
|
rect.set_bottom(rect.top() + length - 1); |
|
|
|
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()); |
|
} |
|
|
|
|
|
set_pos (rect.left(),rect.top()); |
|
|
|
if ((b2.get_rect().top() - b1.get_rect().bottom() - 1 <= 8 && ori == VERTICAL) || |
|
(b2.get_rect().left() - b1.get_rect().right() - 1 <= 8 && ori == HORIZONTAL) || |
|
max_pos == 0) |
|
{ |
|
hide_slider(); |
|
} |
|
else if (enabled && !hidden) |
|
{ |
|
show_slider(); |
|
} |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
set_pos ( |
|
long x, |
|
long y |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::set_pos(x,y); |
|
|
|
b1.set_pos(rect.left(),rect.top()); |
|
if (ori == HORIZONTAL) |
|
{ |
|
|
|
b2.set_pos(rect.right()-b2.get_rect().width() + 1,rect.top()); |
|
|
|
if (max_pos != 0) |
|
{ |
|
double range = b2.get_rect().left() - b1.get_rect().right() - slider.get_rect().width() - 1; |
|
double slider_pos = pos; |
|
slider_pos /= max_pos; |
|
slider_pos *= range; |
|
slider.set_pos( |
|
static_cast<long>(slider_pos)+rect.left() + b1.get_rect().width(), |
|
rect.top() |
|
); |
|
|
|
|
|
rectangle area = rect; |
|
area.set_left(area.left() + style->get_width()); |
|
area.set_right(area.right() - style->get_width()); |
|
slider.set_draggable_area(area); |
|
|
|
} |
|
|
|
|
|
} |
|
else |
|
{ |
|
|
|
b2.set_pos(rect.left(), rect.bottom() - b2.get_rect().height() + 1); |
|
|
|
if (max_pos != 0) |
|
{ |
|
double range = b2.get_rect().top() - b1.get_rect().bottom() - slider.get_rect().height() - 1; |
|
double slider_pos = pos; |
|
slider_pos /= max_pos; |
|
slider_pos *= range; |
|
slider.set_pos( |
|
rect.left(), |
|
static_cast<long>(slider_pos) + rect.top() + b1.get_rect().height() |
|
); |
|
|
|
|
|
rectangle area = rect; |
|
area.set_top(area.top() + style->get_width()); |
|
area.set_bottom(area.bottom() - style->get_width()); |
|
slider.set_draggable_area(area); |
|
} |
|
} |
|
|
|
adjust_fillers(); |
|
} |
|
|
|
|
|
|
|
unsigned long scroll_bar:: |
|
get_slider_size ( |
|
) const |
|
{ |
|
if (ori == HORIZONTAL) |
|
return style->get_slider_length(rect.width(),max_pos); |
|
else |
|
return style->get_slider_length(rect.height(),max_pos); |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
adjust_fillers ( |
|
) |
|
{ |
|
rectangle top(rect), bottom(rect); |
|
|
|
if (ori == HORIZONTAL) |
|
{ |
|
if (slider.is_hidden()) |
|
{ |
|
top.set_left(b1.get_rect().right()+1); |
|
top.set_right(b2.get_rect().left()-1); |
|
bottom.set_left(1); |
|
bottom.set_right(-1); |
|
} |
|
else |
|
{ |
|
top.set_left(b1.get_rect().right()+1); |
|
top.set_right(slider.get_rect().left()-1); |
|
bottom.set_left(slider.get_rect().right()+1); |
|
bottom.set_right(b2.get_rect().left()-1); |
|
} |
|
} |
|
else |
|
{ |
|
if (slider.is_hidden()) |
|
{ |
|
top.set_top(b1.get_rect().bottom()+1); |
|
top.set_bottom(b2.get_rect().top()-1); |
|
bottom.set_top(1); |
|
bottom.set_bottom(-1); |
|
} |
|
else |
|
{ |
|
top.set_top(b1.get_rect().bottom()+1); |
|
top.set_bottom(slider.get_rect().top()-1); |
|
bottom.set_top(slider.get_rect().bottom()+1); |
|
bottom.set_bottom(b2.get_rect().top()-1); |
|
} |
|
} |
|
|
|
top_filler.rect = top; |
|
bottom_filler.rect = bottom; |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
hide_slider ( |
|
) |
|
{ |
|
rectangle top(rect), bottom(rect); |
|
slider.hide(); |
|
top_filler.disable(); |
|
bottom_filler.disable(); |
|
bottom_filler.hide(); |
|
if (ori == HORIZONTAL) |
|
{ |
|
top.set_left(b1.get_rect().right()+1); |
|
top.set_right(b2.get_rect().left()-1); |
|
} |
|
else |
|
{ |
|
top.set_top(b1.get_rect().bottom()+1); |
|
top.set_bottom(b2.get_rect().top()-1); |
|
} |
|
top_filler.rect = top; |
|
bottom_filler.rect = bottom; |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
show_slider ( |
|
) |
|
{ |
|
if ((b2.get_rect().top() - b1.get_rect().bottom() - 1 <= 8 && ori == VERTICAL) || |
|
(b2.get_rect().left() - b1.get_rect().right() - 1 <= 8 && ori == HORIZONTAL) || |
|
max_pos == 0) |
|
return; |
|
|
|
rectangle top(rect), bottom(rect); |
|
slider.show(); |
|
top_filler.enable(); |
|
bottom_filler.enable(); |
|
bottom_filler.show(); |
|
if (ori == HORIZONTAL) |
|
{ |
|
top.set_left(b1.get_rect().right()+1); |
|
top.set_right(slider.get_rect().left()-1); |
|
bottom.set_left(slider.get_rect().right()+1); |
|
bottom.set_right(b2.get_rect().left()-1); |
|
} |
|
else |
|
{ |
|
top.set_top(b1.get_rect().bottom()+1); |
|
top.set_bottom(slider.get_rect().top()-1); |
|
bottom.set_top(slider.get_rect().bottom()+1); |
|
bottom.set_bottom(b2.get_rect().top()-1); |
|
} |
|
top_filler.rect = top; |
|
bottom_filler.rect = bottom; |
|
} |
|
|
|
|
|
|
|
long scroll_bar:: |
|
max_slider_pos ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return max_pos; |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
set_max_slider_pos ( |
|
long mpos |
|
) |
|
{ |
|
auto_mutex M(m); |
|
max_pos = mpos; |
|
if (pos > mpos) |
|
pos = mpos; |
|
|
|
if (ori == HORIZONTAL) |
|
set_length(rect.width()); |
|
else |
|
set_length(rect.height()); |
|
|
|
if (mpos != 0 && enabled) |
|
{ |
|
b1.enable(); |
|
b2.enable(); |
|
} |
|
else |
|
{ |
|
b1.disable(); |
|
b2.disable(); |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
set_slider_pos ( |
|
long pos |
|
) |
|
{ |
|
auto_mutex M(m); |
|
if (pos < 0) |
|
pos = 0; |
|
if (pos > max_pos) |
|
pos = max_pos; |
|
|
|
this->pos = pos; |
|
|
|
|
|
set_pos(rect.left(),rect.top()); |
|
} |
|
|
|
|
|
|
|
long scroll_bar:: |
|
slider_pos ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return pos; |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
on_slider_drag ( |
|
) |
|
{ |
|
if (ori == HORIZONTAL) |
|
{ |
|
double slider_pos = slider.get_rect().left() - b1.get_rect().right() - 1; |
|
double range = b2.get_rect().left() - b1.get_rect().right() - slider.get_rect().width() - 1; |
|
slider_pos /= range; |
|
slider_pos *= max_pos; |
|
pos = static_cast<unsigned long>(slider_pos); |
|
} |
|
else |
|
{ |
|
double slider_pos = slider.get_rect().top() - b1.get_rect().bottom() - 1; |
|
double range = b2.get_rect().top() - b1.get_rect().bottom() - slider.get_rect().height() - 1; |
|
slider_pos /= range; |
|
slider_pos *= max_pos; |
|
pos = static_cast<unsigned long>(slider_pos); |
|
} |
|
|
|
adjust_fillers(); |
|
|
|
if (scroll_handler.is_set()) |
|
scroll_handler(); |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
draw ( |
|
const canvas& |
|
) const |
|
{ |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
b1_down ( |
|
) |
|
{ |
|
if (pos != 0) |
|
{ |
|
set_slider_pos(pos-1); |
|
if (scroll_handler.is_set()) |
|
scroll_handler(); |
|
|
|
if (b1_timer.delay_time() == 1000) |
|
b1_timer.set_delay_time(500); |
|
else |
|
b1_timer.set_delay_time(50); |
|
b1_timer.start(); |
|
} |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
b1_up ( |
|
bool |
|
) |
|
{ |
|
b1_timer.stop(); |
|
b1_timer.set_delay_time(1000); |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
b2_down ( |
|
) |
|
{ |
|
if (pos != max_pos) |
|
{ |
|
set_slider_pos(pos+1); |
|
if (scroll_handler.is_set()) |
|
scroll_handler(); |
|
|
|
if (b2_timer.delay_time() == 1000) |
|
b2_timer.set_delay_time(500); |
|
else |
|
b2_timer.set_delay_time(50); |
|
b2_timer.start(); |
|
} |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
b2_up ( |
|
bool |
|
) |
|
{ |
|
b2_timer.stop(); |
|
b2_timer.set_delay_time(1000); |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
top_filler_down ( |
|
) |
|
{ |
|
|
|
|
|
if (top_filler.rect.contains(lastx,lasty) == false) |
|
{ |
|
top_filler_up(false); |
|
return; |
|
} |
|
|
|
if (pos != 0) |
|
{ |
|
if (pos < js) |
|
{ |
|
|
|
|
|
delayed_set_slider_pos(0); |
|
} |
|
else |
|
{ |
|
delayed_set_slider_pos(pos-js); |
|
} |
|
|
|
if (top_filler_timer.delay_time() == 1000) |
|
top_filler_timer.set_delay_time(500); |
|
else |
|
top_filler_timer.set_delay_time(50); |
|
top_filler_timer.start(); |
|
} |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
top_filler_up ( |
|
bool |
|
) |
|
{ |
|
top_filler_timer.stop(); |
|
top_filler_timer.set_delay_time(1000); |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
bottom_filler_down ( |
|
) |
|
{ |
|
|
|
|
|
if (bottom_filler.rect.contains(lastx,lasty) == false) |
|
{ |
|
bottom_filler_up(false); |
|
return; |
|
} |
|
|
|
if (pos != max_pos) |
|
{ |
|
if (max_pos - pos < js) |
|
{ |
|
|
|
|
|
delayed_set_slider_pos(max_pos); |
|
} |
|
else |
|
{ |
|
delayed_set_slider_pos(pos+js); |
|
} |
|
|
|
if (bottom_filler_timer.delay_time() == 1000) |
|
bottom_filler_timer.set_delay_time(500); |
|
else |
|
bottom_filler_timer.set_delay_time(50); |
|
bottom_filler_timer.start(); |
|
} |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
bottom_filler_up ( |
|
bool |
|
) |
|
{ |
|
bottom_filler_timer.stop(); |
|
bottom_filler_timer.set_delay_time(1000); |
|
} |
|
|
|
|
|
|
|
void scroll_bar:: |
|
set_jump_size ( |
|
long js_ |
|
) |
|
{ |
|
auto_mutex M(m); |
|
if (js_ < 1) |
|
js = 1; |
|
else |
|
js = js_; |
|
} |
|
|
|
|
|
|
|
long scroll_bar:: |
|
jump_size ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
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 (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); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void widget_group:: |
|
empty ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
widgets.clear(); |
|
wg_widgets.clear(); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
add ( |
|
drawable& widget, |
|
unsigned long x, |
|
unsigned long y |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable* w = &widget; |
|
relpos rp; |
|
rp.x = x; |
|
rp.y = y; |
|
if (widgets.is_in_domain(w)) |
|
{ |
|
widgets[w].x = x; |
|
widgets[w].y = y; |
|
} |
|
else |
|
{ |
|
widgets.add(w,rp); |
|
} |
|
if (is_hidden()) |
|
widget.hide(); |
|
else |
|
widget.show(); |
|
|
|
if (is_enabled()) |
|
widget.enable(); |
|
else |
|
widget.disable(); |
|
|
|
widget.set_z_order(z_order()); |
|
widget.set_pos(x+rect.left(),y+rect.top()); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
add ( |
|
widget_group& widget, |
|
unsigned long x, |
|
unsigned long y |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable& w = widget; |
|
add(w, x, y); |
|
|
|
widget_group* wg = &widget; |
|
wg_widgets.add(wg); |
|
} |
|
|
|
|
|
|
|
bool widget_group:: |
|
is_member ( |
|
const drawable& widget |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
drawable* w = const_cast<drawable*>(&widget); |
|
return widgets.is_in_domain(w); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
remove ( |
|
const drawable& widget |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable* w = const_cast<drawable*>(&widget); |
|
if (widgets.is_in_domain(w)) |
|
{ |
|
widgets.destroy(w); |
|
|
|
|
|
|
|
widget_group* wg = reinterpret_cast<widget_group*>(w); |
|
if (wg_widgets.is_member(wg)) |
|
{ |
|
wg_widgets.destroy(wg); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
size_t widget_group:: |
|
size ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return widgets.size(); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
set_pos ( |
|
long x, |
|
long y |
|
) |
|
{ |
|
auto_mutex M(m); |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
{ |
|
const unsigned long rx = widgets.element().value().x; |
|
const unsigned long ry = widgets.element().value().y; |
|
widgets.element().key()->set_pos(x+rx,y+ry); |
|
} |
|
drawable::set_pos(x,y); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
set_z_order ( |
|
long order |
|
) |
|
{ |
|
auto_mutex M(m); |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
widgets.element().key()->set_z_order(order); |
|
drawable::set_z_order(order); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
show ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
widgets.element().key()->show(); |
|
drawable::show(); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
hide ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
widgets.element().key()->hide(); |
|
drawable::hide(); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
enable ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
widgets.element().key()->enable(); |
|
drawable::enable(); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
disable () |
|
{ |
|
auto_mutex M(m); |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
widgets.element().key()->disable(); |
|
drawable::disable(); |
|
} |
|
|
|
|
|
|
|
void widget_group:: |
|
fit_to_contents ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
|
|
|
|
wg_widgets.reset(); |
|
while (wg_widgets.move_next()) |
|
wg_widgets.element()->fit_to_contents(); |
|
|
|
|
|
rectangle r; |
|
widgets.reset(); |
|
while (widgets.move_next()) |
|
r = r + widgets.element().key()->get_rect(); |
|
|
|
if (r.is_empty()) |
|
{ |
|
|
|
r.set_right(rect.left()-1); |
|
r.set_bottom(rect.top()-1); |
|
} |
|
|
|
r.set_left(rect.left()); |
|
r.set_top(rect.top()); |
|
rect = r; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
popup_menu:: |
|
popup_menu ( |
|
) : |
|
base_window(false,true), |
|
pad(2), |
|
item_pad(3), |
|
cur_rect(pad,pad,pad-1,pad-1), |
|
left_width(0), |
|
middle_width(0), |
|
selected_item(0), |
|
submenu_open(false) |
|
{ |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
enable_menu_item ( |
|
unsigned long idx |
|
) |
|
{ |
|
DLIB_ASSERT ( idx < size() , |
|
"\tvoid popup_menu::enable_menu_item()" |
|
<< "\n\tidx: " << idx |
|
<< "\n\tsize(): " << size() |
|
); |
|
auto_mutex M(wm); |
|
item_enabled[idx] = true; |
|
invalidate_rectangle(cur_rect); |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
disable_menu_item ( |
|
unsigned long idx |
|
) |
|
{ |
|
DLIB_ASSERT ( idx < size() , |
|
"\tvoid popup_menu::enable_menu_item()" |
|
<< "\n\tidx: " << idx |
|
<< "\n\tsize(): " << size() |
|
); |
|
auto_mutex M(wm); |
|
item_enabled[idx] = false; |
|
invalidate_rectangle(cur_rect); |
|
} |
|
|
|
|
|
|
|
size_t popup_menu:: |
|
size ( |
|
) const |
|
{ |
|
auto_mutex M(wm); |
|
return items.size(); |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
clear ( |
|
) |
|
{ |
|
auto_mutex M(wm); |
|
hide(); |
|
cur_rect = rectangle(pad,pad,pad-1,pad-1); |
|
win_rect = rectangle(); |
|
left_width = 0; |
|
middle_width = 0; |
|
items.clear(); |
|
item_enabled.clear(); |
|
left_rects.clear(); |
|
middle_rects.clear(); |
|
right_rects.clear(); |
|
line_rects.clear(); |
|
submenus.clear(); |
|
selected_item = 0; |
|
submenu_open = false; |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
show ( |
|
) |
|
{ |
|
auto_mutex M(wm); |
|
selected_item = submenus.size(); |
|
base_window::show(); |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
hide ( |
|
) |
|
{ |
|
auto_mutex M(wm); |
|
|
|
close_submenu(); |
|
selected_item = submenus.size(); |
|
base_window::hide(); |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
select_first_item ( |
|
) |
|
{ |
|
auto_mutex M(wm); |
|
close_submenu(); |
|
selected_item = items.size(); |
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
if ((items[i]->has_click_event() || submenus[i]) && item_enabled[i]) |
|
{ |
|
selected_item = i; |
|
break; |
|
} |
|
} |
|
invalidate_rectangle(cur_rect); |
|
} |
|
|
|
|
|
|
|
bool popup_menu:: |
|
forwarded_on_keydown ( |
|
unsigned long key, |
|
bool is_printable, |
|
unsigned long state |
|
) |
|
{ |
|
auto_mutex M(wm); |
|
|
|
if (items.size() == 0) |
|
return false; |
|
|
|
|
|
|
|
if (selected_item != submenus.size() && submenus[selected_item] != 0 && submenu_open) |
|
{ |
|
|
|
if (submenus[selected_item]->forwarded_on_keydown(key,is_printable,state) == true) |
|
return true; |
|
} |
|
|
|
if (key == KEY_UP) |
|
{ |
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
selected_item = (selected_item + items.size() - 1)%items.size(); |
|
|
|
if (item_enabled[selected_item] && (items[selected_item]->has_click_event() || submenus[selected_item]) ) |
|
break; |
|
} |
|
invalidate_rectangle(cur_rect); |
|
return true; |
|
} |
|
else if (key == KEY_DOWN) |
|
{ |
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
selected_item = (selected_item + 1)%items.size(); |
|
|
|
if (item_enabled[selected_item] && (items[selected_item]->has_click_event() || submenus[selected_item])) |
|
break; |
|
} |
|
invalidate_rectangle(cur_rect); |
|
return true; |
|
} |
|
else if (key == KEY_RIGHT && submenu_open == false && display_selected_submenu()) |
|
{ |
|
submenus[selected_item]->select_first_item(); |
|
return true; |
|
} |
|
else if (key == KEY_LEFT && selected_item != submenus.size() && |
|
submenus[selected_item] != 0 && submenu_open) |
|
{ |
|
close_submenu(); |
|
return true; |
|
} |
|
else if (key == '\n') |
|
{ |
|
if (selected_item != submenus.size() && (items[selected_item]->has_click_event() || submenus[selected_item])) |
|
{ |
|
const long idx = selected_item; |
|
|
|
if (submenus[idx] == 0) |
|
{ |
|
hide(); |
|
hide_handlers.reset(); |
|
while (hide_handlers.move_next()) |
|
hide_handlers.element()(); |
|
} |
|
else |
|
{ |
|
display_selected_submenu(); |
|
submenus[idx]->select_first_item(); |
|
} |
|
items[idx]->on_click(); |
|
return true; |
|
} |
|
} |
|
else if (is_printable) |
|
{ |
|
|
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
if (std::tolower(key) == std::tolower(items[i]->get_hot_key()) && |
|
(items[i]->has_click_event() || submenus[i]) && item_enabled[i] ) |
|
{ |
|
|
|
if (submenus[i] == 0) |
|
{ |
|
hide(); |
|
hide_handlers.reset(); |
|
while (hide_handlers.move_next()) |
|
hide_handlers.element()(); |
|
} |
|
else |
|
{ |
|
if (selected_item != items.size()) |
|
invalidate_rectangle(line_rects[selected_item]); |
|
|
|
selected_item = i; |
|
display_selected_submenu(); |
|
invalidate_rectangle(line_rects[i]); |
|
submenus[i]->select_first_item(); |
|
} |
|
items[i]->on_click(); |
|
} |
|
} |
|
|
|
|
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
on_submenu_hide ( |
|
) |
|
{ |
|
hide(); |
|
hide_handlers.reset(); |
|
while (hide_handlers.move_next()) |
|
hide_handlers.element()(); |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
on_window_resized( |
|
) |
|
{ |
|
invalidate_rectangle(win_rect); |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
on_mouse_up ( |
|
unsigned long btn, |
|
unsigned long, |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (cur_rect.contains(x,y) && btn == LEFT) |
|
{ |
|
|
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
if (line_rects[i].contains(x,y) && item_enabled[i] && items[i]->has_click_event()) |
|
{ |
|
|
|
if (submenus[i] == 0) |
|
{ |
|
hide(); |
|
hide_handlers.reset(); |
|
while (hide_handlers.move_next()) |
|
hide_handlers.element()(); |
|
} |
|
items[i]->on_click(); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
on_mouse_move ( |
|
unsigned long , |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (cur_rect.contains(x,y)) |
|
{ |
|
|
|
rectangle last_rect; |
|
if (selected_item != submenus.size()) |
|
{ |
|
last_rect = line_rects[selected_item]; |
|
} |
|
|
|
|
|
if (last_rect.contains(x,y) == false) |
|
{ |
|
if (selected_item != submenus.size()) |
|
{ |
|
invalidate_rectangle(last_rect); |
|
close_submenu(); |
|
selected_item = submenus.size(); |
|
} |
|
|
|
|
|
|
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
if (items[i]->has_click_event() || submenus[i]) |
|
{ |
|
if (line_rects[i].contains(x,y)) |
|
{ |
|
selected_item = i; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
if (selected_item != submenus.size()) |
|
{ |
|
display_selected_submenu(); |
|
invalidate_rectangle(line_rects[selected_item]); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
close_submenu ( |
|
) |
|
{ |
|
if (selected_item != submenus.size() && submenus[selected_item] && submenu_open) |
|
{ |
|
submenus[selected_item]->hide(); |
|
submenu_open = false; |
|
} |
|
} |
|
|
|
|
|
|
|
bool popup_menu:: |
|
display_selected_submenu ( |
|
) |
|
{ |
|
|
|
if (selected_item != submenus.size() && submenus[selected_item]) |
|
{ |
|
long wx, wy; |
|
get_pos(wx,wy); |
|
wx += line_rects[selected_item].right(); |
|
wy += line_rects[selected_item].top(); |
|
submenus[selected_item]->set_pos(wx+1,wy-2); |
|
submenus[selected_item]->show(); |
|
submenu_open = true; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
on_mouse_leave ( |
|
) |
|
{ |
|
if (selected_item != submenus.size()) |
|
{ |
|
|
|
if (submenus[selected_item] == 0) |
|
{ |
|
invalidate_rectangle(line_rects[selected_item]); |
|
selected_item = submenus.size(); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu:: |
|
paint ( |
|
const canvas& c |
|
) |
|
{ |
|
c.fill(200,200,200); |
|
draw_rectangle(c, win_rect); |
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
bool is_selected = false; |
|
if (selected_item != submenus.size() && i == selected_item && |
|
item_enabled[i]) |
|
is_selected = true; |
|
|
|
items[i]->draw_background(c,line_rects[i], item_enabled[i], is_selected); |
|
items[i]->draw_left(c,left_rects[i], item_enabled[i], is_selected); |
|
items[i]->draw_middle(c,middle_rects[i], item_enabled[i], is_selected); |
|
items[i]->draw_right(c,right_rects[i], item_enabled[i], is_selected); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zoomable_region:: |
|
zoomable_region ( |
|
drawable_window& w, |
|
unsigned long events |
|
) : |
|
drawable(w,MOUSE_CLICK | MOUSE_WHEEL | MOUSE_MOVE | events), |
|
min_scale(0.15), |
|
max_scale(1.0), |
|
zoom_increment_(0.90), |
|
vsb(w, scroll_bar::VERTICAL), |
|
hsb(w, scroll_bar::HORIZONTAL) |
|
{ |
|
scale = 1; |
|
mouse_drag_screen = false; |
|
style.reset(new scrollable_region_style_default()); |
|
|
|
hsb.set_scroll_handler(*this,&zoomable_region::on_h_scroll); |
|
vsb.set_scroll_handler(*this,&zoomable_region::on_v_scroll); |
|
} |
|
|
|
|
|
|
|
zoomable_region:: |
|
~zoomable_region() |
|
{ |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_pos ( |
|
long x, |
|
long y |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::set_pos(x,y); |
|
const long border_size = style->get_border_size(); |
|
vsb.set_pos(rect.right()-border_size+1-vsb.width(),rect.top()+border_size); |
|
hsb.set_pos(rect.left()+border_size,rect.bottom()-border_size+1-hsb.height()); |
|
|
|
display_rect_ = rectangle(rect.left()+border_size, |
|
rect.top()+border_size, |
|
rect.right()-border_size-vsb.width(), |
|
rect.bottom()-border_size-hsb.height()); |
|
|
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_zoom_increment ( |
|
double zi |
|
) |
|
{ |
|
DLIB_ASSERT(0.0 < zi && zi < 1.0, |
|
"\tvoid zoomable_region::set_zoom_increment(zi)" |
|
<< "\n\t the zoom increment must be between 0 and 1" |
|
<< "\n\t zi: " << zi |
|
<< "\n\t this: " << this |
|
); |
|
|
|
auto_mutex M(m); |
|
zoom_increment_ = zi; |
|
} |
|
|
|
|
|
|
|
double zoomable_region:: |
|
zoom_increment ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return zoom_increment_; |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_max_zoom_scale ( |
|
double ms |
|
) |
|
{ |
|
DLIB_ASSERT(ms > 0, |
|
"\tvoid zoomable_region::set_max_zoom_scale(ms)" |
|
<< "\n\t the max zoom scale must be greater than 0" |
|
<< "\n\t ms: " << ms |
|
<< "\n\t this: " << this |
|
); |
|
|
|
auto_mutex M(m); |
|
max_scale = ms; |
|
if (scale > ms) |
|
{ |
|
scale = max_scale; |
|
lr_point = gui_to_graph_space(point(display_rect_.right(),display_rect_.bottom())); |
|
redraw_graph(); |
|
} |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_min_zoom_scale ( |
|
double ms |
|
) |
|
{ |
|
DLIB_ASSERT(ms > 0, |
|
"\tvoid zoomable_region::set_min_zoom_scale(ms)" |
|
<< "\n\t the min zoom scale must be greater than 0" |
|
<< "\n\t ms: " << ms |
|
<< "\n\t this: " << this |
|
); |
|
|
|
auto_mutex M(m); |
|
min_scale = ms; |
|
|
|
if (scale < ms) |
|
{ |
|
scale = min_scale; |
|
} |
|
|
|
|
|
set_size(rect.width(), rect.height()); |
|
} |
|
|
|
|
|
|
|
double zoomable_region:: |
|
min_zoom_scale ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return min_scale; |
|
} |
|
|
|
|
|
|
|
double zoomable_region:: |
|
max_zoom_scale ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return max_scale; |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_size ( |
|
unsigned long width, |
|
unsigned long height |
|
) |
|
{ |
|
auto_mutex M(m); |
|
rectangle old(rect); |
|
const long border_size = style->get_border_size(); |
|
rect = resize_rect(rect,width,height); |
|
vsb.set_pos(rect.right()-border_size+1-vsb.width(), rect.top()+border_size); |
|
hsb.set_pos(rect.left()+border_size, rect.bottom()-border_size+1-hsb.height()); |
|
|
|
display_rect_ = rectangle(rect.left()+border_size, |
|
rect.top()+border_size, |
|
rect.right()-border_size-vsb.width(), |
|
rect.bottom()-border_size-hsb.height()); |
|
vsb.set_length(display_rect_.height()); |
|
hsb.set_length(display_rect_.width()); |
|
parent.invalidate_rectangle(rect+old); |
|
|
|
const double old_scale = scale; |
|
const vector<double,2> old_gr_orig(gr_orig); |
|
scale = min_scale; |
|
gr_orig = vector<double,2>(0,0); |
|
lr_point = gui_to_graph_space(point(display_rect_.right(),display_rect_.bottom())); |
|
scale = old_scale; |
|
|
|
|
|
|
|
const point rect_corner(display_rect_.left(), display_rect_.top()); |
|
adjust_origin(rect_corner, old_gr_orig); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
show ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::show(); |
|
hsb.show(); |
|
vsb.show(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
hide ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::hide(); |
|
hsb.hide(); |
|
vsb.hide(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
enable ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::enable(); |
|
hsb.enable(); |
|
vsb.enable(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
disable ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::disable(); |
|
hsb.disable(); |
|
vsb.disable(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_z_order ( |
|
long order |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::set_z_order(order); |
|
hsb.set_z_order(order); |
|
vsb.set_z_order(order); |
|
} |
|
|
|
|
|
|
|
point zoomable_region:: |
|
graph_to_gui_space ( |
|
const vector<double,2>& p |
|
) const |
|
{ |
|
const point rect_corner(display_rect_.left(), display_rect_.top()); |
|
return (p - gr_orig)*scale + rect_corner; |
|
} |
|
|
|
|
|
|
|
vector<double,2> zoomable_region:: |
|
gui_to_graph_space ( |
|
const point& p |
|
) const |
|
{ |
|
const point rect_corner(display_rect_.left(), display_rect_.top()); |
|
return (p - rect_corner)/scale + gr_orig; |
|
} |
|
|
|
|
|
|
|
point zoomable_region:: |
|
max_graph_point ( |
|
) const |
|
{ |
|
return lr_point; |
|
} |
|
|
|
|
|
|
|
rectangle zoomable_region:: |
|
display_rect ( |
|
) const |
|
{ |
|
return display_rect_; |
|
} |
|
|
|
|
|
|
|
double zoomable_region:: |
|
zoom_scale ( |
|
) const |
|
{ |
|
return scale; |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
set_zoom_scale ( |
|
double new_scale |
|
) |
|
{ |
|
|
|
|
|
if (!(min_scale <= new_scale && new_scale <= max_scale)) |
|
{ |
|
if (new_scale > max_scale) |
|
new_scale = max_scale; |
|
else |
|
new_scale = min_scale; |
|
} |
|
|
|
|
|
point center((display_rect_.left()+display_rect_.right())/2, (display_rect_.top()+display_rect_.bottom())/2); |
|
point graph_p(gui_to_graph_space(center)); |
|
scale = new_scale; |
|
adjust_origin(center, graph_p); |
|
redraw_graph(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
center_display_at_graph_point ( |
|
const vector<double,2>& p |
|
) |
|
{ |
|
|
|
point center((display_rect_.left()+display_rect_.right())/2, (display_rect_.top()+display_rect_.bottom())/2); |
|
adjust_origin(center, p); |
|
redraw_graph(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_wheel_down ( |
|
unsigned long |
|
) |
|
{ |
|
|
|
if (enabled && !hidden && scale > min_scale && display_rect_.contains(lastx,lasty)) |
|
{ |
|
point gui_p(lastx,lasty); |
|
point graph_p(gui_to_graph_space(gui_p)); |
|
const double old_scale = scale; |
|
scale *= zoom_increment_; |
|
if (scale < min_scale) |
|
scale = min_scale; |
|
redraw_graph(); |
|
adjust_origin(gui_p, graph_p); |
|
|
|
if (scale != old_scale) |
|
on_view_changed(); |
|
} |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_wheel_up ( |
|
unsigned long |
|
) |
|
{ |
|
|
|
if (enabled && !hidden && scale < max_scale && display_rect_.contains(lastx,lasty)) |
|
{ |
|
point gui_p(lastx,lasty); |
|
point graph_p(gui_to_graph_space(gui_p)); |
|
const double old_scale = scale; |
|
scale /= zoom_increment_; |
|
if (scale > max_scale) |
|
scale = max_scale; |
|
redraw_graph(); |
|
adjust_origin(gui_p, graph_p); |
|
|
|
if (scale != old_scale) |
|
on_view_changed(); |
|
} |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_mouse_move ( |
|
unsigned long state, |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (enabled && !hidden && mouse_drag_screen) |
|
{ |
|
adjust_origin(point(x,y), drag_screen_point); |
|
redraw_graph(); |
|
on_view_changed(); |
|
} |
|
|
|
|
|
if ((state & base_window::LEFT) == 0) |
|
{ |
|
mouse_drag_screen = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_mouse_up ( |
|
unsigned long , |
|
unsigned long , |
|
long , |
|
long |
|
) |
|
{ |
|
mouse_drag_screen = false; |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_mouse_down ( |
|
unsigned long btn, |
|
unsigned long , |
|
long x, |
|
long y, |
|
bool |
|
) |
|
{ |
|
if (enabled && !hidden && display_rect_.contains(x,y) && btn == base_window::LEFT) |
|
{ |
|
mouse_drag_screen = true; |
|
drag_screen_point = gui_to_graph_space(point(x,y)); |
|
} |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
draw ( |
|
const canvas& c |
|
) const |
|
{ |
|
style->draw_scrollable_region_border(c, rect, enabled); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_h_scroll ( |
|
) |
|
{ |
|
gr_orig.x() = hsb.slider_pos(); |
|
redraw_graph(); |
|
|
|
on_view_changed(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
on_v_scroll ( |
|
) |
|
{ |
|
gr_orig.y() = vsb.slider_pos(); |
|
redraw_graph(); |
|
|
|
on_view_changed(); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
redraw_graph ( |
|
) |
|
{ |
|
parent.invalidate_rectangle(display_rect_); |
|
} |
|
|
|
|
|
|
|
void zoomable_region:: |
|
adjust_origin ( |
|
const point& gui_p, |
|
const vector<double,2>& graph_p |
|
) |
|
{ |
|
const point rect_corner(display_rect_.left(), display_rect_.top()); |
|
const dlib::vector<double,2> v(gui_p - rect_corner); |
|
gr_orig = graph_p - v/scale; |
|
|
|
|
|
|
|
if (gr_orig.x() < 0) |
|
gr_orig.x() = 0; |
|
if (gr_orig.y() < 0) |
|
gr_orig.y() = 0; |
|
|
|
|
|
point lr_rect_corner(display_rect_.right(), display_rect_.bottom()); |
|
point p = graph_to_gui_space(lr_point); |
|
vector<double,2> lr_rect_corner_graph_space(gui_to_graph_space(lr_rect_corner)); |
|
vector<double,2> delta(lr_point - lr_rect_corner_graph_space); |
|
if (lr_rect_corner.x() > p.x()) |
|
{ |
|
gr_orig.x() += delta.x(); |
|
} |
|
|
|
if (lr_rect_corner.y() > p.y()) |
|
{ |
|
gr_orig.y() += delta.y(); |
|
} |
|
|
|
|
|
const vector<double,2> ul_rect_corner_graph_space(gui_to_graph_space(rect_corner)); |
|
lr_rect_corner_graph_space = gui_to_graph_space(lr_rect_corner); |
|
|
|
|
|
hsb.set_max_slider_pos((unsigned long)std::max(lr_point.x()-(lr_rect_corner_graph_space.x()-ul_rect_corner_graph_space.x()),0.0)); |
|
vsb.set_max_slider_pos((unsigned long)std::max(lr_point.y()-(lr_rect_corner_graph_space.y()-ul_rect_corner_graph_space.y()),0.0)); |
|
|
|
hsb.set_slider_pos(static_cast<long>(ul_rect_corner_graph_space.x())); |
|
vsb.set_slider_pos(static_cast<long>(ul_rect_corner_graph_space.y())); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scrollable_region:: |
|
scrollable_region ( |
|
drawable_window& w, |
|
unsigned long events |
|
) : |
|
drawable(w, MOUSE_WHEEL|events|MOUSE_CLICK|MOUSE_MOVE), |
|
hsb(w,scroll_bar::HORIZONTAL), |
|
vsb(w,scroll_bar::VERTICAL), |
|
hscroll_bar_inc(1), |
|
vscroll_bar_inc(1), |
|
h_wheel_scroll_bar_inc(1), |
|
v_wheel_scroll_bar_inc(1), |
|
mouse_drag_enabled_(false), |
|
user_is_dragging_mouse(false) |
|
{ |
|
style.reset(new scrollable_region_style_default()); |
|
|
|
hsb.set_scroll_handler(*this,&scrollable_region::on_h_scroll); |
|
vsb.set_scroll_handler(*this,&scrollable_region::on_v_scroll); |
|
} |
|
|
|
|
|
|
|
scrollable_region:: |
|
~scrollable_region ( |
|
) |
|
{ |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
show ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::show(); |
|
if (need_h_scroll()) |
|
hsb.show(); |
|
if (need_v_scroll()) |
|
vsb.show(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
hide ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::hide(); |
|
hsb.hide(); |
|
vsb.hide(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
enable ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::enable(); |
|
hsb.enable(); |
|
vsb.enable(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
disable ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::disable(); |
|
hsb.disable(); |
|
vsb.disable(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_z_order ( |
|
long order |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::set_z_order(order); |
|
hsb.set_z_order(order); |
|
vsb.set_z_order(order); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_size ( |
|
unsigned long width, |
|
unsigned long height |
|
) |
|
{ |
|
auto_mutex M(m); |
|
rectangle old(rect); |
|
rect = resize_rect(rect,width,height); |
|
vsb.set_pos(rect.right()-style->get_border_size()-vsb.width()+1, rect.top()+style->get_border_size()); |
|
hsb.set_pos(rect.left()+style->get_border_size(), rect.bottom()-style->get_border_size()-hsb.height()+1); |
|
|
|
|
|
if (need_h_scroll() && need_v_scroll()) |
|
{ |
|
|
|
if (!hidden) |
|
{ |
|
vsb.show(); |
|
hsb.show(); |
|
} |
|
display_rect_ = rectangle( rect.left()+style->get_border_size(), |
|
rect.top()+style->get_border_size(), |
|
rect.right()-style->get_border_size()-vsb.width(), |
|
rect.bottom()-style->get_border_size()-hsb.height()); |
|
|
|
|
|
unsigned long hdelta = total_rect_.width()-display_rect_.width(); |
|
unsigned long vdelta = total_rect_.height()-display_rect_.height(); |
|
hdelta = (hdelta+hscroll_bar_inc-1)/hscroll_bar_inc; |
|
vdelta = (vdelta+vscroll_bar_inc-1)/vscroll_bar_inc; |
|
|
|
hsb.set_max_slider_pos(hdelta); |
|
vsb.set_max_slider_pos(vdelta); |
|
|
|
vsb.set_jump_size((display_rect_.height()+vscroll_bar_inc-1)/vscroll_bar_inc/2+1); |
|
hsb.set_jump_size((display_rect_.width()+hscroll_bar_inc-1)/hscroll_bar_inc/2+1); |
|
} |
|
else if (need_h_scroll()) |
|
{ |
|
|
|
if (!hidden) |
|
{ |
|
hsb.show(); |
|
vsb.hide(); |
|
} |
|
display_rect_ = rectangle( rect.left()+style->get_border_size(), |
|
rect.top()+style->get_border_size(), |
|
rect.right()-style->get_border_size(), |
|
rect.bottom()-style->get_border_size()-hsb.height()); |
|
|
|
|
|
unsigned long hdelta = total_rect_.width()-display_rect_.width(); |
|
hdelta = (hdelta+hscroll_bar_inc-1)/hscroll_bar_inc; |
|
|
|
hsb.set_max_slider_pos(hdelta); |
|
vsb.set_max_slider_pos(0); |
|
|
|
hsb.set_jump_size((display_rect_.width()+hscroll_bar_inc-1)/hscroll_bar_inc/2+1); |
|
} |
|
else if (need_v_scroll()) |
|
{ |
|
|
|
if (!hidden) |
|
{ |
|
hsb.hide(); |
|
vsb.show(); |
|
} |
|
display_rect_ = rectangle( rect.left()+style->get_border_size(), |
|
rect.top()+style->get_border_size(), |
|
rect.right()-style->get_border_size()-vsb.width(), |
|
rect.bottom()-style->get_border_size()); |
|
|
|
unsigned long vdelta = total_rect_.height()-display_rect_.height(); |
|
vdelta = (vdelta+vscroll_bar_inc-1)/vscroll_bar_inc; |
|
|
|
hsb.set_max_slider_pos(0); |
|
vsb.set_max_slider_pos(vdelta); |
|
|
|
vsb.set_jump_size((display_rect_.height()+vscroll_bar_inc-1)/vscroll_bar_inc/2+1); |
|
} |
|
else |
|
{ |
|
|
|
if (!hidden) |
|
{ |
|
hsb.hide(); |
|
vsb.hide(); |
|
} |
|
display_rect_ = rectangle( rect.left()+style->get_border_size(), |
|
rect.top()+style->get_border_size(), |
|
rect.right()-style->get_border_size(), |
|
rect.bottom()-style->get_border_size()); |
|
|
|
hsb.set_max_slider_pos(0); |
|
vsb.set_max_slider_pos(0); |
|
} |
|
|
|
vsb.set_length(display_rect_.height()); |
|
hsb.set_length(display_rect_.width()); |
|
|
|
|
|
on_h_scroll(); |
|
on_v_scroll(); |
|
|
|
parent.invalidate_rectangle(rect+old); |
|
} |
|
|
|
|
|
|
|
unsigned long scrollable_region:: |
|
horizontal_mouse_wheel_scroll_increment ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return h_wheel_scroll_bar_inc; |
|
} |
|
|
|
|
|
|
|
unsigned long scrollable_region:: |
|
vertical_mouse_wheel_scroll_increment ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return v_wheel_scroll_bar_inc; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_horizontal_mouse_wheel_scroll_increment ( |
|
unsigned long inc |
|
) |
|
{ |
|
auto_mutex M(m); |
|
h_wheel_scroll_bar_inc = inc; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_vertical_mouse_wheel_scroll_increment ( |
|
unsigned long inc |
|
) |
|
{ |
|
auto_mutex M(m); |
|
v_wheel_scroll_bar_inc = inc; |
|
} |
|
|
|
|
|
|
|
unsigned long scrollable_region:: |
|
horizontal_scroll_increment ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return hscroll_bar_inc; |
|
} |
|
|
|
|
|
|
|
unsigned long scrollable_region:: |
|
vertical_scroll_increment ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return vscroll_bar_inc; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_horizontal_scroll_increment ( |
|
unsigned long inc |
|
) |
|
{ |
|
auto_mutex M(m); |
|
hscroll_bar_inc = inc; |
|
|
|
set_size(rect.width(),rect.height()); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_vertical_scroll_increment ( |
|
unsigned long inc |
|
) |
|
{ |
|
auto_mutex M(m); |
|
vscroll_bar_inc = inc; |
|
|
|
set_size(rect.width(),rect.height()); |
|
} |
|
|
|
|
|
|
|
long scrollable_region:: |
|
horizontal_scroll_pos ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return hsb.slider_pos(); |
|
} |
|
|
|
|
|
|
|
long scrollable_region:: |
|
vertical_scroll_pos ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return vsb.slider_pos(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_horizontal_scroll_pos ( |
|
long pos |
|
) |
|
{ |
|
auto_mutex M(m); |
|
|
|
hsb.set_slider_pos(pos); |
|
on_h_scroll(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_vertical_scroll_pos ( |
|
long pos |
|
) |
|
{ |
|
auto_mutex M(m); |
|
|
|
vsb.set_slider_pos(pos); |
|
on_v_scroll(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_pos ( |
|
long x, |
|
long y |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::set_pos(x,y); |
|
vsb.set_pos(rect.right()-style->get_border_size()-vsb.width()+1, rect.top()+style->get_border_size()); |
|
hsb.set_pos(rect.left()+style->get_border_size(), rect.bottom()-style->get_border_size()-hsb.height()+1); |
|
|
|
const long delta_x = total_rect_.left() - display_rect_.left(); |
|
const long delta_y = total_rect_.top() - display_rect_.top(); |
|
|
|
display_rect_ = move_rect(display_rect_, rect.left()+style->get_border_size(), rect.top()+style->get_border_size()); |
|
|
|
total_rect_ = move_rect(total_rect_, display_rect_.left()+delta_x, display_rect_.top()+delta_y); |
|
} |
|
|
|
|
|
|
|
bool scrollable_region:: |
|
mouse_drag_enabled ( |
|
) const |
|
{ |
|
auto_mutex M(m); |
|
return mouse_drag_enabled_; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
enable_mouse_drag ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
mouse_drag_enabled_ = true; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
disable_mouse_drag ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
mouse_drag_enabled_ = false; |
|
} |
|
|
|
|
|
|
|
const rectangle& scrollable_region:: |
|
display_rect ( |
|
) const |
|
{ |
|
return display_rect_; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
set_total_rect_size ( |
|
unsigned long width, |
|
unsigned long height |
|
) |
|
{ |
|
DLIB_ASSERT((width > 0 && height > 0) || (width == 0 && height == 0), |
|
"\tvoid scrollable_region::set_total_rect_size(width,height)" |
|
<< "\n\twidth and height must be > 0 or both == 0" |
|
<< "\n\twidth: " << width |
|
<< "\n\theight: " << height |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
total_rect_ = move_rect(rectangle(width,height), |
|
display_rect_.left()-static_cast<long>(hsb.slider_pos()), |
|
display_rect_.top()-static_cast<long>(vsb.slider_pos())); |
|
|
|
|
|
set_size(rect.width(),rect.height()); |
|
} |
|
|
|
|
|
|
|
const rectangle& scrollable_region:: |
|
total_rect ( |
|
) const |
|
{ |
|
return total_rect_; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
scroll_to_rect ( |
|
const rectangle& r_ |
|
) |
|
{ |
|
const rectangle r(total_rect_.intersect(r_)); |
|
const rectangle old(total_rect_); |
|
|
|
if (r.left() < display_rect_.left()) |
|
{ |
|
long distance = (r.left()-total_rect_.left())/hscroll_bar_inc; |
|
hsb.set_slider_pos(distance); |
|
} |
|
else if (r.right() > display_rect_.right()) |
|
{ |
|
long distance = (r.right()-total_rect_.left()-display_rect_.width()+hscroll_bar_inc)/hscroll_bar_inc; |
|
hsb.set_slider_pos(distance); |
|
} |
|
|
|
|
|
if (r.top() < display_rect_.top()) |
|
{ |
|
long distance = (r.top()-total_rect_.top())/vscroll_bar_inc; |
|
vsb.set_slider_pos(distance); |
|
} |
|
else if (r.bottom() > display_rect_.bottom()) |
|
{ |
|
long distance = (r.bottom()-total_rect_.top()-display_rect_.height()+vscroll_bar_inc)/vscroll_bar_inc; |
|
vsb.set_slider_pos(distance); |
|
} |
|
|
|
|
|
|
|
total_rect_ = move_rect(total_rect_, |
|
display_rect_.left()-hscroll_bar_inc*hsb.slider_pos(), |
|
display_rect_.top()-vscroll_bar_inc*vsb.slider_pos()); |
|
|
|
|
|
if (total_rect_ != old) |
|
{ |
|
parent.invalidate_rectangle(display_rect_); |
|
} |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_wheel_down ( |
|
unsigned long |
|
) |
|
{ |
|
if (rect.contains(lastx,lasty) && enabled && !hidden) |
|
{ |
|
if (need_v_scroll()) |
|
{ |
|
long pos = vsb.slider_pos(); |
|
vsb.set_slider_pos(pos+(long)v_wheel_scroll_bar_inc); |
|
on_v_scroll(); |
|
} |
|
else if (need_h_scroll()) |
|
{ |
|
long pos = hsb.slider_pos(); |
|
hsb.set_slider_pos(pos+(long)h_wheel_scroll_bar_inc); |
|
on_h_scroll(); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_mouse_move ( |
|
unsigned long state, |
|
long x, |
|
long y |
|
) |
|
{ |
|
if (enabled && !hidden && user_is_dragging_mouse && state==base_window::LEFT) |
|
{ |
|
point current_delta = point(x,y) - point(total_rect().left(), total_rect().top()); |
|
rectangle new_rect(translate_rect(display_rect(), drag_origin - current_delta)); |
|
new_rect = centered_rect(new_rect, new_rect.width()-hscroll_bar_inc, new_rect.height()-vscroll_bar_inc); |
|
scroll_to_rect(new_rect); |
|
on_view_changed(); |
|
} |
|
else |
|
{ |
|
user_is_dragging_mouse = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_mouse_down ( |
|
unsigned long btn, |
|
unsigned long , |
|
long x, |
|
long y, |
|
bool |
|
) |
|
{ |
|
if (mouse_drag_enabled_ && enabled && !hidden && display_rect().contains(x,y) && (btn==base_window::LEFT)) |
|
{ |
|
drag_origin = point(x,y) - point(total_rect().left(), total_rect().top()); |
|
user_is_dragging_mouse = true; |
|
} |
|
else |
|
{ |
|
user_is_dragging_mouse = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_mouse_up ( |
|
unsigned long , |
|
unsigned long , |
|
long , |
|
long |
|
) |
|
{ |
|
user_is_dragging_mouse = false; |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_wheel_up ( |
|
unsigned long |
|
) |
|
{ |
|
if (rect.contains(lastx,lasty) && enabled && !hidden) |
|
{ |
|
if (need_v_scroll()) |
|
{ |
|
long pos = vsb.slider_pos(); |
|
vsb.set_slider_pos(pos-(long)v_wheel_scroll_bar_inc); |
|
on_v_scroll(); |
|
} |
|
else if (need_h_scroll()) |
|
{ |
|
long pos = hsb.slider_pos(); |
|
hsb.set_slider_pos(pos-(long)h_wheel_scroll_bar_inc); |
|
on_h_scroll(); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
draw ( |
|
const canvas& c |
|
) const |
|
{ |
|
style->draw_scrollable_region_border(c, rect, enabled); |
|
} |
|
|
|
|
|
|
|
bool scrollable_region:: |
|
need_h_scroll ( |
|
) const |
|
{ |
|
if (total_rect_.width() > rect.width()-style->get_border_size()*2) |
|
{ |
|
return true; |
|
} |
|
else |
|
{ |
|
|
|
|
|
if (total_rect_.height() > rect.height()-style->get_border_size()*2 && |
|
total_rect_.width() > rect.width()-style->get_border_size()*2-vsb.width()) |
|
return true; |
|
else |
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
bool scrollable_region:: |
|
need_v_scroll ( |
|
) const |
|
{ |
|
if (total_rect_.height() > rect.height()-style->get_border_size()*2) |
|
{ |
|
return true; |
|
} |
|
else |
|
{ |
|
|
|
|
|
if (total_rect_.width() > rect.width()-style->get_border_size()*2 && |
|
total_rect_.height() > rect.height()-style->get_border_size()*2-hsb.height()) |
|
return true; |
|
else |
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_h_scroll ( |
|
) |
|
{ |
|
total_rect_ = move_rect(total_rect_, display_rect_.left()-hscroll_bar_inc*hsb.slider_pos(), total_rect_.top()); |
|
parent.invalidate_rectangle(display_rect_); |
|
if (events_are_enabled()) |
|
on_view_changed(); |
|
} |
|
|
|
|
|
|
|
void scrollable_region:: |
|
on_v_scroll ( |
|
) |
|
{ |
|
total_rect_ = move_rect(total_rect_, total_rect_.left(), display_rect_.top()-vscroll_bar_inc*vsb.slider_pos()); |
|
parent.invalidate_rectangle(display_rect_); |
|
if (events_are_enabled()) |
|
on_view_changed(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
popup_menu_region:: |
|
popup_menu_region( |
|
drawable_window& w |
|
) : |
|
drawable(w,MOUSE_CLICK | KEYBOARD_EVENTS | FOCUS_EVENTS | WINDOW_MOVED), |
|
popup_menu_shown(false) |
|
{ |
|
|
|
menu_.set_on_hide_handler(*this,&popup_menu_region::on_menu_becomes_hidden); |
|
enable_events(); |
|
} |
|
|
|
|
|
|
|
popup_menu_region:: |
|
~popup_menu_region( |
|
) |
|
{ |
|
disable_events(); |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
set_size ( |
|
unsigned long width, |
|
unsigned long height |
|
) |
|
{ |
|
auto_mutex M(m); |
|
rect = resize_rect(rect,width,height); |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
set_rect ( |
|
const rectangle& new_rect |
|
) |
|
{ |
|
auto_mutex M(m); |
|
rect = new_rect; |
|
} |
|
|
|
|
|
|
|
popup_menu& popup_menu_region:: |
|
menu ( |
|
) |
|
{ |
|
return menu_; |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
hide ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::hide(); |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
disable ( |
|
) |
|
{ |
|
auto_mutex M(m); |
|
drawable::disable(); |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
on_keydown ( |
|
unsigned long key, |
|
bool is_printable, |
|
unsigned long state |
|
) |
|
{ |
|
if (enabled && !hidden && popup_menu_shown) |
|
{ |
|
menu_.forwarded_on_keydown(key, is_printable, state); |
|
} |
|
else if (popup_menu_shown) |
|
{ |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
|
|
if (key == (unsigned long)base_window::KEY_ESC) |
|
{ |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
on_menu_becomes_hidden ( |
|
) |
|
{ |
|
popup_menu_shown = false; |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
on_focus_lost ( |
|
) |
|
{ |
|
if (popup_menu_shown) |
|
{ |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
on_focus_gained ( |
|
) |
|
{ |
|
if (popup_menu_shown) |
|
{ |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
on_window_moved( |
|
) |
|
{ |
|
if (popup_menu_shown) |
|
{ |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
on_mouse_down ( |
|
unsigned long btn, |
|
unsigned long , |
|
long x, |
|
long y, |
|
bool |
|
) |
|
{ |
|
if (enabled && !hidden && rect.contains(x,y) && btn == base_window::RIGHT) |
|
{ |
|
long orig_x, orig_y; |
|
parent.get_pos(orig_x, orig_y); |
|
menu_.set_pos(orig_x+x, orig_y+y); |
|
menu_.show(); |
|
popup_menu_shown = true; |
|
} |
|
else if (popup_menu_shown) |
|
{ |
|
menu_.hide(); |
|
popup_menu_shown = false; |
|
} |
|
} |
|
|
|
|
|
|
|
void popup_menu_region:: |
|
draw ( |
|
const canvas& |
|
) const |
|
{ |
|
} |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
|