Commit 53ecad68 authored by Davis King's avatar Davis King

Added the text_box gui widget.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402795
parent 84bb80cc
......@@ -435,26 +435,26 @@ namespace dlib
}
// find the start of the given line
typename string::size_type last_pos = pos;
for (typename string::size_type i = first; i <= last && line != 0; ++i)
{
if (str[i] == '\n')
{
--line;
pos += (i - last_pos);
last_pos = pos;
pos = i + 1;
}
}
// now str[pos] == the first character of the start of the line
// that contains the cursor.
const typename string::size_type start_of_line = pos;
long cur_x = f.left_overflow();
// set the current cursor position to where the mouse clicked
while (pos <= last)
{
if (x <= cur_x)
if (x <= cur_x || str[pos] == '\n')
break;
if (is_combining_char(str[pos]) == false &&
......@@ -467,8 +467,10 @@ namespace dlib
if (x <= cur_x)
{
if (pos != first)
if (pos != start_of_line)
{
// we might actually be closer to the previous character
// so check for that and if so then jump us back one.
const long width = f[str[pos-1]].width();
if (x < cur_x - width/2)
--pos;
......
......@@ -903,6 +903,93 @@ namespace dlib
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_box styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void text_box_style_default::
draw_text_box (
const canvas& c,
const rectangle& display_rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const rectangle& cursor_rect,
const rgb_pixel& text_color,
const rgb_pixel& bg_color,
const bool has_focus,
const bool cursor_visible,
const long highlight_start,
const long highlight_end
) const
{
rectangle area = display_rect.intersect(c);
if (enabled)
{
// first fill our area with the bg_color
fill_rect(c, area,bg_color);
}
else
{
// first fill our area with gray
fill_rect(c, area,rgb_pixel(212,208,200));
}
if (enabled)
mfont.draw_string(c,text_rect,text,text_color, 0, ustring::npos, area);
else
mfont.draw_string(c,text_rect,text,rgb_pixel(128,128,128), 0, ustring::npos, area);
// now draw the highlight if there is any
if (highlight_start <= highlight_end && enabled)
{
const rectangle first_pos = mfont.compute_cursor_rect(text_rect, text, highlight_start);
const rectangle last_pos = mfont.compute_cursor_rect(text_rect, text, highlight_end+1);
const rgb_alpha_pixel color(10, 30, 106, 90);
// if the highlighted text is all on one line
if (first_pos.top() == last_pos.top())
{
fill_rect(c, (first_pos + last_pos).intersect(display_rect), color);
}
else
{
const rectangle min_boundary(display_rect.left()+4, display_rect.top()+4,
display_rect.right()-4, display_rect.bottom()-4);
const rectangle boundary( display_rect.intersect(text_rect) + min_boundary);
rectangle first_row, last_row, middle_rows;
first_row += first_pos;
first_row += point(boundary.right(), first_pos.top());
last_row += last_pos;
last_row += point(boundary.left(), last_pos.bottom());
middle_rows.left() = boundary.left();
middle_rows.right() = boundary.right();
middle_rows.top() = first_row.bottom()+1;
middle_rows.bottom() = last_row.top()-1;
fill_rect(c, first_row.intersect(display_rect), color);
fill_rect(c, middle_rows, color);
fill_rect(c, last_row.intersect(display_rect), color);
}
}
// now draw the cursor if we need to
if (cursor_visible && has_focus && enabled)
{
draw_line(c, point(cursor_rect.left(), cursor_rect.top()),point(cursor_rect.left(), cursor_rect.bottom()), 0, area);
}
}
// ----------------------------------------------------------------------------------------
}
......
......@@ -661,6 +661,82 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_box styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class text_box_style
{
public:
text_box_style()
{
}
virtual ~text_box_style()
{}
virtual unsigned long get_padding (
const font& mfont
) const = 0;
virtual void draw_text_box (
const canvas& c,
const rectangle& display_rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const rectangle& cursor_rect,
const rgb_pixel& text_color,
const rgb_pixel& bg_color,
const bool has_focus,
const bool cursor_visible,
const long highlight_start,
const long highlight_end
) const = 0;
};
// ----------------------------------------------------------------------------------------
class text_box_style_default : public text_box_style
{
public:
text_box_style_default()
{
}
scrollable_region_style_default get_scrollable_region_style (
) const { return scrollable_region_style_default(); }
virtual ~text_box_style_default()
{}
virtual unsigned long get_padding (
const font& mfont
) const { return 1; }
virtual void draw_text_box (
const canvas& c,
const rectangle& display_rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const rectangle& cursor_rect,
const rgb_pixel& text_color,
const rgb_pixel& bg_color,
const bool has_focus,
const bool cursor_visible,
const long highlight_start,
const long highlight_end
) const;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_field styles
......
......@@ -51,7 +51,7 @@ namespace dlib
- rect == the get_rect() that defines where the button is
ensures
- returns a rectangle that should be invalidated whenever a button
needs to redraw itself. (If you wanted your button style to
needs to redraw itself. (e.g. If you wanted your button style to
draw outside the button then you could return a larger rectangle)
!*/
......@@ -489,6 +489,97 @@ namespace dlib
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_box styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class text_box_style
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an abstract class that defines the interface a
text_box style object must implement.
Note that derived classes must be copyable via
their copy constructors.
!*/
public:
virtual ~text_field_style() {}
scrollable_region_style_type get_scrollable_region_style (
) const;
/*!
ensures
- returns the style of scrollable_region to use for the
text_box.
!*/
virtual unsigned long get_padding (
const font& mfont
) const = 0;
/*!
requires
- the mutex drawable::m is locked
ensures
- returns the number of pixels that separate the text in the text_box
from the edge of the text_box widget itself.
!*/
virtual void draw_text_box (
const canvas& c,
const rectangle& display_rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const rectangle& cursor_rect,
const rgb_pixel& text_color,
const rgb_pixel& bg_color,
const bool has_focus,
const bool cursor_visible,
const long highlight_start,
const long highlight_end
) const = 0;
/*!
requires
- the mutex drawable::m is locked
- c == the canvas to draw on
- enabled and mfont are the variables defined in the protected section
- text_rect == the rectangle in which we should draw the given text
of the drawable class.
- display_rect == the rectangle returned by scrollable_region::display_rect()
- text == the current text in the text_box
- cursor_rect == A rectangle of width 1 that represents the current
position of the cursor on the screen.
- text_color == the color of the text to be drawn
- bg_color == the background color of the text field
- has_focus == true if this text field has keyboard input focus
- cursor_visible == true if the cursor should be drawn
- if (highlight_start <= highlight_end) then
- text[highlight_start] though text[highlight_end] should be
highlighted
ensures
- draws the text_box on the canvas c at the location given by text_rect.
(Note that the scroll bars and borders are drawn by the scrollable_region
and therefore the style returned by get_scrollable_region_style()
controls how those appear)
- doesn't draw anything outside display_rect
!*/
};
// ----------------------------------------------------------------------------------------
class text_box_style_default : public text_box_style
{
public:
/*!
This is the default style for text_box objects.
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// list_box styles
......@@ -604,7 +695,7 @@ namespace dlib
/*!
WHAT THIS OBJECT REPRESENTS
This is an abstract class that defines the interface a
list_box style object must implement.
text_field style object must implement.
Note that derived classes must be copyable via
their copy constructors.
......@@ -647,7 +738,7 @@ namespace dlib
- rect, enabled, and mfont are the variables defined in the protected section
of the drawable class.
- text == the current text in the text_field
- text_rect == the rectanle in which we should draw the given text
- text_rect == the rectangle in which we should draw the given text
- 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.
......@@ -661,7 +752,7 @@ namespace dlib
- text[highlight_start] though text[highlight_end] should be
highlighted
ensures
- draws the button on the canvas c at the location given by rect.
- draws the text_field on the canvas c at the location given by rect.
!*/
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -623,6 +623,195 @@ namespace dlib
text_field& operator=(text_field&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class text_box
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class text_box : public drawable
{
/*!
INITIAL VALUE
- text() == ""
- The text color will be black.
- width() == 100
- height() == 100
WHAT THIS OBJECT REPRESENTS
This object represents a simple multi-line text input box.
!*/
public:
text_box(
drawable_window& w
);
/*!
ensures
- #*this is properly initialized
- #*this has been added to window w
- #parent_window() == w
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~text_box(
);
/*!
ensures
- 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 text_box_style
ensures
- this text_box object will draw itself using the given
text box style
!*/
void set_text (const std::wstring& text);
void set_text (const dlib::ustring& text);
void set_text (
const std::string& text
);
/*!
ensures
- #text() == text
throws
- std::bad_alloc
!*/
const std::wstring wtext () const;
const dlib::ustring utext () const;
const std::string text (
) const;
/*!
ensures
- returns the text of this text_box
throws
- std::bad_alloc
!*/
void set_size (
unsigned long width,
unsigned long height
);
/*!
ensures
- #width() == width_
- #height() == height_
- #top() == top()
- #left() == left()
- i.e. The location of the upper left corner of this widget stays the
same but its width and height are modified
!*/
void set_text_color (
const rgb_pixel color
);
/*!
ensures
- #text_color() == color
!*/
const rgb_pixel text_color (
) const;
/*!
ensures
- returns the color used to draw the text in this widget
!*/
void set_background_color (
const rgb_pixel color
);
/*!
ensures
- #background_color() == color
!*/
const rgb_pixel background_color (
) const;
/*!
ensures
- returns the color used to fill in the background of this widget
!*/
template <
typename T
>
void set_text_modified_handler (
T& object,
void (T::*event_handler)()
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- the event_handler function is called on object when the text
in this text_box is modified by the user.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_enter_key_handler (
T& object,
void (T::*event_handler)()
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- the event_handler function is called on object when this text box
has input focus and the user hits the enter key on their keyboard.
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_focus_lost_handler (
T& object,
void (T::*event_handler)()
);
/*!
requires
- event_handler is a valid pointer to a member function in T
ensures
- the event_handler function is called on object when this object
loses input focus due to the user clicking outside the text box
- any previous calls to this function are overridden by this new call.
(i.e. you can only have one event handler associated with this
event at a time)
throws
- std::bad_alloc
!*/
private:
// restricted functions
text_box(text_box&); // copy constructor
text_box& operator=(text_box&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// class check_box
......
......@@ -236,6 +236,11 @@ class win : public drawable_window
else
tf.disable();
if (sb_enabled.is_checked())
tb.enable();
else
tb.disable();
}
void cb_sb_shown (
......@@ -428,6 +433,7 @@ public:
tab_label(*this),
tabs(*this),
tf(*this),
tb(*this),
mbar(*this)
{
bool use_bdf_fonts = false;
......@@ -635,6 +641,13 @@ public:
tf.set_enter_key_handler(*this,&win::on_enter_key);
tf.set_focus_lost_handler(*this,&win::on_tf_focus_lost);
tb.set_pos(250,400);
tb.set_text("initial test\nstring");
tb.set_size(300,300);
tb.set_text_color(rgb_pixel(255,0,0));
tb.set_enter_key_handler(*this,&win::on_enter_key);
tb.set_focus_lost_handler(*this,&win::on_tf_focus_lost);
button_count = 0;
count = 0;
......@@ -646,7 +659,7 @@ public:
b.set_main_font(f);
set_size(800,500);
set_size(815,730);
nrect.wrap_around(
cbox.get_rect() +
......@@ -660,7 +673,10 @@ public:
save_file_box(*this,&win::on_open_file);
if (use_bdf_fonts)
{
tf.set_main_font(f);
tb.set_main_font(f);
}
if (use_bdf_fonts)
tabs.set_main_font(f);
......@@ -676,7 +692,7 @@ private:
void on_tf_focus_lost()
{
cout << "text field lost focus" << endl;
cout << "text field/box lost focus" << endl;
}
......@@ -766,6 +782,7 @@ private:
label tab_label;
tabbed_display tabs;
text_field tf;
text_box tb;
menu_bar mbar;
popup_menu submenu;
......
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