listbox header font

This commit is contained in:
Jinhao 2017-11-21 17:20:47 +08:00
parent a57c7ac409
commit b71427334a
8 changed files with 203 additions and 30 deletions

View File

@ -434,6 +434,8 @@ namespace API
* widget by the content extent.
*/
optional<std::pair<::nana::size, ::nana::size>> content_extent(window wd, unsigned limited_px, bool limit_width);
unsigned screen_dpi(bool x_requested);
}//end namespace API
}//end namespace nana

View File

@ -94,6 +94,12 @@ namespace nana
*/
virtual void fit_content(unsigned maximum = 0) noexcept = 0;
/// Sets an exclusive font for the column
virtual void typeface(const paint::font& column_font) = 0;
/// Returns a font
virtual paint::font typeface() const noexcept = 0;
/// Determines the visibility state of the column
/**
* @return true if the column is visible, false otherwise
@ -1194,17 +1200,25 @@ namespace nana
color_proxy selection_box{ static_cast<color_rgb>(0x3399FF) }; ///< Color of selection box border.
std::shared_ptr<paint::font> column_font; ///< Renderer draws column texts with the font if it is not a nullptr.
/// The max column width which is generated by fit_content is allowed. It is ignored when it is 0, or a max value is passed to fit_content.
unsigned max_fit_content{ 0 };
unsigned min_column_width{ 20 }; ///< def=20 . non counting suspension_width
unsigned min_column_width{ 20 }; ///< def=20 . non counting suspension_width
unsigned suspension_width { 8 }; ///< def= . the trigger will set this to the width if ("...")
unsigned text_margin { 5 }; ///< def= 5. Additional or extended with added (before) to the text width to determine the cell width. cell_w = text_w + ext_w +1
unsigned header_height { 25 }; ///< def=25 . header height header_size
unsigned item_height_ex { 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex
unsigned suspension_width{ 8 }; ///< def= . the trigger will set this to the width if ("...")
unsigned text_margin{ 5 }; ///< def= 5. Additional or extended with added (before) to the text width to determine the cell width. cell_w = text_w + ext_w +1
//deprecated
//unsigned header_height { 25 }; ///< def=25 . header height header_size
unsigned item_height_ex{ 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex
unsigned header_splitter_area_before{ 2 }; ///< def=2. But 4 is better... IMO
unsigned header_splitter_area_after { 3 }; ///< def=3. But 4 is better...
unsigned header_splitter_area_after{ 3 }; ///< def=3. But 4 is better...
unsigned header_padding_top{ 3 };
unsigned header_padding_bottom{ 3 };
::nana::parameters::mouse_wheel mouse_wheel{}; ///< The number of lines/characters to scroll when vertical/horizontal mouse wheel is moved.
};

View File

@ -38,14 +38,21 @@ namespace nana
font(const font&);
font(const ::std::string& name, double size_pt, const font_style& fs = {});
font(double size_pt, const path_type& truetype, const font_style& ft = {});
font(double size_pt, const path_type& truetype, const font_style& fs = {});
~font();
bool empty() const;
void set_default() const;
::std::string name() const;
double size() const;
/// Returns font size, in point.
/**
* @param fixed Indicates whether to return a fixed font size. If this parameter is false, the method may return zero for default system font size. If the parameter is true, the method returns a fixed size of default font size if the font size that assigned by constructor is zero.
* @return The font size, in point.
*/
double size(bool fixed = false) const;
bool bold() const;
unsigned weight() const;
bool italic() const;

View File

