Merge branch 'hotfixes-1.0.2' into develop

Conflicts:
	include/nana/gui/detail/basic_window.hpp
	include/nana/gui/widgets/listbox.hpp
	source/gui/detail/linux_X11/bedrock.cpp
	source/gui/detail/win32/bedrock.cpp
	source/gui/detail/window_layout.cpp
	source/gui/detail/window_manager.cpp
	source/gui/widgets/listbox.cpp
	source/gui/widgets/toolbar.cpp
This commit is contained in:
Jinhao
2015-07-11 13:35:22 +08:00
43 changed files with 2614 additions and 760 deletions

View File

@@ -4,7 +4,10 @@
#include <nana/deploy.hpp>
namespace nana{ namespace audio
{ /// play an audio file in Windows WAV format
{ /// class player
/// \brief play an audio file in PCM Windows WAV format
///
/// \include audio_player.cpp
class player
: private nana::noncopyable
{

View File

@@ -13,6 +13,26 @@
#ifndef NANA_CONFIG_HPP
#define NANA_CONFIG_HPP
#if defined(_MSC_VER)
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#pragma warning(disable : 4996)
#if (_MSC_VER < 1900)
// is this a good idea?
#define NOT_IMPLEMENTED_KEYWORD_noexcept
#endif // _MSC_VER < 1900
#if (_MSC_VER == 1900)
// google: break any code that tries to use codecvt<char16_t> or codecvt<char32_t>.
// google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support.
// google: Those definitions are for codecvt<wchar_t>::id, codecvt<unsigned short>::id and codecvt<char>::id respectively.
// However, the codecvt<char16_t>::id and codecvt<char32_t>::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all.
// google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources.
#define STD_CODECVT_NOT_SUPPORTED
#endif // _MSC_VER == 1900
#endif // _MSVC
//Select platform automatically
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
//Windows:
@@ -35,7 +55,7 @@
#define PLATFORM_SPEC_HPP <nana/detail/linux_X11/platform_spec.hpp>
#define STD_CODECVT_NOT_SUPPORTED
#else
# static_assert(false, "Only Windows and Unix are support now");
# static_assert(false, "Only Windows and Unix are supported now");
#endif
#if defined(NANA_MINGW) || defined(NANA_LINUX)

View File

@@ -55,6 +55,13 @@ namespace detail
unsigned ignore; //determinate that pos or size would be ignored.
};
struct map_thread
{
rectangle update_area;
bool ignore_update_area;
bool forced;
};
enum
{
tray = 0x501,

View File

@@ -0,0 +1,469 @@
/*
* A filesystem Implementation
* Copyright(C) 2003 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: stdex/filesystem/filesystem.hpp
* @description:
* file_iterator is a toolkit for applying each file and directory in a
* specified path.
* Modiffied by Ariel Vina-Rodriguez:
* Now mimic std::experimental::filesystem::v1 (boost v3)
* and need VC2015 or a C++11 compiler. With a few correction will be compiler by VC2013
*/
// http://en.cppreference.com/w/cpp/experimental/fs
// http://cpprocks.com/introduction-to-tr2-filesystem-library-in-vs2012/ --- TR2 filesystem in VS2012
// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.140%29.aspx --- C++ 14, the <filesystem> header VS2015
// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.120%29.aspx --- <filesystem> header VS2013
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf --- last pdf of std draft N4100 2014-07-04
// http://cplusplus.github.io/filesystem-ts/working-draft.html --- in html format
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4099.html --- in html format
// http://article.gmane.org/gmane.comp.lib.boost.devel/256220 --- The filesystem TS unanimously approved by ISO.
// http://theboostcpplibraries.com/boost.filesystem --- Boost docs
// http://www.boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm ---
// http://www.boost.org/doc/libs/1_34_0/libs/filesystem/doc/index.htm
// http://www.boost.org/doc/libs/1_58_0/boost/filesystem.hpp
// https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x --- Table 1.4. g++ C++ Technical Specifications Implementation Status
#ifndef NANA_FILESYSTEM_HPP
#define NANA_FILESYSTEM_HPP
#include <iterator>
#include <memory>
#include <chrono>
#include <nana/deploy.hpp>
#ifdef NANA_WINDOWS
#include <windows.h>
typedef HANDLE find_handle_t;
#elif defined(NANA_LINUX)
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
typedef DIR* find_handle_t;
#endif
// namespace std { namespace experimental { namespace filesystem { inline namespace v1 {
namespace nana { namespace experimental
{
namespace filesystem
{
enum class file_type
{
none = 0, ///< has not been determined or an error occurred while trying to determine
not_found = -1, ///< Pseudo-type: file was not found. Is not considered an error
regular = 1,
directory = 2 ,
symlink =3, ///< Symbolic link file
block =4, ///< Block special file
character= 5 , ///< Character special file
fifo = 6 , ///< FIFO or pipe file
socket =7,
unknown= 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other
};
enum class perms
{
none =0, ///< There are no permissions set for the file.
unknown = 0xFFFF ///< not known, such as when a file_status object is created without specifying the permissions
};
//enum class copy_options;
//enum class directory_options;
// class filesystem_error;
enum class error { none = 0 }; // deprecate ??
struct attribute // deprecate ??
{
uintmax_t size {};
bool directory{};
tm modified {};
attribute() {} ;
attribute( uintmax_t size, bool is_directory) :size{size}, directory{is_directory} {}
};
struct space_info
{
uintmax_t capacity;
uintmax_t free;
uintmax_t available;
};
using file_time_type = std::chrono::time_point< std::chrono::system_clock>;// trivial-clock> ;
class file_status
{
file_type m_ft = file_type::none;
perms m_prms = perms::unknown;
public:
explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown)
:m_ft{ft}, m_prms{prms}
{}
file_status(const file_status& fs) : m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default;
file_status(file_status&& fs) : m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default;
~file_status(){};
file_status& operator=(const file_status&) = default;
file_status& operator=(file_status&&fs) // = default;
{
m_ft=fs.m_ft; m_prms = fs.m_prms;
return *this;
}
// observers
file_type type() const { return m_ft;}
perms permissions() const { return m_prms;}
// modifiers
void type (file_type ft) { m_ft=ft ;}
void permissions(perms prms) { m_prms = prms; }
};
/// concerned only with lexical and syntactic aspects and does not necessarily exist in
/// external storage, and the pathname is not necessarily valid for the current operating system
/// or for a particular file system
/// A sequence of elements that identify the location of a file within a filesystem.
/// The elements are the:
/// rootname (opt), root-directory (opt), and an optional sequence of filenames.
/// The maximum number of elements in the sequence is operating system dependent.
class path
{
public:
path();
path(const nana::string&);
bool empty() const;
path root() const;
file_type what() const;
nana::string filename() const;
#if defined(NANA_WINDOWS)
public:
nana::string to_string() const { return text_; }
operator nana::string() const { return text_; }
private:
nana::string text_;
#else
public:
std::string to_string() const { return text_; }
operator std::string() const { return text_; }
private:
std::string text_;
#endif
};
struct directory_entry
{
path m_path;
attribute attr{};
//file_status m_status;
directory_entry(){}
directory_entry(const nana::string& filename_, bool is_directory, uintmax_t size)
:m_path{filename_}, attr{size, is_directory}
{}
void assign (const path& p){ m_path=p;}
void replace_filename(const path& p){ m_path=p;}
//file_status status() const;
operator const path&() const {return m_path;};
const path& path() const {return m_path;}
};
/// an iterator for a sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator
//template<typename FileInfo>
class directory_iterator :public std::iterator<std::input_iterator_tag, directory_entry>
{
public:
using value_type = directory_entry ;
typedef ptrdiff_t difference_type;
typedef const directory_entry* pointer;
typedef const directory_entry& reference;
typedef std::input_iterator_tag iterator_category;
directory_iterator():end_(true), handle_(nullptr){}
directory_iterator(const nana::string& file_path) { _m_prepare(file_path); }
//directory_iterator(const path& file_path) { _m_prepare(file_path.filename()); }
const value_type&
operator*() const { return value_; }
const value_type*
operator->() const { return &(operator*()); }
directory_iterator& operator++()
{ _m_read(); return *this; }
directory_iterator operator++(int)
{
directory_iterator tmp = *this;
_m_read();
return tmp;
}
bool equal(const directory_iterator& x) const
{
if(end_ && (end_ == x.end_)) return true;
return (value_.path().filename() == x.value_.path().filename());
}
// enable directory_iterator range-based for statements
directory_iterator begin( ) { return *this; }
directory_iterator end( ) { return {}; }
private:
template<typename Char>
static bool _m_ignore(const Char * p)
{
while(*p == '.')
++p;
return (*p == 0);
}
void _m_prepare(const nana::string& file_path)
{
#if defined(NANA_WINDOWS)
path_ = file_path;
auto pat = file_path;
DWORD attr = ::GetFileAttributes(pat.data());
if((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY))
pat += STR("\\*");
::HANDLE handle = ::FindFirstFile(pat.data(), &wfd_);
if(handle == INVALID_HANDLE_VALUE)
{
end_ = true;
return;
}
while(_m_ignore(wfd_.cFileName))
{
if(::FindNextFile(handle, &wfd_) == 0)
{
end_ = true;
::FindClose(handle);
return;
}
}
value_ = value_type(wfd_.cFileName,
(FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY,
wfd_.nFileSizeLow);
#elif defined(NANA_LINUX)
path_ = nana::charset(file_path);
if(path_.size() && (path_[path_.size() - 1] != '/'))
path_ += '/';
find_handle_t handle = opendir(path_.c_str());
end_ = true;
if(handle)
{
struct dirent * dnt = readdir(handle);
if(dnt)
{
while(_m_ignore(dnt->d_name))
{
dnt = readdir(handle);
if(dnt == 0)
{
closedir(handle);
return;
}
}
struct stat fst;
if(stat((path_ + dnt->d_name).c_str(), &fst) == 0)
{
value_ = value_type(nana::charset(dnt->d_name), 0 != S_ISDIR(fst.st_mode), fst.st_size);
}
else
{
value_.m_path = nana::charset(dnt->d_name);
value_.size = 0;
value_.directory = false;
}
end_ = false;
}
}
#endif
if(false == end_)
{
find_ptr_ = std::shared_ptr<find_handle_t>(new find_handle_t(handle), inner_handle_deleter());
handle_ = handle;
}
}
void _m_read()
{
if(handle_)
{
#if defined(NANA_WINDOWS)
if(::FindNextFile(handle_, &wfd_) != 0)
{
while(_m_ignore(wfd_.cFileName))
{
if(::FindNextFile(handle_, &wfd_) == 0)
{
end_ = true;
return;
}
}
value_ = value_type(wfd_.cFileName,
(FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY,
wfd_.nFileSizeLow);
}
else
end_ = true;
#elif defined(NANA_LINUX)
struct dirent * dnt = readdir(handle_);
if(dnt)
{
while(_m_ignore(dnt->d_name))
{
dnt = readdir(handle_);
if(dnt == 0)
{
end_ = true;
return;
}
}
struct stat fst;
if(stat((path_ + "/" + dnt->d_name).c_str(), &fst) == 0)
value_ = value_type(wfd_.cFileName,
(FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY,
wfd_.nFileSizeLow);
else
value_.m_path = nana::charset(dnt->d_name);
}
else
end_ = true;
#endif
}
}
private:
struct inner_handle_deleter
{
void operator()(find_handle_t * handle)
{
if(handle && *handle)
{
#if defined(NANA_WINDOWS)
::FindClose(*handle);
#elif defined(NANA_LINUX)
::closedir(*handle);
#endif
}
delete handle;
}
};
private:
bool end_{false};
#if defined(NANA_WINDOWS)
WIN32_FIND_DATA wfd_;
nana::string path_;
#elif defined(NANA_LINUX)
std::string path_;
#endif
std::shared_ptr<find_handle_t> find_ptr_;
find_handle_t handle_{nullptr};
value_type value_;
};
//class recursive_directory_iterator;
//// enable recursive_directory_iterator range-based for statements
//recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
//recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
//template<typename Value_Type>
inline bool operator==(const directory_iterator/*<Value_Type>*/ & x, const directory_iterator/*<Value_Type>*/ & y)
{
return x.equal(y);
}
//template<typename Value_Type>
inline bool operator!=(const directory_iterator/*<Value_Type>*/ & x, const directory_iterator/*<Value_Type>*/ & y)
{
return !x.equal(y);
}
// file_status status(const path& p);
bool file_attrib(const nana::string& file, attribute&);
inline bool is_directory(file_status s) { return s.type() == file_type::directory ;}
inline bool is_directory(const path& p) { return directory_iterator{ p }->attr.directory; }//works??
inline bool is_directory(const directory_entry& d) { return d.attr.directory; }
//bool is_directory(const path& p, error_code& ec) noexcept;
//bool is_regular_file(file_status s) noexcept;
inline bool is_empty(const path& p)
{
directory_iterator d(p) ;
return d->attr.directory ? d == directory_iterator()
: d->attr.size == 0;
}
//bool is_empty(const path& p, error_code& ec) noexcept;
uintmax_t file_size(const nana::string& file); // deprecate?
inline uintmax_t file_size(const path& p){return file_size(p.filename());}
//uintmax_t file_size(const path& p, error_code& ec) noexcept;
//long long filesize(const nana::string& file);
bool create_directories(const path& p);
//bool create_directories(const path& p, error_code& ec) noexcept;
bool create_directory(const path& p);
//bool create_directory(const path& p, error_code& ec) noexcept;
bool create_directory(const path& p, const path& attributes);
//bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept;
bool create_directory(const nana::string& dir, bool & if_exist);
inline bool create_directory(const path& p, bool & if_exist)
{
return create_directory(p.filename(), if_exist);
};
bool modified_file_time(const nana::string& file, struct tm&);
nana::string path_user();
path current_path();
//path current_path(error_code& ec);
void current_path(const path& p);
//void current_path(const path& p, error_code& ec) noexcept;
//nana::string path_current();
//bool remove(const path& p);
//bool remove(const path& p, error_code& ec) noexcept;
bool rmfile(const nana::char_t* file);
//uintmax_t remove_all(const path& p);
//uintmax_t remove_all(const path& p, error_code& ec) noexcept;
bool rmdir(const nana::char_t* dir, bool fails_if_not_empty);
nana::string root(const nana::string& path);
}//end namespace filesystem
} //end namespace experimental
}//end namespace nana
#endif

View File

@@ -84,6 +84,7 @@ namespace nana
end_of_medium = 0x19, //Ctrl+Y
substitute = 0x1A, //Ctrl+Z
escape = 0x1B,
space = 0x20, //Space
//The following names are intuitive name of ASCII control codes
select_all = start_of_headline,

View File

@@ -25,6 +25,11 @@ namespace detail
{
struct basic_window;
enum class visible_state
{
invisible, visible, displayed
};
class caret_descriptor
{
public:
@@ -43,15 +48,16 @@ namespace detail
void size(const ::nana::size&);
void update();
private:
void _m_visible(bool isshow);
//private:
//void _m_visible(bool isshow); //deprecated
private:
core_window_t* wd_;
::nana::point point_;
::nana::size size_;
::nana::size paint_size_;
bool visible_;
bool real_visible_state_;
visible_state visible_state_;
//bool visible_;
//bool real_visible_state_; //deprecated
bool out_of_range_;
::nana::rectangle effective_range_;
};//end class caret_descriptor
@@ -112,7 +118,9 @@ namespace detail
bool is_ancestor_of(const basic_window* wd) const;
bool visible_parents() const;
bool displayed() const;
bool belong_to_lazy() const;
const basic_window * child_caret() const; //Returns a child which owns a caret
bool is_draw_through() const; ///< Determines whether it is a draw-through window.

View File

@@ -44,7 +44,7 @@ namespace detail
~bedrock();
void pump_event(window, bool is_modal);
void map_thread_root_buffer(core_window_t*, bool forced);
void map_thread_root_buffer(core_window_t*, bool forced, const rectangle* update_area = nullptr);
static int inc_window(unsigned tid = 0);
thread_context* open_thread_context(unsigned tid = 0);
thread_context* get_thread_context(unsigned tid = 0);

View File

@@ -23,12 +23,18 @@ namespace nana
{
class widget;
namespace detail
{
class drawer;
}
class drawer_trigger
: ::nana::noncopyable, ::nana::nonmovable
{
friend class detail::drawer;
public:
typedef widget& widget_reference;
typedef paint::graphics& graph_reference;
using widget_reference = widget&;
using graph_reference = paint::graphics&;
virtual ~drawer_trigger();
virtual void attached(widget_reference, graph_reference); //none-const
@@ -56,10 +62,11 @@ namespace nana
virtual void key_release(graph_reference, const arg_keyboard&);
virtual void shortkey(graph_reference, const arg_keyboard&);
void _m_reset_overrided();
bool _m_overrided() const;
private:
bool overrided_{false};
void _m_reset_overrided();
bool _m_overrided(event_code) const;
private:
unsigned overrided_{ 0xFFFFFFFF };
};
namespace detail
@@ -83,7 +90,7 @@ namespace nana
enum class method_state
{
unknown,
pending,
overrided,
not_overrided
};
@@ -110,7 +117,7 @@ namespace nana
void key_char(const arg_keyboard&);
void key_release(const arg_keyboard&);
void shortkey(const arg_keyboard&);
void map(window, bool forced); //Copy the root buffer to screen
void map(window, bool forced, const rectangle* update_area = nullptr); //Copy the root buffer to screen
void refresh();
drawer_trigger* realizer() const;
void attached(widget&, drawer_trigger&);
@@ -128,31 +135,27 @@ namespace nana
template<typename Arg, typename Mfptr>
void _m_emit(event_code evt_code, const Arg& arg, Mfptr mfptr)
{
if (realizer_)
const int pos = static_cast<int>(evt_code);
if (realizer_ && (method_state::not_overrided != mth_state_[pos]))
{
const int pos = static_cast<int>(evt_code);
if (method_state::not_overrided != mth_state_[pos])
_m_bground_pre();
if (method_state::pending == mth_state_[pos])
{
_m_bground_pre();
(realizer_->*mfptr)(graphics, arg);
//Check realizer, when the window is closed in that event handler, the drawer will be
//detached and realizer will be a nullptr
if(realizer_)
mth_state_[pos] = (realizer_->_m_overrided(evt_code) ? method_state::overrided : method_state::not_overrided);
}
else
(realizer_->*mfptr)(graphics, arg);
if (method_state::unknown == mth_state_[pos])
{
realizer_->_m_reset_overrided();
(realizer_->*mfptr)(graphics, arg);
//Check realizer, when the window is closed in that event handler, the drawer will be
//detached and realizer will be a nullptr
if(realizer_)
mth_state_[pos] = (realizer_->_m_overrided() ? method_state::overrided : method_state::not_overrided);
}
else
(realizer_->*mfptr)(graphics, arg);
if (_m_lazy_decleared())
{
_m_draw_dynamic_drawing_object();
_m_bground_end();
}
if (_m_lazy_decleared())
{
_m_draw_dynamic_drawing_object();
_m_bground_end();
}
}
}

View File

@@ -13,9 +13,9 @@ namespace nana{
{
edge_nimbus_renderer() = default;
public:
typedef CoreWindow core_window_t;
typedef window_layout window_layer;
typedef nana::paint::graphics & graph_reference;
using core_window_t = CoreWindow;
using window_layer = window_layout;
using graph_reference = ::nana::paint::graphics&;
static edge_nimbus_renderer& instance()
{
@@ -23,37 +23,69 @@ namespace nana{
return object;
}
std::size_t weight() const
unsigned weight() const
{
return 2;
}
bool render(core_window_t * wd, bool forced)
void erase(core_window_t* wd)
{
bool rendered = false;
if (effects::edge_nimbus::none == wd->effect.edge_nimbus)
return;
core_window_t * root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
if(nimbus.size())
for (auto i = nimbus.cbegin(); i != nimbus.cend(); ++i)
{
core_window_t * focused = root_wd->other.attribute.root->focus;
native_window_type native = root_wd->root;
std::size_t pixels = weight();
if (i->window == wd)
{
auto pixels = weight();
rectangle r{wd->pos_root, wd->dimension};
r.x -= static_cast<int>(pixels);
r.y -= static_cast<int>(pixels);
r.width += static_cast<unsigned>(pixels << 1);
r.height += static_cast<unsigned>(pixels << 1);
root_wd->root_graph->paste(root_wd->root, r, r.x, r.y);
nimbus.erase(i);
break;
}
}
}
void render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr)
{
bool copy_separately = true;
std::vector<std::pair<rectangle, core_window_t*>> rd_set;
if (wd->root_widget->other.attribute.root->effects_edge_nimbus.size())
{
auto root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
auto focused = root_wd->other.attribute.root->focus;
const unsigned pixels = weight();
auto graph = root_wd->root_graph;
std::vector<core_window_t*> erase;
std::vector<std::pair<rectangle,core_window_t*>> rd_set;
nana::rectangle r;
for(auto & action : nimbus)
{
if(_m_edge_nimbus(focused, action.window) && window_layer::read_visual_rectangle(action.window, r))
{
if(action.window == wd)
rendered = true;
if (action.window == wd)
{
if (update_area)
::nana::overlap(*update_area, rectangle(r), r);
copy_separately = false;
}
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
if ((forced && (action.window == wd)) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
{
rd_set.emplace_back(r, action.window);
action.rendered = true;
@@ -62,29 +94,36 @@ namespace nana{
else if(action.rendered)
{
action.rendered = false;
erase.push_back(action.window);
if (action.window == wd)
copy_separately = false;
::nana::rectangle erase_r(
action.window->pos_root.x - static_cast<int>(pixels),
action.window->pos_root.y - static_cast<int>(pixels),
static_cast<unsigned>(action.window->dimension.width + (pixels << 1)),
static_cast<unsigned>(action.window->dimension.height + (pixels << 1))
);
graph->paste(root_wd->root, erase_r, erase_r.x, erase_r.y);
}
}
//Erase
for(auto el : erase)
{
if(el == wd)
rendered = true;
r.x = el->pos_root.x - static_cast<int>(pixels);
r.y = el->pos_root.y - static_cast<int>(pixels);
r.width = static_cast<unsigned>(el->dimension.width + (pixels << 1));
r.height = static_cast<unsigned>(el->dimension.height + (pixels << 1));
graph->paste(native, r, r.x, r.y);
}
//Render
for (auto & rd : rd_set)
_m_render_edge_nimbus(rd.second, rd.first);
}
return rendered;
if (copy_separately)
{
rectangle vr;
if (window_layer::read_visual_rectangle(wd, vr))
{
if (update_area)
::nana::overlap(*update_area, rectangle(vr), vr);
wd->root_graph->paste(wd->root, vr, vr.x, vr.y);
}
}
//Render
for (auto & rd : rd_set)
_m_render_edge_nimbus(rd.second, rd.first);
}
private:
static bool _m_edge_nimbus(core_window_t * focused_wd, core_window_t * wd)
@@ -103,8 +142,8 @@ namespace nana{
rectangle good_r;
if (overlap(r, rectangle{ wd->root_graph->size() }, good_r))
{
if( (good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) ||
(good_r.x + good_r.width > visual.x + visual.width) || (good_r.y + good_r.height > visual.y + visual.height))
if ((good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) ||
(good_r.right() > visual.right()) || (good_r.bottom() > visual.bottom()))
{
auto graph = wd->root_graph;
nana::paint::pixel_buffer pixbuf(graph->handle(), r);

View File

@@ -121,7 +121,6 @@ namespace nana{
{
core_window_t* pressed{nullptr}; //The handle to a window which is being pressed
core_window_t* hovered{nullptr}; //the latest window that mouse moved
bool tabstop_focus_changed{false}; //KeyDown may set it true, if it is true KeyChar will ignore the message
}condition;
root_misc(core_window_t * wd, unsigned width, unsigned height)

View File

@@ -70,13 +70,11 @@ namespace detail
std::vector<thr_refcnt> stack_;
};
public:
typedef native_window_type native_window;
typedef revertible_mutex mutex_type;
using native_window = native_window_type;
using mutex_type = revertible_mutex;
typedef basic_window core_window_t;
typedef std::vector<core_window_t*> cont_type;
typedef window_layout wndlayout_type;
using core_window_t = basic_window;
using window_layer = window_layout;
window_manager();
~window_manager();
@@ -126,9 +124,9 @@ namespace detail
core_window_t* root(native_window_type) const;
//Copy the root buffer that wnd specified into DeviceContext
void map(core_window_t*, bool forced);
void map(core_window_t*, bool forced, const rectangle* update_area = nullptr);
bool update(core_window_t*, bool redraw, bool force);
bool update(core_window_t*, bool redraw, bool force, const rectangle* update_area = nullptr);
void refresh_tree(core_window_t*);
bool do_lazy_refresh(core_window_t*, bool force_copy_to_screen);

View File

@@ -34,27 +34,38 @@ namespace nana
virtual const ::nana::rectangle& workarea() const = 0;
};
/// Provides some functions to get the metrics of the monitors \include screen.cpp
class screen
{
struct implement;
public:
static ::nana::size desktop_size();
static ::nana::size primary_monitor_size();
/// gets the size in pixel of the whole virtual desktop
static ::nana::size desktop_size();
/// gets the resolution in pixel of the primary monitor,
/// if there is only one monitor installed in the system,
/// the return value of primary_monitor_size is equal to desktop_size's.
static ::nana::size primary_monitor_size();
screen();
/// Reload has no preconditions, it's safe to call on moved-from
void reload();
/// Returns the number of display monitors
/// Returns the number of display monitors installed in the system
std::size_t count() const;
/// gets the display monitor that contains the specified point
display& from_point(const point&);
/// gets the display monitor that contains the specified window
display& from_window(window);
display& get_display(std::size_t index) const;
display& get_primary() const;
/// applies a given function to all display monitors
void for_each(std::function<void(display&)>) const;
private:
std::shared_ptr<implement> impl_;

View File

@@ -166,9 +166,13 @@ namespace nana
std::size_t pos_{0};
};
//struct essence_t
//@brief: this struct gives many data for listbox,
// the state of the struct does not effect on member funcions, therefore all data members are public.
typedef std::vector<index_pair> selection;
/// struct essence_t
///@brief: this struct gives many data for listbox,
/// the state of the struct does not effect on member funcions, therefore all data members are public.
struct essence_t;
struct category_t;
@@ -371,13 +375,17 @@ namespace nana
return iter;
}
void append(std::initializer_list<nana::string>);
/// Appends one item at the end of this category with the specifies text in the column fields
void append(std::initializer_list<nana::string>);
size_type columns() const;
cat_proxy& text(nana::string);
nana::string text() const;
cat_proxy & select(bool);
bool selected() const;
/// Behavior of a container
void push_back(nana::string);
@@ -480,16 +488,54 @@ namespace nana
color_proxy header_grabbed{ static_cast<color_rgb>(0x8BD6F6)};
color_proxy header_floated{ static_cast<color_rgb>(0xBABBBC)};
color_proxy item_selected{ static_cast<color_rgb>(0xD5EFFC) };
unsigned max_header_width{3000}, /// \todo how to implement some geometrical parameters ??
ext_w = 5;
};
}
}//end namespace drawerbase
/*! \brief A rectangle containing a list of strings from which the user can select. This widget contain a list of \a categories, with in turn contain a list of \a items.
/*! \class listbox
\brief A rectangle containing a list of strings from which the user can select. This widget contain a list of \a categories, with in turn contain a list of \a items.
A category is a text with can be \a selected, \a checked and \a expanded to show the items.
An item is formed by \a column-fields, each corresponding to one of the \a headers.
An item can be \a selected and \a checked.
The user can \a drag the header to \a reisize it or to \a reorganize it.
By \a clicking on a header the list get \a reordered, first up, and then down alternatively.
The user can \a drag the header to \a resize it or to \a reorganize it.
By \a clicking on one header the list get \a reordered, first up, and then down alternatively.
1. The resolver is used to resolute an object of the specified type for a listbox item.
3. nana::listbox creates the category 0 by default. The member functions without the categ parameter operate the items that belong to category 0.
4. A sort compare is used for sorting the items. It is a strict weak ordering comparer that must meet the requirement:
Irreflexivity (comp(x, x) returns false)
and
antisymmetry(comp(a, b) != comp(b, a) returns true)
A simple example.
bool sort_compare( const nana::string& s1, nana::any*,
const nana::string& s2, nana::any*, bool reverse)
{
return (reverse ? s1 > s2 : s1 < s2);
}
listbox.set_sort_compare(0, sort_compare);
The listbox supports attaching a customer's object for each item, therefore the items can be
sorted by comparing these customer's object.
bool sort_compare( const nana::string&, nana::any* o1,
const nana::string&, nana::any* o2, bool reverse)
{
if(o1 && o2) //some items may not attach a customer object.
{
int * i1 = o1->get<int>();
int * i2 = o2->get<int>();
return (i1 && i2 && (reverse ? *i1 > *i2 : *i1 < *i2));
;//some types may not be int.
}
return false;
}
listbox.anyobj(0, 0, 10); //the type of customer's object is int.
listbox.anyobj(0, 0, 20);
\todo doc: actualize this example listbox.at(0)...
\see nana::drawerbase::listbox::cat_proxy
\see nana::drawerbase::listbox::item_proxy
\example listbox_Resolver.cpp
*/
class listbox
: public widget_object<category::widget_tag, drawerbase::listbox::trigger, drawerbase::listbox::listbox_events, drawerbase::listbox::scheme>,
@@ -512,14 +558,17 @@ By \a clicking on a header the list get \a reordered, first up, and then down al
listbox(window, bool visible);
listbox(window, const rectangle& = {}, bool visible = true);
void auto_draw(bool); ///<Set state: Redraw automatically after an operation?
void auto_draw(bool); ///< Set state: Redraw automatically after an operation?
void append_header(nana::string, unsigned width = 120);///<Appends a new column with a header text and the specified width at the end
listbox& header_width(size_type pos, unsigned pixels);
unsigned header_width(size_type pos) const;
/// Appends a new column with a header text and the specified width at the end, and return it position
size_type append_header(nana::string header_text, unsigned width = 120);
listbox& header_width(size_type position, unsigned pixels);
unsigned header_width(size_type position) const;
unsigned auto_width(size_type position, unsigned max=3000);
cat_proxy append(nana::string); ///<Appends a new category at the end
void append(std::initializer_list<nana::string>); ///<Appends categories at the end
cat_proxy append(nana::string); ///< Appends a new category at the end
void append(std::initializer_list<nana::string>); ///< Appends categories at the end
cat_proxy insert(cat_proxy, nana::string);
cat_proxy at(size_type pos) const;

View File

@@ -108,7 +108,7 @@ namespace nana
virtual void background(graph_reference, window) = 0;
virtual void item(graph_reference, const nana::rectangle&, const attr&) = 0;
virtual void item_image(graph_reference, const nana::point&, const paint::image&) = 0;
virtual void item_image(graph_reference, const nana::point&, unsigned image_px, const paint::image&) = 0;
virtual void item_text(graph_reference, const nana::point&, const nana::string&, unsigned text_pixels, const attr&) = 0;
virtual void sub_arrow(graph_reference, const nana::point&, unsigned item_pixels, const attr&) = 0;
};

View File

@@ -30,6 +30,8 @@ namespace nana
unsigned Max(unsigned);
void unknown(bool);
bool unknown() const;
bool stop(bool s = true);
bool stoped() const;
private:
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
@@ -45,6 +47,7 @@ namespace nana
nana::paint::graphics* graph_{nullptr};
unsigned draw_width_{static_cast<unsigned>(-1)};
bool unknown_{false};
bool stop_{false};
unsigned max_{100};
unsigned value_{0};
}; //end class drawer
@@ -67,6 +70,8 @@ namespace nana
unsigned amount(unsigned value);
void unknown(bool);
bool unknown() const;
bool stop(bool s=true); ///< request stop or cancel and return previus stop status
bool stoped() const;
};
}//end namespace nana
#endif

View File

@@ -14,7 +14,6 @@
#define NANA_GUI_WIDGET_TOOLBAR_HPP
#include "widget.hpp"
#include <vector>
namespace nana
{
@@ -39,10 +38,10 @@ namespace nana
basic_event<arg_toolbar> selected; ///< A mouse click on a control button.
basic_event<arg_toolbar> enter; ///< The mouse enters a control button.
basic_event<arg_toolbar> leave; ///< The mouse leaves a control button.
};
struct item_type;
class item_container;
class drawer
: public drawer_trigger
@@ -50,15 +49,12 @@ namespace nana
struct drawer_impl_type;
public:
typedef std::size_t size_type;
using size_type = std::size_t;
drawer();
~drawer();
void append(const nana::string&, const nana::paint::image&);
void append();
bool enable(size_type) const;
bool enable(size_type, bool);
item_container& items() const;
void scale(unsigned);
private:
void refresh(graph_reference) override;
@@ -69,32 +65,28 @@ namespace nana
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
private:
size_type _m_which(int x, int y, bool want_if_disabled) const;
void _m_draw_background(const ::nana::color&);
void _m_draw();
void _m_owner_sized(const arg_resized&);
private:
void _m_fill_pixels(item_type*, bool force);
size_type _m_which(point, bool want_if_disabled) const;
void _m_calc_pixels(item_type*, bool force);
private:
::nana::toolbar* widget_;
::nana::paint::graphics* graph_;
drawer_impl_type* impl_;
};
}//end namespace toolbar
}//end namespace drawerbase
/// Control bar that contains buttons for controlling
class toolbar
: public widget_object<category::widget_tag, drawerbase::toolbar::drawer, drawerbase::toolbar::toolbar_events>
{
public:
typedef std::size_t size_type; ///< A type to count the number of elements.
using size_type = std::size_t; ///< A type to count the number of elements.
toolbar() = default;
toolbar(window, bool visible);
toolbar(window, const rectangle& = rectangle(), bool visible = true);
void append(); ///< Adds a separator.
void separate(); ///< Adds a separator.
void append(const nana::string& text, const nana::paint::image& img); ///< Adds a control button.
void append(const nana::string& text); ///< Adds a control button.
bool enable(size_type index) const;