improve all widgets for bground effects

This commit is contained in:
Jinhao 2017-04-11 07:06:43 +08:00
parent 198bac505f
commit 6cbf721f9d
24 changed files with 479 additions and 284 deletions

View File

@ -1,7 +1,7 @@
/*
* A Drawer Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -126,8 +126,7 @@ namespace nana
void* draw(std::function<void(paint::graphics&)> &&, bool diehard);
void erase(void* diehard);
private:
void _m_effect_bground(bool before);
bool _m_lazy_decleared() const;
void _m_effect_bground_subsequent();
method_state& _m_mth_state(int pos);
template<typename Arg, typename Mfptr>
@ -140,8 +139,6 @@ namespace nana
if (realizer && (method_state::not_overrided != mth_state))
{
_m_effect_bground(true);
if (method_state::pending == mth_state)
{
(realizer->*mfptr)(graphics, arg);
@ -154,8 +151,7 @@ namespace nana
else
(realizer->*mfptr)(graphics, arg);
if (_m_lazy_decleared())
_m_effect_bground(false);
_m_effect_bground_subsequent();
}
}
public:

View File

@ -54,6 +54,8 @@ namespace API
effects::edge_nimbus effects_edge_nimbus(window);
void effects_bground(window, const effects::bground_factory_interface&, double fade_rate);
void effects_bground(std::initializer_list<window> wdgs, const effects::bground_factory_interface&, double fade_rate);
bground_mode effects_bground_mode(window);
void effects_bground_remove(window);
@ -96,6 +98,9 @@ namespace API
void enable_space_click(window, bool enable);
bool copy_transparent_background(window, paint::graphics&);
bool copy_transparent_background(window, const rectangle& src_r, paint::graphics&, const point& dst_pt);
/// Refreshs a widget surface
/*
* This function will copy the drawer surface into system window after the event process finished.
@ -195,6 +200,8 @@ namespace API
bool is_destroying(window); ///< Determines whether a window is destroying
void enable_dropfiles(window, bool);
bool is_transparent_background(window);
/// \brief Retrieves the native window of a Nana.GUI window.
///
/// The native window type is platform-dependent. Under Microsoft Windows, a conversion can be employed between

View File

@ -1,7 +1,7 @@
/**
* A Panel Implementation
* Nana C++ Library(http://www.nanaro.org)
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -57,7 +57,7 @@ namespace nana
bool transparent() const
{
return (bground_mode::basic == API::effects_bground_mode(*this));
return API::is_transparent_background(*this);
}
void transparent(bool tr)

View File

@ -139,7 +139,7 @@ namespace nana{ namespace widgets
void clear_undo(); ///< same with undo_max_steps(0)
unsigned line_height() const;
unsigned screen_lines() const;
unsigned screen_lines(bool completed_line = false) const;
bool getline(std::size_t pos, ::std::wstring&) const;
void text(std::wstring, bool end_caret);
@ -153,7 +153,7 @@ namespace nana{ namespace widgets
bool move_caret(const upoint& pos, bool reset = false);
void move_caret_end(bool update);
void reset_caret_pixels() const;
void reset_caret();
void reset_caret(bool stay_in_view = false);
void show_caret(bool isshow);
bool selected() const;
@ -204,10 +204,12 @@ namespace nana{ namespace widgets
bool focus_changed(const arg_focus&);
bool mouse_enter(bool entering);
bool mouse_move(bool left_button, const point& screen_pos);
bool mouse_pressed(const arg_mouse& arg);
void mouse_pressed(const arg_mouse& arg);
skeletons::textbase<char_type>& textbase();
const skeletons::textbase<char_type>& textbase() const;
bool try_refresh();
private:
std::vector<upoint> _m_render_text(const ::nana::color& text_color);
void _m_pre_calc_lines(std::size_t line_off, std::size_t lines);
@ -223,7 +225,7 @@ namespace nana{ namespace widgets
bool _m_accepts(char_type) const;
::nana::color _m_bgcolor() const;
void _m_reset_content_size();
void _m_reset_content_size(bool calc_lines = false);
void _m_reset();
::nana::upoint _m_put(::std::wstring);
::nana::upoint _m_erase_select();
@ -258,6 +260,7 @@ namespace nana{ namespace widgets
unsigned _m_pixels_by_char(const ::std::wstring&, ::std::size_t pos) const;
void _m_handle_move_key(const arg_keyboard& arg);
unsigned _m_width_px(bool exclude_vs) const;
void _m_draw_border();
private:
struct implementation;

View File

@ -73,8 +73,8 @@ namespace nana
typedef compset_interface::comp_attribute_t comp_attribute_t;
virtual ~renderer_interface() = default;
virtual void set_color(const nana::color& bgcolor, const nana::color& fgcolor) = 0;
virtual void begin_paint(::nana::widget&) = 0;
virtual void bground(graph_reference, const compset_interface *) const = 0;
virtual void expander(graph_reference, const compset_interface *) const = 0;
virtual void crook(graph_reference, const compset_interface *) const = 0;

View File

@ -30,7 +30,8 @@ namespace detail
nana::pixel_color_t fade_color_intermedia(pixel_color_t fgcolor, const unsigned char* fade_table);
nana::pixel_color_t fade_color_by_intermedia(pixel_color_t bgcolor, nana::pixel_color_t fgcolor_intermedia, const unsigned char* const fade_table);
void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t, double fade_rate);
//dw color = dw color * fade_rate + bdcolor * (1 - fade_rate)
void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t bdcolor, double fade_rate);
nana::size raw_text_extent_size(drawable_type, const wchar_t*, std::size_t len);
nana::size text_extent_size(drawable_type, const wchar_t*, std::size_t len);

View File

@ -1,7 +1,7 @@
/*
* A Drawer Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -297,9 +297,8 @@ namespace nana
if (data_impl_->realizer && !data_impl_->refreshing)
{
data_impl_->refreshing = true;
_m_effect_bground(true);
data_impl_->realizer->refresh(graphics);
_m_effect_bground(false);
_m_effect_bground_subsequent();
graphics.flush();
data_impl_->refreshing = false;
}
@ -372,27 +371,20 @@ namespace nana
}
}
void drawer::_m_effect_bground(bool before)
void drawer::_m_effect_bground_subsequent()
{
auto & effect = data_impl_->window_handle->effect;
for (auto * dw : data_impl_->draws)
dw->draw(graphics);
auto & effect = data_impl_->window_handle->effect;
if (effect.bground)
{
if (before)
{
if (effect.bground_fade_rate < 0.01)
data_impl_->window_handle->other.glass_buffer.paste(graphics, 0, 0);
}
else if (effect.bground_fade_rate >= 0.01)
if (effect.bground_fade_rate >= 0.01)
data_impl_->window_handle->other.glass_buffer.blend(::nana::rectangle{ data_impl_->window_handle->other.glass_buffer.size() }, graphics, nana::point(), effect.bground_fade_rate);
}
}
bool drawer::_m_lazy_decleared() const
{
return (basic_window::update_state::refreshed == data_impl_->window_handle->other.upd_state);
}
drawer::method_state& drawer::_m_mth_state(int pos)

View File

@ -155,6 +155,12 @@ namespace API
}
}
void effects_bground(std::initializer_list<window> wdgs, const effects::bground_factory_interface& factory, double fade_rate)
{
for (auto wd : wdgs)
effects_bground(wd, factory, fade_rate);
}
bground_mode effects_bground_mode(window wd)
{
auto const iwd = reinterpret_cast<basic_window*>(wd);
@ -329,6 +335,32 @@ namespace API
iwd->flags.space_click_enabled = enable;
}
bool copy_transparent_background(window wd, paint::graphics& graph)
{
auto & buf = reinterpret_cast<basic_window*>(wd)->other.glass_buffer;
internal_scope_guard lock;
if (bground_mode::basic != API::effects_bground_mode(wd))
return false;
buf.paste(rectangle{ buf.size() }, graph, 0, 0);
return true;
}
bool copy_transparent_background(window wd, const rectangle& src_r, paint::graphics& graph, const point& dst_pt)
{
auto iwd = reinterpret_cast<basic_window*>(wd);
internal_scope_guard lock;
if (bground_mode::basic != API::effects_bground_mode(wd))
return false;
iwd->other.glass_buffer.paste(src_r, graph, dst_pt.x, dst_pt.y);
return true;
}
void lazy_refresh()
{
restrict::bedrock.thread_context_lazy_refresh();
@ -469,6 +501,11 @@ namespace API
}
}
bool is_transparent_background(window wd)
{
return (bground_mode::basic == effects_bground_mode(wd));
}
native_window_type root(window wd)
{
internal_scope_guard lock;

View File

@ -155,7 +155,7 @@ namespace nana{ namespace drawerbase
if (false == cite_.draw(graph, attr_.bgcolor, attr_.fgcolor, ::nana::rectangle{ graph.size() }, e_state))
{
if (bground_mode::basic != API::effects_bground_mode(wdg_->handle()))
if (!API::is_transparent_background(*wdg_))
{
_m_draw_background(graph);
_m_draw_border(graph);
@ -492,7 +492,7 @@ namespace nana{ namespace drawerbase
bool button::transparent() const
{
return (bground_mode::basic == API::effects_bground_mode(*this));
return API::is_transparent_background(*this);
}
button& button::edge_effects(bool enable)

View File

@ -1,7 +1,7 @@
/*
* A CheckBox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -55,7 +55,7 @@ namespace nana{ namespace drawerbase
auto wdg = impl_->widget_ptr;
//draw background
if (bground_mode::basic != API::effects_bground_mode(*wdg))
if (!API::dev::copy_transparent_background(*wdg, graph))
graph.rectangle(true, wdg->bgcolor());
//draw title
@ -193,7 +193,7 @@ namespace nana{ namespace drawerbase
bool checkbox::transparent() const
{
return (bground_mode::basic == API::effects_bground_mode(*this));
return API::is_transparent_background(*this);
}
//end class checkbox

View File

@ -193,6 +193,7 @@ namespace nana
if(r.width > place) r.width -= place;
}
editor_->text_area(r);
editor_->render(state_.focused);
}
widgets::skeletons::text_editor * editor() const
@ -233,6 +234,12 @@ namespace nana
}
graph.gradual_rectangle(::nana::rectangle(graph.size()).pare_off(pare_off_px), clr_from, clr_to, true);
if (API::is_transparent_background(this->widget_ptr()->handle()))
{
paint::graphics trns_graph{ graph.size() };
if (API::dev::copy_transparent_background(this->widget_ptr()->handle(), trns_graph))
trns_graph.blend(rectangle{ trns_graph.size() }, graph, { 0, 0 }, 0.5);
}
};
}
else
@ -362,7 +369,6 @@ namespace nana
if(editor_)
{
text_area(widget_->size());
editor_->render(state_.focused);
}
_m_draw_push_button(enb);
_m_draw_image();
@ -397,7 +403,8 @@ namespace nana
if (calc_where(*graph_, pos.x, pos.y))
state_.button_state = element_state::normal;
editor_->text(::nana::charset(items_[index]->item_text, ::nana::unicode::utf8), false);
editor_->text(to_wstring(items_[index]->item_text), false);
editor_->try_refresh();
_m_draw_push_button(widget_->enabled());
_m_draw_image();
@ -511,9 +518,10 @@ namespace nana
facade<element::button> button;
button.draw(*graph_, ::nana::color{ 3, 65, 140 }, colors::white, r, estate);
facade<element::arrow> arrow("solid_triangle");
facade<element::arrow> arrow;// ("solid_triangle");
arrow.direction(::nana::direction::south);
r.x += 4;
r.y += (r.height / 2) - 7;
r.width = r.height = 16;
arrow.draw(*graph_, {}, colors::white, r, element_state::normal);
@ -664,7 +672,6 @@ namespace nana
void trigger::mouse_down(graph_reference, const arg_mouse& arg)
{
//drawer_->set_mouse_press(true);
drawer_->set_button_state(element_state::pressed, false);
if(drawer_->widget_ptr()->enabled())
{
@ -762,12 +769,14 @@ namespace nana
if (call_other_keys)
drawer_->editor()->respond_key(arg);
drawer_->editor()->try_refresh();
API::dev::lazy_refresh();
}
void trigger::key_char(graph_reference, const arg_keyboard& arg)
{
if (drawer_->editor()->respond_char(arg))
drawer_->editor()->respond_char(arg);
if (drawer_->editor()->try_refresh())
API::dev::lazy_refresh();
}
//end class trigger

View File

@ -784,7 +784,7 @@ namespace nana
if(nullptr == impl_->wd) return;
window wd = impl_->wd->handle();
if(bground_mode::basic != API::effects_bground_mode(wd))
if (!API::dev::copy_transparent_background(wd, graph))
graph.rectangle(true, API::bgcolor(wd));
impl_->renderer.render(graph, API::fgcolor(wd), impl_->text_align, impl_->text_align_v);
@ -830,7 +830,7 @@ namespace nana
bool label::transparent() const throw()
{
return (bground_mode::basic == API::effects_bground_mode(*this));
return API::is_transparent_background(*this);
}
label& label::format(bool f)

View File

@ -3168,7 +3168,10 @@ namespace nana
if (column_r.x < r.right())
{
column_r.width = (r.right() - column_r.x);
graph.rectangle(column_r, true, essence_->scheme_ptr->header_bgcolor);
if(API::dev::copy_transparent_background(essence_->listbox_ptr->handle(), column_r, graph, column_r.position()))
graph.blend(column_r, essence_->scheme_ptr->header_bgcolor, 0.8);
else
graph.rectangle(column_r, true, essence_->scheme_ptr->header_bgcolor);
}
const int y = r.bottom() - 1;
@ -3229,7 +3232,15 @@ namespace nana
case item_state::floated: bgcolor = essence_->scheme_ptr->header_floated.get_color(); break;
}
graph.gradual_rectangle(column_r, bgcolor.blend(colors::white, 0.9), bgcolor.blend(colors::black, 0.9), true);
if(API::dev::copy_transparent_background(essence_->listbox_ptr->handle(), column_r, graph, column_r.position()))
{
paint::graphics grad_graph{column_r.dimension()};
grad_graph.gradual_rectangle(rectangle{column_r.dimension()}, bgcolor.blend(colors::white, 0.1), bgcolor.blend(colors::black, 0.1), true);
grad_graph.blend(rectangle{column_r.dimension()}, graph, column_r.position(), 0.3);
}
else
graph.gradual_rectangle(column_r, bgcolor.blend(colors::white, 0.9), bgcolor.blend(colors::black, 0.9), true);
paint::aligner text_aligner{ graph, column.alignment, column.alignment };
@ -3329,23 +3340,28 @@ namespace nana
essence_->graph->palette(false, bgcolor);
auto const header_w = essence_->header.pixels();
auto const item_height_px = essence_->item_height();
auto origin = essence_->content_view->origin();
if (header_w < origin.x + rect.width)
essence_->graph->rectangle(rectangle{ point{ rect.x + static_cast<int>(header_w) - origin.x, rect.y },
size{ rect.width + origin.x - header_w, rect.height } }, true);
{
rectangle r{ point{ rect.x + static_cast<int>(header_w)-origin.x, rect.y },
size{ rect.width + origin.x - header_w, rect.height } };
if (!API::dev::copy_transparent_background(essence_->listbox_ptr->handle(), r, *essence_->graph, r.position()))
essence_->graph->rectangle(r, true);
}
es_lister & lister = essence_->lister;
auto & ptr_where = essence_->pointer_where;
int item_top = rect.y - (origin.y % essence_->item_height());
int item_top = rect.y - (origin.y % item_height_px);
auto first_disp = essence_->first_display();
// The first display is empty when the listbox is empty.
if (!first_disp.empty())
{
index_pair hoverred_pos(npos, npos); //the hoverred item.
//if where == lister || where == checker, 'second' indicates the offset to the relative display-order pos of the scroll offset_y which stands for the first item to be displayed in lister.
@ -3397,7 +3413,7 @@ namespace nana
(hoverred_pos == idx ? item_state::highlighted : item_state::normal)
);
item_top += essence_->item_height();
item_top += item_height_px;
}
++i_categ;
@ -3414,7 +3430,7 @@ namespace nana
_m_draw_categ(*i_categ, rect.x - origin.x, item_top, txtoff, header_w, rect, bgcolor,
(hoverred_pos.is_category() && (idx.cat == hoverred_pos.cat) ? item_state::highlighted : item_state::normal)
);
item_top += essence_->item_height();
item_top += item_height_px;
if (false == i_categ->expand)
continue;
@ -3431,7 +3447,7 @@ namespace nana
(idx == hoverred_pos ? item_state::highlighted : item_state::normal)
);
item_top += essence_->item_height();
item_top += item_height_px;
if (item_top >= rect.bottom())
break;
@ -3443,7 +3459,11 @@ namespace nana
}
if (item_top < rect.bottom())
essence_->graph->rectangle(rectangle{ rect.x, item_top, rect.width, static_cast<unsigned>(rect.bottom() - item_top) }, true, bgcolor);
{
rectangle bground_r{ rect.x, item_top, rect.width, static_cast<unsigned>(rect.bottom() - item_top) };
if (!API::dev::copy_transparent_background(essence_->listbox_ptr->handle(), bground_r, *essence_->graph, bground_r.position()))
essence_->graph->rectangle(bground_r, true, bgcolor);
}
//Draw mouse selection
//Check if the mouse selection box is present.
@ -3459,26 +3479,24 @@ namespace nana
};
paint::graphics box_graph{ box_size };
box_graph.rectangle(true, essence_->scheme_ptr->selection_box.get_color().blend(colors::white, 0.6));
box_graph.rectangle(true, essence_->scheme_ptr->selection_box.get_color().blend(colors::white, 0.4));
box_graph.rectangle(false, essence_->scheme_ptr->selection_box.get_color());
box_graph.blend(rectangle{ box_size }, *essence_->graph, essence_->coordinate_cast(box_position, false), 0.5);
}
}
private:
void _m_draw_categ(const category_t& categ, int x, int y, int txtoff, unsigned width, const nana::rectangle& r, nana::color bgcolor, item_state state) const
void _m_draw_categ(const category_t& categ, int x, int y, int txtoff, unsigned width, const nana::rectangle& r, nana::color bgcolor, item_state state)
{
const bool sel = categ.selected();
if (sel && (categ.expand == false))
bgcolor = static_cast<color_rgb>(0xD5EFFC);
if (state == item_state::highlighted)
bgcolor = bgcolor.blend(static_cast<color_rgb>(0x99defd), 0.8);
const auto item_height = essence_->item_height();
rectangle bground_r{ x, y, width, item_height };
auto graph = essence_->graph;
graph->rectangle(rectangle{ x, y, width, item_height }, true, bgcolor);
item_data item;
item.flags.selected = categ.selected();
this->_m_draw_item_bground(bground_r, bgcolor, {}, state, item);
color txt_color{ static_cast<color_rgb>(0x3399) };
@ -3506,10 +3524,53 @@ namespace nana
}
//Draw selecting inner rectangle
if (sel && (categ.expand == false))
if (item.flags.selected && (categ.expand == false))
_m_draw_item_border(r.x, y, (std::min)(r.width, width - essence_->content_view->origin().x));
}
color _m_draw_item_bground(const rectangle& bground_r, color bgcolor, color cell_color, item_state state, const item_data& item)
{
auto graph = essence_->graph;
auto const is_transparent = API::dev::copy_transparent_background(essence_->listbox_ptr->handle(), bground_r, *graph, bground_r.position());
if (is_transparent)
bgcolor = color{};
if (item.flags.selected)
{
bgcolor = essence_->scheme_ptr->item_selected;
if (!cell_color.invisible())
bgcolor = bgcolor.blend(cell_color, 0.5);
}
else if (!cell_color.invisible())
bgcolor = cell_color;
else if (!item.bgcolor.invisible())
bgcolor = item.bgcolor;
if (item_state::highlighted == state)
{
if (item.flags.selected)
bgcolor = bgcolor.blend(colors::black, 0.9);
else
bgcolor = bgcolor.blend(essence_->scheme_ptr->item_highlighted, 0.3);
}
if (is_transparent)
{
if(!bgcolor.invisible())
graph->blend(bground_r, bgcolor, 0.2);
}
else
{
graph->rectangle(bground_r, true, bgcolor);
}
return bgcolor;
}
/// Draws an item
void _m_draw_item(const category_t& cat,
const index_pair& item_pos,
@ -3534,28 +3595,16 @@ namespace nana
auto & cells = (cat.model_ptr ? model_cells : *item.cells);
if (item.flags.selected) // fetch the "def" colors
bgcolor = essence_->scheme_ptr->item_selected;
else if (!item.bgcolor.invisible())
bgcolor = item.bgcolor;
if(!item.fgcolor.invisible())
fgcolor = item.fgcolor;
if (item_state::highlighted == state) // and blend it if "highlighted"
{
if (item.flags.selected)
bgcolor = bgcolor.blend(colors::black, 0.98); // or "selected"
else
bgcolor = bgcolor.blend(essence_->scheme_ptr->item_highlighted, 0.7);/// \todo create a parametre for amount of blend
}
const unsigned show_w = (std::min)(content_r.width, width - essence_->content_view->origin().x);
auto graph = essence_->graph;
//draw the background for the whole item
graph->rectangle(rectangle{ content_r.x, y, show_w, essence_->item_height() }, true, bgcolor);
rectangle bground_r{ content_r.x, y, show_w, essence_->item_height() };
auto const state_bgcolor = this->_m_draw_item_bground(bground_r, bgcolor, {}, state, item);
int column_x = x;
@ -3563,7 +3612,6 @@ namespace nana
{
const auto column_pos = seqs[display_order];
const auto & col = essence_->header.at(column_pos); // deduce the corresponding header which is in a kind of dislay order
auto it_bgcolor = bgcolor;
if (col.width_px > essence_->scheme_ptr->text_margin)
{
@ -3664,7 +3712,8 @@ namespace nana
}
}
auto cell_txtcolor = fgcolor;
auto col_bgcolor = bgcolor;
auto col_fgcolor = fgcolor;
if (cells.size() > column_pos) // process only if the cell is visible
{
@ -3673,24 +3722,13 @@ namespace nana
if (m_cell.custom_format) // adapt to costum format if need
{
if (!item.bgcolor.invisible())
cell_txtcolor = m_cell.custom_format->bgcolor;
if (item.flags.selected) // fetch the "def" colors
it_bgcolor = essence_->scheme_ptr->item_selected;
col_fgcolor = m_cell.custom_format->fgcolor;
cell_txtcolor = m_cell.custom_format->fgcolor;
if (item_state::highlighted == state) // and blend it if "highlighted"
{
if (item.flags.selected)
it_bgcolor = it_bgcolor.blend(colors::black, 0.98); // or "selected"
else
it_bgcolor = it_bgcolor.blend(essence_->scheme_ptr->item_highlighted, 0.7); /// \todo create a parametre for amount of blend
}
graph->rectangle(rectangle{ column_x, y, col.width_px, essence_->item_height() }, true, it_bgcolor);
bground_r = rectangle{ column_x, y, col.width_px, essence_->item_height() };
col_bgcolor = this->_m_draw_item_bground(bground_r, bgcolor, m_cell.custom_format->bgcolor, state, item);
}
else
col_bgcolor = state_bgcolor;
if (draw_column)
{
@ -3702,7 +3740,7 @@ namespace nana
else if (align::right == col.alignment)
text_margin_right = essence_->scheme_ptr->text_margin;
graph->palette(true, cell_txtcolor);
graph->palette(true, col_fgcolor);
text_aligner.draw(m_cell.text, { column_x + content_pos, y + txtoff }, col.width_px - content_pos - text_margin_right);
}
}
@ -3710,7 +3748,7 @@ namespace nana
if (0 == display_order)
{
if (essence_->checkable)
crook_renderer_.draw(*graph, it_bgcolor, cell_txtcolor, essence_->checkarea(column_x, y), estate);
crook_renderer_.draw(*graph, col_bgcolor, col_fgcolor, essence_->checkarea(column_x, y), estate);
if (item.img)
item.img.stretch(rectangle{ item.img.size() }, *graph, img_r);
}
@ -4196,16 +4234,6 @@ namespace nana
bool do_expand = (lister.expand(item_pos.cat) == false);
lister.expand(item_pos.cat, do_expand);
if(false == do_expand)
{
auto last = lister.advance(lister.last(), -static_cast<int>(essence_->count_of_exposed(false)));
if (!last.empty())
{
auto px = lister.distance(lister.first(), last) * essence_->item_height();
essence_->content_view->change_position(static_cast<int>(px), true, false);
}
}
essence_->calc_content_size(false);
essence_->content_view->sync(false);
refresh(graph);
@ -4727,20 +4755,6 @@ namespace nana
return to_utf8(cat_->text);
}
bool assign_colors_for_last(essence* ess, category_t* cat)
{
auto wd = ess->lister.wd_ptr();
if (wd && !API::empty_window(wd->handle()))
{
auto & m = cat->items.back();
m.bgcolor = wd->bgcolor();
m.fgcolor = wd->fgcolor();
return true;
}
return false;
}
void cat_proxy::push_back(std::string s)
{
internal_scope_guard lock;
@ -4766,8 +4780,7 @@ namespace nana
else
cat_->items.emplace_back(std::move(s));
if (assign_colors_for_last(ess_, cat_))
ess_->update();
ess_->update();
}
//Behavior of a container
@ -4947,8 +4960,6 @@ namespace nana
}
cat_->sorted.push_back(cat_->items.size() - 1);
assign_colors_for_last(ess_, cat_);
}
void cat_proxy::_m_try_append_model(const const_virtual_pointer& dptr)
@ -4964,7 +4975,6 @@ namespace nana
cat_->sorted.push_back(cat_->items.size());
cat_->items.emplace_back();
assign_colors_for_last(ess_, cat_);
}
void cat_proxy::_m_cat_by_pos() noexcept

View File

@ -1,6 +1,6 @@
/*
* A Panel Implementation
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -31,7 +31,7 @@ namespace nana
void drawer::refresh(graph_reference graph)
{
if(bground_mode::basic != API::effects_bground_mode(window_))
if (!API::dev::copy_transparent_background(window_, graph))
graph.rectangle(true, API::bgcolor(window_));
}
//end class drawer

View File

@ -194,9 +194,9 @@ namespace nana
{
auto graph = impl_->graph_ptr;
if (graph && (bground_mode::basic != API::effects_bground_mode(*impl_->wdg_ptr)))
if (graph && (!API::dev::copy_transparent_background(*impl_->wdg_ptr, *graph)))
{
if (w < graph->size().width || h < graph->size().height /* .width ??? */ || impl_->backimg.image.alpha())
if (w < graph->size().width || h < graph->size().height || impl_->backimg.image.alpha())
{
auto & bground = impl_->gradual_bground;
if (bground.gradual_from.invisible() || bground.gradual_to.invisible())
@ -320,7 +320,7 @@ namespace nana
bool picture::transparent() const
{
return (bground_mode::basic == API::effects_bground_mode(*this));
return API::is_transparent_background(*this);
}
//end class picture
}//end namespace nana