@ -255,6 +255,35 @@ namespace nana
data::storage = nullptr;
}
double platform_abstraction::font_default_pt()
{
#ifdef NANA_WINDOWS
//Create default font object.
NONCLIENTMETRICS metrics = {};
metrics.cbSize = sizeof metrics;
#if(WINVER >= 0x0600)
#if defined(NANA_MINGW)
OSVERSIONINFO osvi = {};
osvi.dwOSVersionInfoSize = sizeof(osvi);
::GetVersionEx(&osvi);
if (osvi.dwMajorVersion < 6)
metrics.cbSize -= sizeof(metrics.iPaddedBorderWidth);
#else
if (!IsWindowsVistaOrGreater())
metrics.cbSize -= sizeof(metrics.iPaddedBorderWidth);
#endif
#endif
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof metrics, &metrics, 0);
auto desktop = ::GetDC(nullptr);
auto pt = std::abs(metrics.lfMessageFont.lfHeight) * 72.0 / ::GetDeviceCaps(desktop, LOGPIXELSY);
::ReleaseDC(nullptr, desktop);
return pt;
#else
return 10;
#endif
}
::std::shared_ptr<platform_abstraction::font> platform_abstraction::default_font(const ::std::shared_ptr<font>& new_font)
{
auto & r = platform_storage();
@ -337,7 +366,7 @@ namespace nana
if(font_family.empty())
font_family = '*';
std::string pat_str = font_family + '-' + std::to_string(size_pt ? size_pt : 10);
std::string pat_str = font_family + '-' + std::to_string(size_pt ? size_pt : font_default_pt());
auto pat = ::XftNameParse(pat_str.c_str());
XftResult res;
auto match_pat = ::XftFontMatch(disp, ::XDefaultScreen(disp), pat, &res);
@ -407,6 +436,31 @@ namespace nana
::FcConfigAppFontClear(nullptr);
}
}
#endif
}
unsigned platform_abstraction::screen_dpi(bool x_requested)
{
#ifdef NANA_WINDOWS
auto hdc = ::GetDC(nullptr);
auto dots = static_cast<unsigned>(::GetDeviceCaps(hdc, (x_requested ? LOGPIXELSX : LOGPIXELSY)));
::ReleaseDC(nullptr, hdc);
return dots;
#else
auto & spec = ::nana::detail::platform_spec::instance();
auto disp = spec.open_display();
auto screen = ::XDefaultScreen(disp);
double dots;
if (x_requested)
dots += ((((double)DisplayWidth(disp, screen)) * 25.4) /
((double)DisplayWidthMM(disp, screen)));
else
dots += ((((double)DisplayHeight(disp, screen)) * 25.4) /
((double)DisplayHeightMM(disp, screen)));
return static_cast<unsigned>(dots + 0.5);
#endif
}
}

View File

@ -33,10 +33,13 @@ namespace nana
static void initialize();
/// Shutdown before destruction of platform_spec
static void shutdown();
static double font_default_pt();
static ::std::shared_ptr<font> default_font(const ::std::shared_ptr<font>&);
static ::std::shared_ptr<font> make_font(const ::std::string& font_family, double size_pt, const font::font_style& fs);
static ::std::shared_ptr<font> make_font_from_ttf(const path_type& ttf, double size_pt, const font::font_style& fs);
static void font_resource(bool try_add, const path_type& ttf);
static unsigned screen_dpi(bool x_requested);
};
}

View File

@ -20,6 +20,8 @@
#include <nana/gui/widgets/widget.hpp>
#include <nana/gui/detail/events_operation.hpp>
#include "../../source/detail/platform_abstraction.hpp"
namespace nana
{
//restrict
@ -1466,5 +1468,10 @@ namespace API
return{};
}
unsigned screen_dpi(bool x_requested)
{
return ::nana::platform_abstraction::screen_dpi(x_requested);
}
}//end namespace API
}//end namespace nana

View File

