Commit e1838b1e authored by Davis King's avatar Davis King

Added a user settable style to the text_field widget.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402605
parent 5d23ce5f
......@@ -794,6 +794,115 @@ namespace dlib
draw_button_up(c, rect);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_field styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
unsigned long text_field_style_default::
get_padding (
const font& mfont
) const
{
return mfont.height()-mfont.ascender();
}
// ----------------------------------------------------------------------------------------
void text_field_style_default::
draw_text_field (
const canvas& c,
const rectangle& rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const unsigned long cursor_x,
const unsigned long text_pos,
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 = 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,text_pos);
else
mfont.draw_string(c,text_rect,text,rgb_pixel(128,128,128),text_pos);
// now draw the edge of the text_field
draw_sunken_rectangle(c, rect);
if (highlight_start <= highlight_end && enabled)
{
rectangle highlight_rect = text_rect;
unsigned long left_pad = 0, right_pad = mfont.left_overflow();
long i;
for (i = text_pos; i <= highlight_end; ++i)
{
if (i == highlight_start)
left_pad = right_pad;
right_pad += mfont[text[i]].width();
}
highlight_rect.set_left(text_rect.left()+left_pad);
highlight_rect.set_right(text_rect.left()+right_pad);
// highlight the highlight_rect area
highlight_rect = highlight_rect.intersect(c);
for (long row = highlight_rect.top(); row <= highlight_rect.bottom(); ++row)
{
for (long col = highlight_rect.left(); col <= highlight_rect.right(); ++col)
{
canvas::pixel& pixel = c[row-c.top()][col-c.left()];
if (pixel.red == 255 && pixel.green == 255 && pixel.blue == 255)
{
// this is a background (and white) pixel so set it to a dark
// blueish color.
pixel.red = 10;
pixel.green = 36;
pixel.blue = 106;
}
else
{
// this should be a pixel that is part of a letter so set it to white
pixel.red = 255;
pixel.green = 255;
pixel.blue = 255;
}
}
}
}
// now draw the cursor if we need to
if (cursor_visible && has_focus && enabled)
{
const unsigned long top = rect.top()+3;
const unsigned long bottom = rect.bottom()-3;
draw_line(c, point(rect.left()+cursor_x,top),point(rect.left()+cursor_x,bottom));
}
}
// ----------------------------------------------------------------------------------------
}
......
......@@ -661,6 +661,81 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_field styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class text_field_style
{
public:
text_field_style()
{
}
virtual ~text_field_style()
{}
virtual unsigned long get_padding (
const font& mfont
) const = 0;
virtual void draw_text_field (
const canvas& c,
const rectangle& rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const unsigned long cursor_x,
const unsigned long text_pos,
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_field_style_default : public text_field_style
{
public:
text_field_style_default()
{
}
virtual ~text_field_style_default()
{}
virtual unsigned long get_padding (
const font& mfont
) const;
virtual void draw_text_field (
const canvas& c,
const rectangle& rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const unsigned long cursor_x,
const unsigned long text_pos,
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;
};
// ----------------------------------------------------------------------------------------
}
......
......@@ -593,6 +593,89 @@ namespace dlib
!*/
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// text_field styles
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class text_field_style
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an abstract class that defines the interface a
list_box style object must implement.
Note that derived classes must be copyable via
their copy constructors.
!*/
public:
virtual ~text_field_style() {}
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_field
from the edge of the text_field widget itself.
!*/
virtual void draw_text_field (
const canvas& c,
const rectangle& rect,
const rectangle& text_rect,
const bool enabled,
const font& mfont,
const ustring& text,
const unsigned long cursor_x,
const unsigned long text_pos,
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
- 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
- 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.
- text_pos == the index of the first letter in text that appears in
this text field.
- 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 button on the canvas c at the location given by rect.
!*/
};
// ----------------------------------------------------------------------------------------
class text_field_style_default : public text_field_style
{
public:
/*!
This is the default style for text_field objects.
!*/
};
// ----------------------------------------------------------------------------------------
}
......
......@@ -424,9 +424,9 @@ namespace dlib
unsigned long vertical_pad = (rect.height() - mfont->height())/2+1;
rectangle text_rect;
text_rect.set_left(rect.left()+(mfont->height()-mfont->ascender()));
text_rect.set_left(rect.left()+style->get_padding(*mfont));
text_rect.set_top(rect.top()+vertical_pad);
text_rect.set_right(rect.right()-(mfont->height()-mfont->ascender()));
text_rect.set_right(rect.right()-style->get_padding(*mfont));
text_rect.set_bottom(text_rect.top()+mfont->height()-1);
return text_rect;
}
......@@ -468,7 +468,7 @@ namespace dlib
mfont = f;
// adjust the height of this text field so that it is appropriate for the current
// font size
rect.set_bottom(rect.top() + mfont->height()+ (mfont->height()-mfont->ascender())*2);
rect.set_bottom(rect.top() + mfont->height()+ (style->get_padding(*mfont))*2);
set_text(text_);
}
......@@ -483,79 +483,9 @@ namespace dlib
if (area.is_empty())
return;
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));
}
const rectangle text_rect = get_text_rect();
if (enabled)
mfont->draw_string(c,text_rect,text_,text_color_,text_pos);
else
mfont->draw_string(c,text_rect,text_,rgb_pixel(128,128,128),text_pos);
// now draw the edge of the text_field
draw_sunken_rectangle(c, rect);
if (highlight_start <= highlight_end && enabled)
{
rectangle highlight_rect = text_rect;
unsigned long left_pad = 0, right_pad = mfont->left_overflow();
long i;
for (i = text_pos; i <= highlight_end; ++i)
{
if (i == highlight_start)
left_pad = right_pad;
right_pad += (*mfont)[text_[i]].width();
}
highlight_rect.set_left(text_rect.left()+left_pad);
highlight_rect.set_right(text_rect.left()+right_pad);
// highlight the highlight_rect area
highlight_rect = highlight_rect.intersect(c);
for (long row = highlight_rect.top(); row <= highlight_rect.bottom(); ++row)
{
for (long col = highlight_rect.left(); col <= highlight_rect.right(); ++col)
{
canvas::pixel& pixel = c[row-c.top()][col-c.left()];
if (pixel.red == 255 && pixel.green == 255 && pixel.blue == 255)
{
// this is a background (and white) pixel so set it to a dark
// blueish color.
pixel.red = 10;
pixel.green = 36;
pixel.blue = 106;
}
else
{
// this should be a pixel that is part of a letter so set it to white
pixel.red = 255;
pixel.green = 255;
pixel.blue = 255;
}
}
}
}
// now draw the cursor if we need to
if (cursor_visible && has_focus && enabled && !hidden)
{
const unsigned long top = rect.top()+3;
const unsigned long bottom = rect.bottom()-3;
draw_line(c, point(rect.left()+cursor_x,top),point(rect.left()+cursor_x,bottom));
}
style->draw_text_field(c,rect,get_text_rect(), enabled, *mfont, text_, cursor_x, text_pos,
text_color_, bg_color_, has_focus, cursor_visible, highlight_start,
highlight_end);
}
// ----------------------------------------------------------------------------------------
......@@ -633,7 +563,7 @@ namespace dlib
unsigned long width
)
{
if (width < 10)
if (width < style->get_padding(*mfont)*2)
return;
m.lock();
......@@ -1140,7 +1070,7 @@ namespace dlib
mfont->compute_size(text_,text_width,height,text_pos);
unsigned long width;
unsigned long new_x = (mfont->height()-mfont->ascender());
unsigned long new_x = style->get_padding(*mfont);
if (static_cast<long>(cursor_pos)-1 >= static_cast<long>(text_pos))
{
mfont->compute_size(text_,width,height,text_pos,cursor_pos-1);
......@@ -1156,7 +1086,7 @@ namespace dlib
unsigned long width;
mfont->compute_size(text_,width,height,text_pos,pos-1);
unsigned long new_x = (mfont->height()-mfont->ascender()) +
unsigned long new_x = style->get_padding(*mfont) +
width - mfont->right_overflow();
// move the text to the left if necessary
......
......@@ -361,9 +361,10 @@ namespace dlib
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());
style.reset(new text_field_style_default());
rect.set_bottom(mfont->height()+ (style->get_padding(*mfont))*2);
rect.set_right((style->get_padding(*mfont))*2);
cursor_x = style->get_padding(*mfont);
enable_events();
t.set_delay_time(500);
......@@ -377,6 +378,19 @@ namespace dlib
t.stop_and_wait();
}
template <
typename style_type
>
void set_style (
const style_type& style_
)
{
auto_mutex M(m);
style.reset(new style_type(style_));
// call this just so that this widget redraws itself with the new style
set_main_font(mfont);
}
void set_text (
const std::string& text_
);
......@@ -543,6 +557,7 @@ namespace dlib
member_function_pointer<>::kernel_1a_c enter_key_handler;
member_function_pointer<>::kernel_1a_c focus_lost_handler;
scoped_ptr<text_field_style> style;
timer<text_field>::kernel_2a t;
......
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