View File

@ -209,7 +209,10 @@ namespace nana {
vert.value(origin.y);
}
else
{
vert.close();
origin.y = 0;
}
if (imd_area.height != disp_area.height)
{
@ -233,7 +236,10 @@ namespace nana {
horz.value(origin.x);
}
else
{
horz.close();
origin.x = 0;
}
this->enable_update = true;
}
@ -308,7 +314,31 @@ namespace nana {
void content_view::content_size(const size& sz, bool try_update)
{
if (sz.height < impl_->content_size.height)
{
if (impl_->origin.y + impl_->disp_area.height > sz.height)
{
if (impl_->disp_area.height > sz.height)
impl_->origin.y = 0;
else
impl_->origin.y = sz.height - impl_->disp_area.height;
}
}
if (sz.width < impl_->content_size.width)
{
if (impl_->origin.x + impl_->disp_area.width > sz.width)
{
if (impl_->disp_area.width > sz.width)
impl_->origin.x = 0;
else
impl_->origin.x = sz.width - impl_->disp_area.width;
}
}
impl_->content_size = sz;
impl_->size_changed(try_update);
}

View File

@ -388,6 +388,13 @@ namespace nana{ namespace widgets
const keyword_scheme * scheme;
};
enum class sync_graph
{
none,
refresh,
lazy_refresh
};
struct text_editor::implementation
{
@ -397,6 +404,8 @@ namespace nana{ namespace widgets
skeletons::textbase<wchar_t> textbase;
sync_graph try_refresh{ sync_graph::none };
struct inner_capacities
{
editor_behavior_interface * behavior;
@ -411,14 +420,12 @@ namespace nana{ namespace widgets
paint::graphics buffer; //A offscreen buffer which keeps the background that painted by external part.
}counterpart;
struct indent_rep
{
bool enabled{ false };
std::function<std::string()> generator;
}indent;
struct inner_keywords
{
std::map<std::string, std::shared_ptr<keyword_scheme>> schemes;
@ -487,13 +494,10 @@ namespace nana{ namespace widgets
if ((0 == textlines) || (0 == line_px))
return{};
auto const offset_top = editor_._m_text_topline();
const int text_area_top = editor_.text_area_.area.y;
if (top < text_area_top)
top = offset_top ? offset_top - 1 : 0;
if (top < editor_.text_area_.area.y)
top = (std::max)(editor_._m_text_topline() - 1, 0);
else
top = (top - text_area_top) / line_px + offset_top;
top = (top - editor_.text_area_.area.y + editor_.impl_->cview->origin().y) / line_px;
return{ (textlines <= static_cast<std::size_t>(top) ? textlines - 1 : static_cast<std::size_t>(top)),
0 };
@ -676,16 +680,9 @@ namespace nana{ namespace widgets
if ((0 == editor_.textbase().lines()) || (0 == line_px))
return coord;
const int text_area_top = editor_.text_area_.area.y;
auto const offset_top = editor_._m_text_topline();
auto screen_rows = (top - editor_.text_area_.area.y + editor_.impl_->cview->origin().y) / line_px;
auto screen_line = (text_area_top - top) / line_px;
if ((top < text_area_top) && (screen_line > offset_top))
screen_line = 0;
else
screen_line = offset_top - screen_line;
coord = _m_textline(static_cast<std::size_t>(screen_line));
coord = _m_textline(static_cast<std::size_t>(screen_rows));
if (linemtr_.size() <= coord.first)
{
coord.first = linemtr_.size() - 1;
@ -1261,6 +1258,7 @@ namespace nana{ namespace widgets
put(key);
}
reset_caret();
impl_->try_refresh = sync_graph::refresh;
return true;
}
return false;
@ -1289,6 +1287,7 @@ namespace nana{ namespace widgets
default:
return false;
}
impl_->try_refresh = sync_graph::refresh;
return true;
}
@ -1316,8 +1315,7 @@ namespace nana{ namespace widgets
_m_reset();
impl_->capacities.behavior->pre_calc_lines(width_pixels());
render(API::is_focus_ready(window_));
impl_->try_refresh = sync_graph::refresh;
_m_reset_content_size();
return true;
}
@ -1326,7 +1324,7 @@ namespace nana{ namespace widgets
{
this->attributes_.alignment = alignment;
this->reset_caret();
render(API::is_focus_ready(window_));
impl_->try_refresh = sync_graph::refresh;
_m_reset_content_size();
}
@ -1340,11 +1338,9 @@ namespace nana{ namespace widgets
if (impl_->counterpart.enabled)
impl_->counterpart.buffer.make(r.dimension());
impl_->capacities.behavior->pre_calc_lines(width_pixels());
impl_->cview->disp_area(r, { -1, 1 }, { 1, -1 }, { 2, 2 });
if (impl_->cview->content_size().empty() || this->attributes_.line_wrapped)
_m_reset_content_size();
_m_reset_content_size(true);
move_caret(points_.caret);
return true;
@ -1381,14 +1377,12 @@ namespace nana{ namespace widgets
else
impl_->capacities.behavior = new behavior_normal(*this);
impl_->capacities.behavior->pre_calc_lines(width_pixels());
_m_reset_content_size(true);
impl_->cview->move_origin(point{} -impl_->cview->origin());
move_caret(upoint{});
_m_reset_content_size();
render(API::is_focus_ready(window_));
impl_->try_refresh = sync_graph::refresh;
return true;
}
return false;
@ -1478,14 +1472,19 @@ namespace nana{ namespace widgets
return px;
}
unsigned text_editor::screen_lines() const
unsigned text_editor::screen_lines(bool completed_line) const
{
auto const line_px = line_height();
if (line_px)
{
auto h = impl_->cview->view_area().height;
if (graph_ && h)
{
if (completed_line)
return (h / line_px);
return (h / line_px + (h % line_px ? 1 : 0));
}
}
return 0;
}
@ -1559,23 +1558,23 @@ namespace nana{ namespace widgets
else if (selection::mode::move_selected == select_.mode_selection)
select_.mode_selection = selection::mode::move_selected_take_effect;
_m_draw_border();
impl_->try_refresh = sync_graph::refresh;
return true;
}
return false;
}
bool text_editor::mouse_pressed(const arg_mouse& arg)
void text_editor::mouse_pressed(const arg_mouse& arg)
{
if(!attributes_.enable_caret)
return false;
return;
if (event_code::mouse_down == arg.evt_code)
{
if (select_.ignore_press || (!hit_text_area(arg.pos)))
{
select_.ignore_press = false;
return false;
return;
}
if (::nana::mouse::left_button == arg.button)
@ -1614,13 +1613,11 @@ namespace nana{ namespace widgets
}
}
_m_draw_border();
return true;
impl_->try_refresh = sync_graph::refresh;
}
else if (event_code::mouse_up == arg.evt_code)
{
select_.ignore_press = false;
bool updated = false;
if (select_.mode_selection == selection::mode::mouse_selected)
{
@ -1630,13 +1627,18 @@ namespace nana{ namespace widgets
else if (selection::mode::move_selected == select_.mode_selection || selection::mode::move_selected_take_effect == select_.mode_selection)
{
//move_selected indicates the mouse is pressed on the selected text, but the mouse has not moved. So the text_editor should cancel the selection.
//move_selected_take_effect indicates the mouse is pressed on the selected text, and the mouse has moved. So the text_editor should try move the selection.
//move_selected_take_effect indicates the text_editor should try to move the selection.
if((selection::mode::move_selected == select_.mode_selection) || !move_select())
if ((selection::mode::move_selected == select_.mode_selection) || !move_select())
{
//no move occurs
select(false);
move_caret(_m_screen_to_caret(arg.pos));
}
select_.mode_selection = selection::mode::no_selected;
updated = true;
impl_->try_refresh = sync_graph::refresh;
}
API::release_capture(window_);
@ -1644,12 +1646,7 @@ namespace nana{ namespace widgets
text_area_.captured = false;
if (hit_text_area(arg.pos) == false)
API::window_cursor(window_, nana::cursor::arrow);
_m_draw_border();
return updated;
}
return false;
}
textbase<text_editor::char_type> & text_editor::textbase()
@ -1662,6 +1659,19 @@ namespace nana{ namespace widgets
return impl_->textbase;
}
bool text_editor::try_refresh()
{
if (sync_graph::none != impl_->try_refresh)
{
if (sync_graph::refresh == impl_->try_refresh)
render(API::is_focus_ready(window_));
impl_->try_refresh = sync_graph::none;
return true;
}
return false;
}
bool text_editor::getline(std::size_t pos, std::wstring& text) const
{
if (impl_->textbase.lines() <= pos)
@ -1677,7 +1687,8 @@ namespace nana{ namespace widgets
impl_->textbase.erase_all();
_m_reset();
impl_->capacities.behavior->pre_calc_lines(width_pixels());
_m_reset_content_size(true);
if (!end_caret)
{
auto undo_ptr = std::unique_ptr<undo_input_text>{ new undo_input_text(*this, str) };
@ -1691,9 +1702,7 @@ namespace nana{ namespace widgets
{
impl_->capacities.behavior->adjust_caret_into_screen();
reset_caret();
render(API::is_focus_ready(window_));
_m_reset_content_size();
impl_->try_refresh = sync_graph::refresh;
points_.xpos = 0;
}
}
@ -1755,7 +1764,7 @@ namespace nana{ namespace widgets
if (reset_caret && (!hit_text_area(pos)))
{
impl_->capacities.behavior->adjust_caret_into_screen();
render(true);
impl_->try_refresh = sync_graph::refresh;
caret->visible(true);
return true;
}
@ -1777,9 +1786,9 @@ namespace nana{ namespace widgets
API::open_caret(window_, true).get()->dimension({ 1, line_height() });
}
void text_editor::reset_caret()
void text_editor::reset_caret(bool stay_in_view)
{
move_caret(points_.caret);
move_caret(points_.caret, stay_in_view);
}
void text_editor::show_caret(bool isshow)
@ -1821,14 +1830,14 @@ namespace nana{ namespace widgets
if(select_.b.y) --select_.b.y;
select_.b.x = static_cast<unsigned>(impl_->textbase.getline(select_.b.y).size());
select_.mode_selection = selection::mode::method_selected;
render(true);
impl_->try_refresh = sync_graph::refresh;
return true;
}
select_.mode_selection = selection::mode::no_selected;
if (_m_cancel_select(0))
{
render(true);
impl_->try_refresh = sync_graph::refresh;
return true;
}
return false;
@ -1840,8 +1849,8 @@ namespace nana{ namespace widgets
select_.b = points_.caret;
points_.xpos = points_.caret.x;
if (new_sel_end || (stay_in_view && impl_->capacities.behavior->adjust_caret_into_screen()))
render(true);
if(new_sel_end || (stay_in_view && impl_->capacities.behavior->adjust_caret_into_screen()))
impl_->try_refresh = sync_graph::refresh;
}
bool text_editor::hit_text_area(const point& pos) const
@ -1877,7 +1886,7 @@ namespace nana{ namespace widgets
points_.caret = select_.b;
if (impl_->capacities.behavior->adjust_caret_into_screen())
render(true);
impl_->try_refresh = sync_graph::refresh;
reset_caret();
return true;
@ -1886,7 +1895,7 @@ namespace nana{ namespace widgets
if (_m_move_select(true))
{
impl_->capacities.behavior->adjust_caret_into_screen();
render(true);
impl_->try_refresh = sync_graph::refresh;
return true;
}
return false;
@ -1906,7 +1915,7 @@ namespace nana{ namespace widgets
unsigned exclude_px = API::open_caret(window_, true).get()->dimension().width;
if (attributes_.line_wrapped)
exclude_px += impl_->cview->space();
exclude_px += impl_->cview->extra_space(false);
return (text_area_.area.width > exclude_px ? text_area_.area.width - exclude_px : 0);
}
@ -1948,8 +1957,11 @@ namespace nana{ namespace widgets
graph_.rectangle(false, bgcolor);
//Draw background
if(attributes_.enable_background)
graph_.rectangle(text_area_.area, true, bgcolor);
if (!API::dev::copy_transparent_background(window_, graph_))
{
if (attributes_.enable_background)
graph_.rectangle(text_area_.area, true, bgcolor);
}
if (impl_->customized_renderers.background)
impl_->customized_renderers.background(graph_, text_area_.area, bgcolor);
@ -1982,6 +1994,7 @@ namespace nana{ namespace widgets
impl_->text_position.emplace_back(upoint{});
_m_draw_border();
impl_->try_refresh = sync_graph::none;
}
//public:
void text_editor::put(std::wstring text)
@ -2006,7 +2019,7 @@ namespace nana{ namespace widgets
{
impl_->capacities.behavior->adjust_caret_into_screen();
reset_caret();
render(API::is_focus_ready(window_));
impl_->try_refresh = sync_graph::refresh;
_m_reset_content_size();
points_.xpos = points_.caret.x;
}
@ -2033,10 +2046,14 @@ namespace nana{ namespace widgets
points_.caret.x ++;
if (refresh || _m_update_caret_line(secondary_before))
render(true);
if (!refresh)
{
if (!_m_update_caret_line(secondary_before))
draw_corner();
}
else
draw_corner();
impl_->try_refresh = sync_graph::refresh;
_m_reset_content_size();
points_.xpos = points_.caret.x;
@ -2232,14 +2249,13 @@ namespace nana{ namespace widgets
if (record_undo)
impl_->undo.push(std::move(undo_ptr));
_m_reset_content_size(has_to_redraw);
if(has_to_redraw)
{
impl_->capacities.behavior->pre_calc_lines(width_pixels());
impl_->capacities.behavior->adjust_caret_into_screen();
render(true);
impl_->try_refresh = sync_graph::refresh;
}
_m_reset_content_size();
}
void text_editor::undo(bool reverse)
@ -2249,11 +2265,10 @@ namespace nana{ namespace widgets
else
impl_->undo.undo();
impl_->capacities.behavior->pre_calc_lines(width_pixels());
impl_->capacities.behavior->adjust_caret_into_screen();
render(true);
_m_reset_content_size(true);
_m_reset_content_size();
impl_->capacities.behavior->adjust_caret_into_screen();
impl_->try_refresh = sync_graph::refresh;
}
void text_editor::set_undo_queue_length(std::size_t len)
@ -2265,7 +2280,7 @@ namespace nana{ namespace widgets
{
const bool redraw_required = _m_cancel_select(0);
if (_m_move_caret_ns(to_north) || redraw_required)
render(true);
impl_->try_refresh = sync_graph::refresh;
}
void text_editor::move_left()
@ -2280,7 +2295,7 @@ namespace nana{ namespace widgets
pending = false;
bool adjust_y = (attributes_.line_wrapped && impl_->capacities.behavior->adjust_caret_into_screen());
if (_m_move_offset_x_while_over_border(-2) || adjust_y)
render(true);
impl_->try_refresh = sync_graph::refresh;
}
else if (points_.caret.y) //Move to previous line
points_.caret.x = static_cast<unsigned>(textbase().getline(--points_.caret.y).size());
@ -2289,7 +2304,7 @@ namespace nana{ namespace widgets
}
if (pending && impl_->capacities.behavior->adjust_caret_into_screen())
render(true);
impl_->try_refresh = sync_graph::refresh;
points_.xpos = points_.caret.x;
}
@ -2318,7 +2333,7 @@ namespace nana{ namespace widgets
do_render = impl_->capacities.behavior->adjust_caret_into_screen();
if (do_render)
render(true);
impl_->try_refresh = sync_graph::refresh;
points_.xpos = points_.caret.x;
}
@ -2477,9 +2492,20 @@ namespace nana{ namespace widgets
impl_->cview->move_origin(origin - impl_->cview->origin());
impl_->cview->sync(true);
points_.xpos = points_.caret.x;
impl_->try_refresh = sync_graph::refresh;
}
}
unsigned text_editor::_m_width_px(bool include_vs) const
{
unsigned exclude_px = API::open_caret(window_, true).get()->dimension().width;
if (!include_vs)
exclude_px += impl_->cview->space();
return (text_area_.area.width > exclude_px ? text_area_.area.width - exclude_px : 0);
}
void text_editor::_m_draw_border()
{
if (!API::widget_borderless(this->window_))
@ -2510,7 +2536,7 @@ namespace nana{ namespace widgets
points_.caret = _m_screen_to_caret(scrpos);
if (stay_in_view && impl_->capacities.behavior->adjust_caret_into_screen())
render(true);
impl_->try_refresh = sync_graph::refresh;
move_caret(points_.caret);
return points_.caret;
@ -2790,7 +2816,9 @@ namespace nana{ namespace widgets
auto top = _m_caret_to_screen(upoint{ 0, static_cast<unsigned>(pos) }).y;
const unsigned pixels = line_height();
graph_.rectangle({ text_area_.area.x, top, width_pixels(), static_cast<unsigned>(pixels * secondary_count_before) }, true, API::bgcolor(window_));
const rectangle update_area = { text_area_.area.x, top, width_pixels(), static_cast<unsigned>(pixels * secondary_count_before) };
if (!API::dev::copy_transparent_background(window_, update_area, graph_, update_area.position()))
graph_.rectangle(update_area, true, API::bgcolor(window_));
auto fgcolor = API::fgcolor(window_);
auto text_ptr = textbase().getline(pos).c_str();
@ -2803,9 +2831,10 @@ namespace nana{ namespace widgets
}
_m_draw_border();
impl_->try_refresh = sync_graph::lazy_refresh;
}
else
render(API::is_focus_ready(window_));
impl_->try_refresh = sync_graph::refresh;
}
bool text_editor::_m_accepts(char_type ch) const
@ -2835,22 +2864,58 @@ namespace nana{ namespace widgets
return (!API::window_enabled(window_) ? static_cast<color_rgb>(0xE0E0E0) : API::bgcolor(window_));
}
void text_editor::_m_reset_content_size()
void text_editor::_m_reset_content_size(bool calc_lines)
{
auto const height = static_cast<unsigned>(impl_->capacities.behavior->take_lines() * line_height());
size csize;
unsigned width = 0;
if (this->attributes_.line_wrapped)
{
width = width_pixels();
if (calc_lines)
{
//detect if vertical scrollbar is required
auto const max_lines = screen_lines(true);
auto const text_lines = textbase().lines();
csize.width = _m_width_px(true);
if (text_lines > max_lines)
{
//enable vertical scrollbar
csize.width = _m_width_px(false);
}
else
{
std::size_t lines = 0;
for (std::size_t i = 0; i < text_lines; ++i)
{
impl_->capacities.behavior->pre_calc_line(i, csize.width);
lines += impl_->capacities.behavior->take_lines(i);
if (lines > max_lines)
{
//enable vertical scrollbar
csize.width = _m_width_px(false);
break;
}
}
}
impl_->capacities.behavior->pre_calc_lines(csize.width);
}
else
csize.width = impl_->cview->content_size().width;
}
else
{
if (calc_lines)
impl_->capacities.behavior->pre_calc_lines(0);
auto maxline = textbase().max_line();
width = _m_text_extent_size(textbase().getline(maxline.first).c_str(), maxline.second).width;
csize.width = _m_text_extent_size(textbase().getline(maxline.first).c_str(), maxline.second).width;
}
impl_->cview->content_size({ width, height });
csize.height = static_cast<unsigned>(impl_->capacities.behavior->take_lines() * line_height());
impl_->cview->content_size(csize);
}
void text_editor::_m_reset()
@ -3188,10 +3253,7 @@ namespace nana{ namespace widgets
int text_editor::_m_text_topline() const
{
auto px = static_cast<int>(line_height());
if (0 == px)
return 0;
return (impl_->cview->origin().y / px);
return (px ? (impl_->cview->origin().y / px) : px);
}
int text_editor::_m_text_x(const text_section& sct) const
@ -3508,6 +3570,7 @@ namespace nana{ namespace widgets
return false;
}
}
impl_->try_refresh = sync_graph::refresh;
return true;
}

View File

@ -300,7 +300,7 @@ namespace nana
{
if(!graph.size().empty())
{
proto_.renderer->background(other_.wd, graph, (bground_mode::basic == API::effects_bground_mode(other_.wd)), other_.widget->scheme());
proto_.renderer->background(other_.wd, graph, API::dev::copy_transparent_background(other_.wd, graph), other_.widget->scheme());
_m_draw_elements(graph);
}
}
@ -897,7 +897,7 @@ namespace nana
bool slider::transparent() const
{
return (bground_mode::basic == API::effects_bground_mode(*this));
return API::is_transparent_background(*this);
}
//end class slider
}//end namespace nana

View File

@ -372,7 +372,8 @@ namespace nana
return true;
}
if (editor_->mouse_pressed(arg))
editor_->mouse_pressed(arg);
if(editor_->try_refresh())
{
_m_draw_spins(buttons::none);
return true;
@ -383,10 +384,11 @@ namespace nana
bool mouse_move(bool left_button, const ::nana::point& pos)
{
if (editor_->mouse_move(left_button, pos))
editor_->mouse_move(left_button, pos);
if(editor_->try_refresh())
{
editor_->reset_caret();
render();
_m_draw_spins(spin_stated_);
return true;
}
@ -570,10 +572,11 @@ namespace nana
void drawer::key_char(graph_reference, const arg_keyboard& arg)
{
if (impl_->editor()->respond_char(arg))
impl_->editor()->respond_char(arg);
if (impl_->editor()->try_refresh())
{
if (!impl_->value(to_utf8(impl_->editor()->text()), false))
impl_->draw_spins();
impl_->value(to_utf8(impl_->editor()->text()), false);
impl_->draw_spins();
API::dev::lazy_refresh();
}

View File

@ -103,22 +103,22 @@ namespace drawerbase {
void drawer::mouse_down(graph_reference, const arg_mouse& arg)
{
if (editor_->mouse_pressed(arg))
{
editor_->render(true);
editor_->mouse_pressed(arg);
if(editor_->try_refresh())
API::dev::lazy_refresh();
}
}
void drawer::mouse_move(graph_reference, const arg_mouse& arg)
{
if(editor_->mouse_move(arg.left_button, arg.pos))
editor_->mouse_move(arg.left_button, arg.pos);
if(editor_->try_refresh())
API::dev::lazy_refresh();
}
void drawer::mouse_up(graph_reference, const arg_mouse& arg)
{
if(editor_->mouse_pressed(arg))
editor_->mouse_pressed(arg);
if(editor_->try_refresh())
API::dev::lazy_refresh();
}
@ -145,16 +145,16 @@ namespace drawerbase {
void drawer::key_press(graph_reference, const arg_keyboard& arg)
{
if(editor_->respond_key(arg))
{
editor_->reset_caret();
editor_->respond_key(arg);
editor_->reset_caret(true);
if(editor_->try_refresh())
API::dev::lazy_refresh();
}
}
void drawer::key_char(graph_reference, const arg_keyboard& arg)
{
if (editor_->respond_char(arg))
editor_->respond_char(arg);
if(editor_->try_refresh())
API::dev::lazy_refresh();
}
@ -163,6 +163,10 @@ namespace drawerbase {
_m_text_area(arg.width, arg.height);
refresh(graph);
editor_->reset_caret();
if (!editor_->try_refresh())
refresh(graph);
API::dev::lazy_refresh();
}
@ -225,7 +229,10 @@ namespace drawerbase {
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor && editor->load(file.data()))
API::update_window(handle());
{
if (editor->try_refresh())
API::update_window(handle());
}
}
void textbox::store(std::string file)
@ -267,7 +274,9 @@ namespace drawerbase {
editor->move_caret_end(true);
editor->textbase().reset();
API::update_window(this->handle());
if (editor->try_refresh())
API::update_window(this->handle());
}
return *this;
}
@ -383,6 +392,8 @@ namespace drawerbase {
editor->move_caret_end(false);
editor->put(to_wstring(text));
editor->try_refresh();
API::update_window(this->handle());
}
return *this;
@ -399,8 +410,11 @@ namespace drawerbase {
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor->line_wrapped(autl))
if (editor && editor->line_wrapped(autl))
{
editor->try_refresh();
API::update_window(handle());
}
return *this;
}
@ -420,6 +434,8 @@ namespace drawerbase {
{
auto wd = handle();
API::eat_tabstop(wd, ml); //textbox handles the Tab pressing when it is multi-line.
editor->try_refresh();
API::update_window(wd);
}
return *this;
@ -495,7 +511,7 @@ namespace drawerbase {
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if(editor && editor->select(yes))
API::update_window(*this);
API::refresh_window(*this);
}
std::pair<upoint, upoint> textbox::selection() const
@ -525,7 +541,8 @@ namespace drawerbase {
if(editor)
{
editor->paste();
API::update_window(*this);
if (editor->try_refresh())
API::update_window(*this);
}
}
@ -578,7 +595,10 @@ namespace drawerbase {
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
{
editor->set_highlight(name, fgcolor, bgcolor);
API::refresh_window(handle());
}
}
void textbox::erase_highlight(const std::string& name)
@ -586,7 +606,10 @@ namespace drawerbase {
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
{
editor->erase_highlight(name);
API::refresh_window(handle());
}
}
void textbox::set_keywords(const std::string& name, bool case_sensitive, bool whole_word_match, std::initializer_list<std::wstring> kw_list)
@ -597,6 +620,7 @@ namespace drawerbase {
{
for (auto & kw : kw_list)
editor->set_keyword(kw, name, case_sensitive, whole_word_match);
API::refresh_window(handle());
}
}
@ -608,6 +632,7 @@ namespace drawerbase {
{
for (auto & kw : kw_list_utf8)
editor->set_keyword(::nana::charset(kw, ::nana::unicode::utf8), name, case_sensitive, whole_word_match);
API::refresh_window(handle());
}
}
@ -616,7 +641,10 @@ namespace drawerbase {
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
{
editor->erase_keyword(to_wstring(kw));
API::refresh_window(handle());
}
}
textbox& textbox::text_align(::nana::align alignment)
@ -626,7 +654,7 @@ namespace drawerbase {
if (editor)
{
editor->text_align(alignment);
API::update_window(this->handle());
API::refresh_window(handle());
}
return *this;

View File

@ -105,7 +105,7 @@ namespace nana
nana::paint::graphics item_graph({ item_r_.width, item_r_.height });
item_graph.typeface(graph_->typeface());
renderer_->set_color(widget_->bgcolor(), widget_->fgcolor());
renderer_->begin_paint(*widget_);
renderer_->bground(item_graph, this);
renderer_->expander(item_graph, this);
renderer_->crook(item_graph, this);
@ -343,7 +343,9 @@ namespace nana
if (attr.auto_draw || ignore_auto_draw)
{
//Draw background
data.graph->rectangle(true, data.widget_ptr->bgcolor());
rectangle bground_r{ data.graph->size() };
if (!API::dev::copy_transparent_background(data.widget_ptr->handle(), bground_r, *data.graph, {}))
data.graph->rectangle(true, data.widget_ptr->bgcolor());
//Draw tree
attr.tree_cont.for_each(shape.first, Renderer(this, nana::point(static_cast<int>(attr.tree_cont.indent_size(shape.first) * shape.indent_pixels) - shape.offset_x, 1)));
@ -1201,13 +1203,11 @@ namespace nana
class internal_renderer
: public renderer_interface
{
nana::color bgcolor_;
nana::color fgcolor_;
window window_handle_;
void set_color(const nana::color & bgcolor, const nana::color& fgcolor) override
void begin_paint(::nana::widget& wdg) override
{
bgcolor_ = bgcolor;
fgcolor_ = fgcolor;
window_handle_ = wdg.handle();
}
void bground(graph_reference graph, const compset_interface * compset) const override
@ -1234,8 +1234,19 @@ namespace nana
if (clrptr)
{
graph.rectangle(attr.area, false, clrptr[1]);
graph.rectangle(attr.area.pare_off(1), true, *clrptr);
if (API::is_transparent_background(window_handle_))
{
paint::graphics item_graph{ attr.area.dimension() };
item_graph.rectangle(false, clrptr[1]);
item_graph.rectangle(rectangle{attr.area.dimension()}.pare_off(1), true, *clrptr);
item_graph.blend(rectangle{ attr.area.dimension() }, graph, attr.area.position(), 0.5);
}
else
{
graph.rectangle(attr.area, false, clrptr[1]);
graph.rectangle(attr.area.pare_off(1), true, *clrptr);
}
}
}
}
@ -1255,7 +1266,7 @@ namespace nana
auto r = attr.area;
r.y += (attr.area.height - 16) / 2;
r.width = r.height = 16;
arrow.draw(graph, bgcolor_, (attr.mouse_pointed ? colors::deep_sky_blue : colors::black), r, element_state::normal);
arrow.draw(graph, API::bgcolor(window_handle_), (attr.mouse_pointed ? colors::deep_sky_blue : colors::black), r, element_state::normal);
}
}
@ -1266,7 +1277,7 @@ namespace nana
{
attr.area.y += (attr.area.height - 16) / 2;
crook_.check(compset->item_attribute().checked);
crook_.draw(graph, bgcolor_, fgcolor_, attr.area, attr.mouse_pointed ? element_state::hovered : element_state::normal);
crook_.draw(graph, API::bgcolor(window_handle_), API::fgcolor(window_handle_), attr.area, attr.mouse_pointed ? element_state::hovered : element_state::normal);
}
}
@ -1308,7 +1319,7 @@ namespace nana
{
comp_attribute_t attr;
if (compset->comp_attribute(component::text, attr))
graph.string(point{ attr.area.x, attr.area.y + 3 }, compset->item_attribute().text, fgcolor_);
graph.string(point{ attr.area.x, attr.area.y + 3 }, compset->item_attribute().text, API::fgcolor(window_handle_));
}
private:
mutable facade<element::crook> crook_;
@ -1408,8 +1419,6 @@ namespace nana
item_renderer(implement * impl, const nana::point& pos)
: impl_(impl),
bgcolor_(impl->data.widget_ptr->bgcolor()),
fgcolor_(impl->data.widget_ptr->fgcolor()),
pos_(pos)
{
}
@ -1441,7 +1450,7 @@ namespace nana
node_r_.height = comp_placer->item_height(*impl_->data.graph);
auto renderer = draw_impl->data.renderer;
renderer->set_color(bgcolor_, fgcolor_);
renderer->begin_paint(*draw_impl->data.widget_ptr);
renderer->bground(*draw_impl->data.graph, this);
renderer->expander(*draw_impl->data.graph, this);
renderer->crook(*draw_impl->data.graph, this);
@ -1476,8 +1485,6 @@ namespace nana
}
private:
trigger::implement * impl_;
::nana::color bgcolor_;
::nana::color fgcolor_;
::nana::point pos_;
const node_type * iterated_node_;
item_attribute_t node_attr_;

View File

@ -36,11 +36,13 @@ namespace nana{ namespace paint
::SHGetFileInfo(filename.c_str(), 0, &sfi, sizeof sfi, SHGFI_ICON);
native_handle_ = sfi.hIcon;
#else
static_cast<void>(filename); //eliminate unused parameter compiler warnings
#endif
return (nullptr != native_handle_);
}
bool open(const void* data, std::size_t bytes) override
bool open(const void* /*data*/, std::size_t /*bytes*/) override
{
return false;
}
@ -92,6 +94,7 @@ namespace nana{ namespace paint
::DrawIconEx(graph.handle()->context, p_dst.x, p_dst.y, reinterpret_cast<HICON>(native_handle_), src_r.width, src_r.height, 0, 0, DI_NORMAL);
#else
static_cast<void>(src_r); //eliminate unused parameter compiler warning.
static_cast<void>(graph);
static_cast<void>(p_dst);
#endif
@ -105,7 +108,8 @@ namespace nana{ namespace paint
#if defined(NANA_WINDOWS)
::DrawIconEx(graph.handle()->context, r.x, r.y, reinterpret_cast<HICON>(native_handle_), r.width, r.height, 0, 0, DI_NORMAL);
#else
static_cast<void>(r); //eliminate unused parameter compiler warning.
static_cast<void>(graph); //eliminate unused parameter compiler warning.
static_cast<void>(r);
#endif
}

View File

@ -1,7 +1,7 @@
/*
* Platform Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -100,18 +100,23 @@ namespace detail
void blend(drawable_type dw, const rectangle& area, pixel_color_t color, double fade_rate)
{
if (fade_rate <= 0) return;
if (fade_rate > 1) fade_rate = 1;
if (fade_rate < 0)
fade_rate = 0;
else if (fade_rate >= 1)
return;
rectangle r;
if (false == ::nana::overlap(rectangle{ drawable_size(dw) }, area, r))
return;
unsigned red = static_cast<unsigned>((color.value & 0xFF0000) * fade_rate);
unsigned green = static_cast<unsigned>((color.value & 0xFF00) * fade_rate);
unsigned blue = static_cast<unsigned>((color.value & 0xFF) * fade_rate);
auto const color_fd_rate = (double(color.element.alpha_channel) / 255.0) * (1 - fade_rate);
fade_rate = (1 - color_fd_rate);
unsigned red = static_cast<unsigned>((color.value & 0xFF0000) * color_fd_rate);
unsigned green = static_cast<unsigned>((color.value & 0xFF00) * color_fd_rate);
unsigned blue = static_cast<unsigned>((color.value & 0xFF) * color_fd_rate);
double lrate = 1 - fade_rate;
pixel_buffer pixbuf(dw, r.y, r.height);
for (std::size_t row = 0; row < r.height; ++row)
@ -120,9 +125,9 @@ namespace detail
const auto end = i + r.width;
for (; i < end; ++i)
{
unsigned px_r = ((static_cast<unsigned>((i->value & 0xFF0000) * lrate) + red) & 0xFF0000);
unsigned px_g = ((static_cast<unsigned>((i->value & 0xFF00) * lrate) + green) & 0xFF00);
unsigned px_b = ((static_cast<unsigned>((i->value & 0xFF) * lrate) + blue) & 0xFF);
unsigned px_r = ((static_cast<unsigned>((i->value & 0xFF0000) * fade_rate) + red) & 0xFF0000);
unsigned px_g = ((static_cast<unsigned>((i->value & 0xFF00) * fade_rate) + green) & 0xFF00);
unsigned px_b = ((static_cast<unsigned>((i->value & 0xFF) * fade_rate) + blue) & 0xFF);
i->value = (px_r | px_g | px_b);
}
}

View File

@ -672,6 +672,15 @@ namespace paint
}
}
void graphics::blend(const nana::rectangle& r, const ::nana::color& clr, double fade_rate)
{
if (impl_->handle)
{
nana::paint::detail::blend(impl_->handle, r, clr.px_color(), fade_rate);
if (impl_->changed == false) impl_->changed = true;
}
}
void graphics::blur(const nana::rectangle& r, std::size_t radius)
{
if(impl_->handle)
@ -968,15 +977,6 @@ namespace paint
return bidi_string(pos, wstr.data(), wstr.size());
}
void graphics::blend(const nana::rectangle& r, const ::nana::color& clr, double fade_rate)
{
if (impl_->handle)
{
nana::paint::detail::blend(impl_->handle, r, clr.px_color(), fade_rate);
if (impl_->changed == false) impl_->changed = true;
}
}
void graphics::set_pixel(int x, int y, const ::nana::color& clr)
{
if (impl_->handle)