@ -134,6 +134,7 @@ namespace nana
std::function<bool(const std::string&, nana::any*, const std::string&, nana::any*, bool reverse)> weak_ordering;
std::shared_ptr<paint::font> font; ///< The exclusive column font
column() = default;
@ -150,11 +151,12 @@ namespace nana
index = other.index;
alignment = other.alignment;
weak_ordering = other.weak_ordering;
font = other.font;
}
return *this;
}
column(column&& other):
caption(std::move(other.caption)),
width_px(other.width_px),
@ -163,6 +165,7 @@ namespace nana
index(other.index),
alignment(other.alignment),
weak_ordering(std::move(other.weak_ordering)),
font(std::move(other.font)),
ess_(other.ess_)
{
}
@ -237,6 +240,12 @@ namespace nana
//Definition is provided after essence
void fit_content(unsigned maximize = 100000) noexcept override;
/// Sets an exclusive font for the column
void typeface(const paint::font& column_font) override;
/// Returns a font
paint::font typeface() const noexcept override;
bool visible() const noexcept override
{
return visible_state;
@ -2254,7 +2263,7 @@ namespace nana
{ /// we are inside
auto const origin = content_view->origin();
if(header.visible() && (pos.y < static_cast<int>(scheme_ptr->header_height) + area.y))
if (header.visible() && (pos.y < static_cast<int>(header_visible_px()) + area.y))
{ /// we are in the header
new_where.first = parts::header;
new_where.second = this->column_from_pos(pos.x);
@ -2339,9 +2348,32 @@ namespace nana
return r;
}
double header_font_px() const
{
unsigned max_font_px = 0;
paint::graphics graph{ size{ 1, 1 } };
for (auto & col : this->header.cont())
{
if (!col.visible())
continue;
graph.typeface(col.typeface());
unsigned as, ds, ileading;
graph.text_metrics(as, ds, ileading);
max_font_px = (std::max)(as + ds, max_font_px);
}
return max_font_px;
}
unsigned header_visible_px() const
{
return (header.visible() ? scheme_ptr->header_height : 0);
if (!header.visible())
return 0;
return scheme_ptr->header_padding_top + scheme_ptr->header_padding_bottom + static_cast<unsigned>(header_font_px());
}
bool rect_header(nana::rectangle& r) const
@ -2350,7 +2382,7 @@ namespace nana
{
r = this->content_area();
r.height = scheme_ptr->header_height;
r.height = header_visible_px();
if (lister.wd_ptr()->borderless())
return !r.empty();
@ -2760,6 +2792,29 @@ namespace nana
_m_refresh();
}
/// Sets an exclusive font for the column
void es_header::column::typeface(const paint::font& column_font)
{
this->font.reset(new paint::font{ column_font });
API::refresh_window(*ess_->listbox_ptr);
}
/// Returns a font
paint::font es_header::column::typeface() const noexcept
{
//Returns the exclusive font if it is not empty
if (this->font && !this->font->empty())
return *this->font;
//Returns the column font if it is not empty
if (ess_->scheme_ptr->column_font && !ess_->scheme_ptr->column_font)
return *(ess_->scheme_ptr->column_font);
//If all above fonts are invalid, returns the widget font.
return ess_->listbox_ptr->typeface();
}
//end es_header::column functions
class inline_indicator
@ -3064,6 +3119,14 @@ namespace nana
using item_state = essence::item_state;
using parts = essence::parts;
struct column_rendering_parameter
{
unsigned margin;
unsigned height;
double max_font_px;
paint::font wdg_font;
};
drawer_header_impl(essence* es) noexcept: essence_(es){}
size_type splitter() const noexcept
@ -3175,25 +3238,31 @@ namespace nana
0, r.height - 1
};
column_rendering_parameter crp;
//The first item includes the margin
unsigned margin = essence_->header.margin();
crp.margin = essence_->header.margin();
crp.height = essence_->header_visible_px();
crp.max_font_px = essence_->header_font_px();
crp.wdg_font = graph.typeface();
for (auto & col : essence_->header.cont())
{
if (col.visible_state)
{
column_r.width = col.width_px + margin;
column_r.width = col.width_px + crp.margin;
const auto right_pos = column_r.right();
//Make sure the column is in the display area.
if (right_pos > r.x)
{
_m_draw_header_item(graph, margin, column_r, text_color, col, (col.index == essence_->pointer_where.second ? state : item_state::normal));
_m_draw_header_item(graph, crp, column_r, text_color, col, (col.index == essence_->pointer_where.second ? state : item_state::normal));
graph.line({ right_pos - 1, r.y }, { right_pos - 1, r.bottom() - 2 }, border_color);
}
margin = 0;
crp.margin = 0;
column_r.x = right_pos;
if (right_pos > r.right())
@ -3258,7 +3327,7 @@ namespace nana
return npos;
}
void _m_draw_header_item(graph_reference graph, unsigned margin, const rectangle& column_r, const ::nana::color& fgcolor, const es_header::column& column, item_state state)
void _m_draw_header_item(graph_reference graph, const column_rendering_parameter& crp, const rectangle& column_r, const ::nana::color& fgcolor, const es_header::column& column, item_state state)
{
::nana::color bgcolor;
@ -3289,7 +3358,16 @@ namespace nana
{
graph.palette(true, fgcolor);
point text_pos{ column_r.x + static_cast<int>(margin), (static_cast<int>(essence_->scheme_ptr->header_height) - static_cast<int>(essence_->text_height)) / 2 };
//Set column font
graph.typeface(column.typeface());
unsigned ascent, descent, ileading;
graph.text_metrics(ascent, descent, ileading);
point text_pos{
column_r.x + static_cast<int>(crp.margin),
column_r.bottom() - static_cast<int>(crp.height + ascent + descent) / 2
};
if (align::left == column.alignment)
text_pos.x += text_margin;
@ -3297,6 +3375,9 @@ namespace nana
text_margin = 0;
text_aligner.draw(column.caption, text_pos, column_r.width - text_margin);
//Restores widget font
graph.typeface(crp.wdg_font);
}
auto & sort = essence_->lister.sort_attrs();
@ -3313,16 +3394,20 @@ namespace nana
{
const auto & col = essence_->header.at(essence_->pointer_where.second);
auto margin = 0;
if (&essence_->header.at(0, true) == &col)
margin = essence_->header.margin();
column_rendering_parameter crp;
crp.margin = 0;
crp.height = essence_->header_visible_px();
crp.max_font_px = essence_->header_font_px();
crp.wdg_font = essence_->listbox_ptr->typeface();
paint::graphics fl_graph({ col.width_px + margin, essence_->scheme_ptr->header_height });
if (&essence_->header.at(0, true) == &col)
crp.margin = essence_->header.margin();
paint::graphics fl_graph({ col.width_px + crp.margin, crp.height });
fl_graph.typeface(essence_->graph->typeface());
_m_draw_header_item(fl_graph, margin, rectangle{ fl_graph.size()}, colors::white, col, item_state::floated);
_m_draw_header_item(fl_graph, crp, rectangle{ fl_graph.size()}, colors::white, col, item_state::floated);
auto xpos = essence_->header.range(col.index).first + pos.x - grabs_.start_pos;
essence_->graph->blend(rectangle{ point{ xpos - essence_->content_view->origin().x + rect.x, rect.y } , fl_graph.size() }, fl_graph, {}, 0.5);
@ -3944,8 +4029,6 @@ namespace nana
void trigger::typeface_changed(graph_reference graph)
{
//essence_->text_height = graph.text_extent_size(L"jHWn0123456789/<?'{[|\\_").height;
essence_->text_height = 0;
unsigned as, ds, il;
if (graph.text_metrics(as, ds, il))

View File

@ -127,11 +127,14 @@ namespace paint
return impl_->real_font->family();
}
double font::size() const
double font::size(bool fixed) const
{
if(empty()) return 0;
double size_pt = (empty() ? 0.0 : impl_->real_font->size());
return impl_->real_font->size();
if (fixed && (0.0 == size_pt))
return platform_abstraction::font_default_pt();
return size_pt;
}
bool font::bold() const