first init of 0.9

This commit is contained in:
cnjinhao
2014-12-11 03:32:35 +08:00
commit d0a317bd45
206 changed files with 69773 additions and 0 deletions

145
include/nana/any.hpp Normal file
View File

@@ -0,0 +1,145 @@
#ifndef NANA_ANY_HPP
#define NANA_ANY_HPP
#include <typeinfo>
#include <utility> //C++11 for std::move
namespace nana
{
class any
{
struct super_type
{
virtual ~super_type();
super_type& operator=(const super_type&);
virtual super_type& assign(const super_type&) = 0;
virtual bool same(const super_type&) const = 0;
virtual super_type* clone() const = 0;
}; //end struct super_type
template<typename T>
struct object_type
: public super_type
{
object_type(){}
object_type(T const & obj)
: object(obj)
{}
object_type(T && obj)
: object(std::move(obj))
{}
object_type(const object_type& rhs)
:object(rhs.object)
{}
virtual super_type& assign(const super_type& rhs)
{
if(this != &rhs)
{
auto other = dynamic_cast<const object_type*>(&rhs);
if(other)
object = other->object;
}
return *this;
}
virtual bool same(const super_type& rhs) const
{
return (dynamic_cast<const object_type*>(&rhs) != nullptr);
}
virtual super_type* clone() const
{
return new object_type(object);
}
T object;
}; //end struct object_type
public:
template<typename T>
any(const T & obj)
: super_(new object_type<typename std::remove_reference<T>::type>(obj))
{}
template<typename T>
any(T && obj)
: super_(new object_type<typename std::remove_reference<T>::type>(std::move(obj)))
{}
any();
any(const any&);
any(any&&);
~any();
bool same(const any &) const;
any& operator=(const any&);
any& operator=(any&&);
template<typename T>
any& operator=(T const &rhs)
{
T * obj = get<T>();
if(nullptr == obj)
{
delete super_;
super_ = new object_type<T>(rhs);
}
else
*obj = rhs;
return *this;
}
template<typename T>
any & operator=(T && rhs)
{
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
type* obj = get<type>();
if(nullptr == obj)
{
delete super_;
super_ = new object_type<type>(std::move(rhs));
}
else
*obj = std::move(rhs);
return *this;
}
template<typename T>
T * get() const
{
if(super_)
{
typedef typename std::remove_const<T>::type type;
object_type<type>* obj = dynamic_cast<object_type<type>*>(super_);
if(obj) return &(obj->object);
}
return nullptr;
}
template<typename T>
operator T&() const
{
typedef typename std::remove_const<T>::type type;
type *obj = get<type>();
if(nullptr == obj)
throw std::bad_cast();
return *obj;
}
template<typename T>
operator T*() const
{
typedef typename std::remove_const<T>::type type;
return get<type>();
}
private:
super_type * super_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,53 @@
#ifndef NANA_AUDIO_DETAIL_AUDIO_DEVICE_HPP
#define NANA_AUDIO_DETAIL_AUDIO_DEVICE_HPP
#include <nana/deploy.hpp>
#include <nana/audio/detail/buffer_preparation.hpp>
#include <vector>
#if defined(NANA_WINDOWS)
#include <windows.h>
#elif defined(NANA_LINUX)
#include <alsa/asoundlib.h>
#endif
namespace nana{ namespace audio
{
namespace detail
{
class audio_device
{
public:
audio_device();
~audio_device();
bool empty() const;
bool open(std::size_t channels, std::size_t rate, std::size_t bits_per_sample);
void close();
void prepare(buffer_preparation & buf_prep);
void write(buffer_preparation::meta * m);
void wait_for_drain() const;
private:
#if defined(NANA_WINDOWS)
static void __stdcall _m_dev_callback(HWAVEOUT handle, UINT msg, audio_device * self, DWORD_PTR, DWORD_PTR);
#endif
#if defined(NANA_WINDOWS)
HWAVEOUT handle_;
std::recursive_mutex queue_lock_;
std::vector<buffer_preparation::meta*> done_queue_;
#elif defined(NANA_LINUX)
snd_pcm_t * handle_;
std::size_t rate_;
std::size_t channels_;
std::size_t bytes_per_sample_;
std::size_t bytes_per_frame_;
#endif
buffer_preparation * buf_prep_;
};
}//end namespace detail
}//end namespace audio
}//end namespace nana
#endif

View File

@@ -0,0 +1,81 @@
#ifndef NANA_AUDIO_DETAIL_AUDIO_STREAM_HPP
#define NANA_AUDIO_DETAIL_AUDIO_STREAM_HPP
#include <fstream>
#include <nana/deploy.hpp>
namespace nana{ namespace audio{
namespace detail
{
namespace wave_spec
{
#if defined(NANA_WINDOWS)
#pragma pack(1)
struct master_riff_chunk
{
unsigned long ckID; //"RIFF"
unsigned long cksize;
unsigned long waveID; //"WAVE"
};
struct format_chunck
{
unsigned long ckID; //"fmt "
unsigned long cksize;
unsigned short wFormatTag;
unsigned short nChannels;
unsigned long nSamplePerSec;
unsigned long nAvgBytesPerSec;
unsigned short nBlockAlign;
unsigned short wBitsPerSample;
};
#pragma pack()
#elif defined(NANA_LINUX)
struct master_riff_chunk
{
unsigned long ckID; //"RIFF"
unsigned long cksize;
unsigned long waveID; //"WAVE"
}__attribute__((packed));
struct format_chunck
{
unsigned long ckID; //"fmt "
unsigned long cksize;
unsigned short wFormatTag;
unsigned short nChannels;
unsigned long nSamplePerSec;
unsigned long nAvgBytesPerSec;
unsigned short nBlockAlign;
unsigned short wBitsPerSample;
}__attribute__((packed));
#endif
}
class audio_stream
{
struct chunck
{
unsigned long ckID;
unsigned long cksize;
};
public:
bool open(const nana::string& file);
void close();
bool empty() const;
const wave_spec::format_chunck & format() const;
std::size_t data_length() const;
void locate();
std::size_t read(void * buf, std::size_t len);
private:
std::size_t _m_locate_chunck(unsigned ckID);
private:
std::ifstream fs_;
wave_spec::format_chunck ck_format_;
std::size_t pcm_data_pos_;
std::size_t pcm_data_size_;
std::size_t data_size_;
}; //end class audio_stream
}
}//end namespace audio
}//end namespace nana
#endif

View File

@@ -0,0 +1,65 @@
#ifndef NANA_AUDIO_DETAIL_BUFFER_PREPARATION_HPP
#define NANA_AUDIO_DETAIL_BUFFER_PREPARATION_HPP
#include <nana/deploy.hpp>
#include <nana/audio/detail/audio_stream.hpp>
#if defined(NANA_MINGW) && defined(STD_THREAD_NOT_SUPPORTED)
#include <nana/std_thread.hpp>
#include <nana/std_mutex.hpp>
#include <nana/std_condition_variable.hpp>
#else
#include <mutex>
#include <condition_variable>
#include <thread>
#endif
#include <sstream>
#include <vector>
#if defined(NANA_WINDOWS)
#include <windows.h>
#endif
namespace nana{ namespace audio
{
namespace detail
{
class buffer_preparation
{
public:
#if defined(NANA_WINDOWS)
typedef WAVEHDR meta;
#elif defined(NANA_LINUX)
struct meta
{
char * buf;
std::size_t bufsize;
};
#endif
public:
buffer_preparation(audio_stream& as, std::size_t seconds);
~buffer_preparation();
meta * read();
//Revert the meta that returned by read()
void revert(meta * m);
bool data_finished() const;
private:
void _m_prepare_routine();
private:
volatile bool running_;
volatile bool wait_for_buffer_;
std::thread thr_;
mutable std::mutex token_buffer_, token_prepared_;
mutable std::condition_variable cond_buffer_, cond_prepared_;
std::vector<meta*> buffer_, prepared_;
std::size_t block_size_;
audio_stream & as_;
};
}//end namespace detail
}//end namespace audio
}//end namespace nana
#endif

View File

@@ -0,0 +1,25 @@
#ifndef NANA_AUDIO_PLAYER_HPP
#define NANA_AUDIO_PLAYER_HPP
#include <nana/traits.hpp>
#include <nana/deploy.hpp>
namespace nana{ namespace audio
{ /// play an audio file in Windows WAV format
class player
: private nana::noncopyable
{
struct implementation;
public:
player();
player(const nana::string& file);
~player();
bool open(const nana::string& file);
void play();
void close();
private:
implementation* impl_;
};
}//end namespace audio
}//end namespace nana
#endif

View File

@@ -0,0 +1,254 @@
/*
* Basic Types definition
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/basic_types.hpp
*/
#ifndef NANA_BASIC_TYPES_HPP
#define NANA_BASIC_TYPES_HPP
#include <nana/deploy.hpp>
namespace nana
{
//A constant value for the invalid position.
const std::size_t npos = static_cast<std::size_t>(-1);
template<typename CharT>
struct casei_char_traits
: public std::char_traits<CharT>
{
typedef CharT char_type;
//static constexpr bool eq(char_type c1, char_type c2) noexcept
//VC2012 does not support constexpr and noexcept keywords
static bool eq(char_type c1, char_type c2)
{
return std::toupper(c1) == std::toupper(c2);
}
//static constexpr bool lt(char_type c1, char_type c2) noexcept
//VC2012 does not support constexpr and noexcept keywords
static bool lt(char_type c1, char_type c2)
{
return std::toupper(c1) < std::toupper(c2);
}
static int compare(const char_type* s1, const char_type* s2, std::size_t n)
{
while(n--)
{
char_type c1 = std::toupper(*s1);
char_type c2 = std::toupper(*s2);
if(c1 < c2) return -1;
if(c1 > c2) return 1;
++s1;
++s2;
}
return 0;
}
static const char_type* find(const char_type* s, std::size_t n, const char_type& a)
{
char_type ua = std::toupper(a);
const char_type * end = s + n;
while((s != end) && (std::toupper(*s) != ua))
++s;
return (s == end ? nullptr : s);
}
};
typedef std::basic_string<nana::char_t, casei_char_traits<nana::char_t> > cistring;
namespace detail
{
struct drawable_impl_type; //declearation, defined in platform_spec.hpp
}
namespace paint
{
typedef nana::detail::drawable_impl_type* drawable_type;
}
enum class mouse_action
{
begin, normal = begin, over, pressed, end
};
enum class element_state
{
normal,
hovered,
focus_normal,
focus_hovered,
pressed,
disabled
};
typedef unsigned scalar_t;
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
typedef unsigned uint_t;
typedef unsigned color_t;
typedef long long long_long_t;
const color_t null_color = 0xFFFFFFFF;
struct pixel_rgb_t
{
union
{
struct element_tag
{
unsigned int blue:8;
unsigned int green:8;
unsigned int red:8;
unsigned int alpha_channel:8;
}element;
color_t color;
}u;
};
struct rectangle;
struct point
{
point();
point(int x, int y);
point(const rectangle&);
point& operator=(const rectangle&);
bool operator==(const point&) const;
bool operator!=(const point&) const;
bool operator<(const point&) const;
bool operator<=(const point&) const;
bool operator>(const point&) const;
bool operator>=(const point&) const;
point operator-(const point&) const;
point operator+(const point&) const;
point& operator-=(const point&);
point& operator+=(const point&);
int x;
int y;
};
struct upoint
{
typedef unsigned value_type;
upoint();
upoint(value_type x, value_type y);
bool operator==(const upoint&) const;
bool operator!=(const upoint&) const;
bool operator<(const upoint&) const;
bool operator<=(const upoint&) const;
bool operator>(const upoint&) const;
bool operator>=(const upoint&) const;
value_type x;
value_type y;
};
struct size
{
size();
size(unsigned width, unsigned height);
size(const rectangle&);
size& operator=(const rectangle&);
bool empty() const; ///< true if width * height == 0
bool is_hit(const point&) const; ///< Assume it is a rectangle at (0,0), and check whether a specified position is in the rectange.
bool operator==(const size& rhs) const;
bool operator!=(const size& rhs) const;
size operator+(const size&) const;
unsigned width;
unsigned height;
};
struct rectangle
{
rectangle(); ///< a zero-size rectangle at (0, 0).
rectangle(int x, int y, unsigned width, unsigned height);
rectangle(const size &); ///< a rectangle with specified size at coordinate (0, 0).
rectangle(const point&, const size& = size());
bool operator==(const rectangle& rhs) const;
bool operator!=(const rectangle& rhs) const;
rectangle& operator=(const point&);
rectangle& operator=(const size&);
rectangle& set_pos(const point&);
rectangle& set_size(const size&);
rectangle& pare_off(int pixels); ///<Pares the specified pixels off the rectangle. It's equal to x += pixels; y + pixels; width -= (pixels << 1); height -= (pixels << 1);
int right() const;
int bottom() const;
bool is_hit(int x, int y) const;
bool is_hit(const point& pos) const;
bool empty() const; ///< true if width * height == 0
int x;
int y;
unsigned width;
unsigned height;
};
class area_rotator
{
public:
area_rotator(bool rotated, const ::nana::rectangle& area);
int x() const;
int & x_ref();
int y() const;
int & y_ref();
unsigned w() const;
unsigned & w_ref();
unsigned h() const;
unsigned & h_ref();
int right() const;
int bottom() const;
const ::nana::rectangle& result() const;
private:
bool rotated_;
::nana::rectangle area_;
};//end class area_rotator
enum class arrange
{
unknown, horizontal, vertical, horizontal_vertical
};
///The definition of horizontal alignment
enum class align
{
left, center, right
};
///The definition of vertical alignment
enum class align_v
{
top, center, bottom
};
}//end namespace nana
#endif

67
include/nana/charset.hpp Normal file
View File

@@ -0,0 +1,67 @@
#ifndef NANA_CHARSET_HPP
#define NANA_CHARSET_HPP
#include <string>
namespace nana
{
enum class unicode
{
utf8, utf16, utf32
};
namespace detail
{
class charset_encoding_interface;
}
/// An intelligent charset class for character code conversion.
class charset
{
public:
charset(const charset&);
charset & operator=(const charset&);
charset(charset&&);
charset & operator=(charset&&);
charset(const std::string&); ///<Attempt to convert a multibytes string.
charset(std::string&&); ///<Attempt to convert a multibytes string.
charset(const std::string&, unicode);///<Attempt to convert a unicode string in byte sequence.
charset(std::string&&, unicode); ///<Attempt to convert a unicode string in byte sequence.
charset(const std::wstring&); ///<Attempt to convert a UCS2/UCS4 string.
charset(std::wstring&&); ///<Attempt to convert a UCS2/UCS4 string.
~charset();
operator std::string() const; ///<Converts the string to multibytes string.
operator std::string&&(); ///<Converts the string to multibytes string.
operator std::wstring() const; ///<Converts the string to UCS2/UCS4 string.
operator std::wstring&&(); ///<Converts the string to UCS2/UCS4 string.
std::string to_bytes(unicode) const; ///<Converts the string to a unicode in bytes sequenece width a specified unicode transformation format.
private:
detail::charset_encoding_interface* impl_;
};
}//end namespace nana
#endif
/*!\class charset
Example
1. A UTF-8 string from the socket.
int len = ::recv(sd, buf, buflen, 0);
textbox.caption(nana::charset(std::string(buf, len), nana::unicode::utf8));
2. Send the string in text to the socket as UTF-8.
std::string utf8str = nana::charset(textbox.caption()).to_bytes(nana::unicode::utf8);
::send(sd, utf8str.c_str(), utf8str.size(), 0);
3, Convert a string to the specified multi-byte character code.
//Convert to a multibytes string through default system language.
std::string mbstr = nana::charset(a_wstring);
//If the default system language is English and convert
//a Chinese unicode string to multibytes string through GB2312
std::setlocale(LC_CTYPE, "zh_CN.GB2312");
//set::setlocale(LC_CTYPE, ".936"); call it in Windows
std::string mbstr = nana::charset(a_wstring_with_chinese);
*/

132
include/nana/concepts.hpp Normal file
View File

@@ -0,0 +1,132 @@
/*
* A Concepts Definition of Nana C++ Library
* Copyright(C) 2003-2013 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: nana/concepts.hpp
*/
#ifndef NANA_CONCEPTS_HPP
#define NANA_CONCEPTS_HPP
#include <nana/any.hpp>
namespace nana
{
namespace concepts
{
/// The Any Objective is an object that may attach to some other object.
template<typename IndexType, int Dimension> // no dep. on IndexType ??
class any_objective
{
public:
virtual ~any_objective(){}
template<typename Target>
void anyobj(const Target& t)
{
nana::any * p = _m_anyobj(true);
if(nullptr == p)
throw std::runtime_error("Nana.any_objective: Object does not exist");
*p = t;
}
template<typename Target>
void anyobj(Target&& t)
{
nana::any * p = _m_anyobj(true);
if(nullptr == 0)
throw std::runtime_error("Nana.any_objective: Object does not exist");
*p = std::move(t);
}
template<typename Target>
Target * anyobj() const ///< Retrieves the attached object. Returns a nullptr if empty or if the type not match.
{
nana::any * p = _m_anyobj(false);
return (p ? p->get<Target>() : nullptr);
}
private:
virtual nana::any* _m_anyobj(bool allocate_if_empty) const = 0;
};
/// The Any Objective is an object that may attach to some other object.
template<typename IndexType>
class any_objective<IndexType, 1>
{
public:
typedef IndexType anyobj_index_t; ///< The type of index. It is available if Dimension is greater than 0.
virtual ~any_objective(){}
template<typename Target>
void anyobj(anyobj_index_t i, const Target& t)
{
nana::any * p = _m_anyobj(i, true);
if(nullptr == p)
throw std::runtime_error("Nana.any_objective: Object does not exist.");
*p = t;
}
template<typename Target>
void anyobj(anyobj_index_t i, Target&& t)
{
nana::any * p = _m_anyobj(i, true);
if(nullptr == p)
throw std::runtime_error("Nana.any_objective: Object does not exist");
*p = std::move(t);
}
template<typename Target>
Target * anyobj(anyobj_index_t i) const ///< Retrieves the attached object. Returns a nullptr if empty or if the type not match.
{
nana::any * p = _m_anyobj(i, false);
return (p ? p->get<Target>() : nullptr);
}
private:
virtual nana::any* _m_anyobj(anyobj_index_t i, bool allocate_if_empty) const = 0;
};
/// The Any Objective is an object that may attach to some other object.
template<typename IndexType>
class any_objective<IndexType, 2>
{
public:
typedef IndexType anyobj_index_t;
virtual ~any_objective(){}
template<typename Target>
void anyobj(anyobj_index_t i0, anyobj_index_t i1, const Target& t)
{
nana::any * p = _m_anyobj(i0, i1, true);
if(nullptr == p)
throw std::runtime_error("Nana.any_objective: Object does not exist");
*p = t;
}
template<typename Target>
void anyobj(anyobj_index_t i0, anyobj_index_t i1, Target&& t)
{
nana::any * p = _m_anyobj(i0, i1, true);
if(nullptr == p)
throw std::runtime_error("Nana.any_objective: Object does not exist");
*p = std::move(t);
}
template<typename Target>
Target * anyobj(anyobj_index_t i0, anyobj_index_t i1) const ///< Retrieves the attached object. Returns a nullptr if empty or if the type not match.
{
nana::any * p = _m_anyobj(i0, i1, false);
return (p ? p->get<Target>() : nullptr);
}
private:
virtual nana::any* _m_anyobj(anyobj_index_t i0, anyobj_index_t i1, bool allocate_if_empty) const = 0;
};
}//end namespace concepts
}//end namespace nana
#endif

62
include/nana/config.hpp Normal file
View File

@@ -0,0 +1,62 @@
/*
* Nana Configuration
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/config.hpp
*/
#ifndef NANA_CONFIG_HPP
#define NANA_CONFIG_HPP
//Select platform automatically
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
//Windows:
#define NANA_WINDOWS 1
#define PLATFORM_SPEC_HPP <nana/detail/win32/platform_spec.hpp>
#define GUI_BEDROCK_HPP <nana/gui/detail/bedrock.hpp>
//Test if it is MINGW
#if defined(__MINGW32__)
#define NANA_MINGW
#define STD_CODECVT_NOT_SUPPORTED
//#define STD_THREAD_NOT_SUPPORTED //Use this flag if MinGW version is older than 4.8.1
#endif
#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC)
//Linux:
#define NANA_LINUX 1
#define NANA_X11 1
#define PLATFORM_SPEC_HPP <nana/detail/linux_X11/platform_spec.hpp>
#define GUI_BEDROCK_HPP <nana/gui/detail/bedrock.hpp>
#define STD_CODECVT_NOT_SUPPORTED
#endif
//Here defines some flags that tell Nana what features will be supported.
#define NANA_UNICODE
#if defined(NANA_UNICODE) && defined(NANA_WINDOWS)
#ifndef _UNICODE
#define _UNICODE
#endif
#ifndef UNICODE
#define UNICODE
#endif
#endif
//Support for PNG
// Comment it to disable the feature of support for PNG.
//#define NANA_ENABLE_PNG
#if defined(NANA_ENABLE_PNG)
//Comment it to use libpng from operating system.
#define NANA_LIBPNG
#endif
#endif //NANA_CONFIG_HPP

75
include/nana/datetime.hpp Normal file
View File

@@ -0,0 +1,75 @@
/*
* A Date Time Implementation
* Copyright(C) 2003-2013 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: nana/datetime.hpp
*/
#ifndef NANA_DATETIME_HPP
#define NANA_DATETIME_HPP
#include <ctime>
namespace nana
{
/// A date operation class. \see nana::date_chooser
class date
{
public:
struct value
{
unsigned year; ///< 1601 - 30827
unsigned month; ///< 1-12
unsigned day; ///< 1-31
};
date(); ///< the initialized date is today.
date(const std::tm&);
date(int year, int month, int day);
date operator - (int off) const;
date operator + (int off) const;
bool operator==(const date&) const;
bool operator!=(const date&) const;
bool operator<(const date&) const;
bool operator>(const date&) const;
bool operator<=(const date&) const;
bool operator>=(const date&) const;
int day_of_week() const;
const value & read() const;
static int day_of_week(int year, int month, int day);
static unsigned year_days(unsigned year); ///< the number of days in the specified year.
static unsigned month_days(unsigned year, unsigned month); ///< the number of days in the specified month.
static unsigned day_in_year(unsigned y, unsigned m, unsigned d); ///< Returns the index of the specified day in this year, at range[1, 365] or [1, 366]
private:
date _m_add(unsigned x) const;
date _m_sub(unsigned x) const;
private:
value value_;
}; //end class date
class time
{
public:
struct value
{
unsigned hour; ///<[0-23]
unsigned minute; ///<[0-59]
unsigned second; ///<[0-61], the range of [60, 61] is used for leap seconds
};
time();
time(const std::tm&);
time(unsigned hour, unsigned minute, unsigned second);
const value& read() const;
private:
value value_;
};//end class time
}//end namespace nana
#endif

67
include/nana/deploy.hpp Normal file
View File

@@ -0,0 +1,67 @@
/*
* The Deploy Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/deploy.hpp
*
* What follow are dependented on what defined in nana/config.hpp
*/
#ifndef NANA_DEPLOY_HPP
#define NANA_DEPLOY_HPP
#include <nana/config.hpp>
#include <nana/charset.hpp>
#if defined(NANA_LINUX)
#undef NANA_WINDOWS
#endif
#ifndef NANA_UNICODE
namespace nana
{
typedef char char_t;
typedef std::string string; ///< An alias of std::wstring or std::string, depending on the macro NANA_UNICODE
}
#define STR(string) string
#else
namespace nana
{
typedef wchar_t char_t;
typedef std::wstring string; ///< An alias of std::wstring or std::string, depending on the macro NANA_UNICODE
}
#define STR(string) L##string
#endif
namespace nana
{
std::size_t strlen(const char_t* str);
double strtod(const char_t* str, char_t** endptr);
char_t* strcpy(char_t* dest, const char_t* source);
}
#if defined(NANA_WINDOWS)
#define NANA_SHARED_EXPORT extern "C" _declspec(dllexport)
#elif defined(NANA_LINUX)
#define NANA_SHARED_EXPORT extern "C"
#endif
namespace nana
{
bool is_incomplete(const nana::string& str, unsigned pos);
inline unsigned make_rgb(unsigned char red, unsigned char green, unsigned char blue)
{
return ((unsigned(red) << 16)|((unsigned(green)<<8))|blue);
}
}
#define NANA_RGB(a) (((DWORD)(a) & 0xFF)<<16) | ((DWORD)(a) & 0xFF00) | (((DWORD)(a) & 0xFF0000) >> 16 )
#endif //NANA_MACROS_HPP

View File

@@ -0,0 +1,341 @@
/*
* Message Dispatcher Implementation
* Copyright(C) 2003-2013 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: nana/detail/msg_dispatcher.hpp
*
* @DO NOT INCLUDE THIS HEADER FILE IN YOUR SOURCE FILE!!
*
* This class msg_dispatcher provides a simulation of Windows-like message
* dispatcher. Every event is dispatched into its own message queue for
* corresponding thread.
*/
#ifndef NANA_DETAIL_MSG_DISPATCHER_HPP
#define NANA_DETAIL_MSG_DISPATCHER_HPP
#include "msg_packet.hpp"
#include <nana/system/platform.hpp>
#include <list>
#include <set>
#include <map>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <thread>
namespace nana
{
namespace detail
{
class msg_dispatcher
{
struct thread_binder
{
unsigned tid;
std::mutex mutex;
std::condition_variable cond;
std::list<msg_packet_tag> msg_queue;
std::set<Window> window;
};
public:
typedef msg_packet_tag msg_packet;
typedef void (*timer_proc_type)(unsigned tid);
typedef void (*event_proc_type)(Display*, msg_packet_tag&);
typedef int (*event_filter_type)(XEvent&, msg_packet_tag&);
typedef std::list<msg_packet_tag> msg_queue_type;
msg_dispatcher(Display* disp)
: display_(disp), is_work_(false)
{
proc_.event_proc = 0;
proc_.timer_proc = 0;
proc_.filter_proc = 0;
}
void set(timer_proc_type timer_proc, event_proc_type event_proc, event_filter_type filter)
{
proc_.timer_proc = timer_proc;
proc_.event_proc = event_proc;
proc_.filter_proc = filter;
}
void insert(Window wd)
{
unsigned tid = nana::system::this_thread_id();
bool start_driver;
{
std::lock_guard<decltype(table_.mutex)> lock(table_.mutex);
//No thread is running, so msg dispatcher should start the msg driver.
start_driver = (0 == table_.thr_table.size());
thread_binder * thr;
std::map<unsigned, thread_binder*>::iterator i = table_.thr_table.find(tid);
if(i == table_.thr_table.end())
{
thr = new thread_binder;
thr->tid = tid;
table_.thr_table.insert(std::make_pair(tid, thr));
}
else
thr = i->second;
thr->mutex.lock();
thr->window.insert(wd);
thr->mutex.unlock();
table_.wnd_table[wd] = thr;
}
if(start_driver && proc_.event_proc && proc_.timer_proc)
{
//It should start the msg driver, before starting it, the msg driver must be inactive.
if(thrd_)
{
is_work_ = false;
thrd_->join();
}
is_work_ = true;
thrd_ = std::unique_ptr<std::thread>(new std::thread([this](){ this->_m_msg_driver(); }));
}
}
void erase(Window wd)
{
std::lock_guard<decltype(table_.mutex)> lock(table_.mutex);
auto i = table_.wnd_table.find(wd);
if(i != table_.wnd_table.end())
{
thread_binder * const thr = i->second;
std::lock_guard<decltype(thr->mutex)> lock(thr->mutex);
for(auto li = thr->msg_queue.begin(); li != thr->msg_queue.end();)
{
if(wd == _m_window(*li))
li = thr->msg_queue.erase(li);
else
++li;
}
table_.wnd_table.erase(i);
thr->window.erase(wd);
//There still is at least one window alive.
if(thr->window.size())
{
//Make a cleanup msg packet to infor the dispatcher the window is closed.
msg_packet_tag msg;
msg.kind = msg.kind_cleanup;
msg.u.packet_window = wd;
thr->msg_queue.push_back(msg);
}
}
}
void dispatch(Window modal)
{
unsigned tid = nana::system::this_thread_id();
msg_packet_tag msg;
int qstate;
//Test whether the thread is registered for window, and retrieve the queue state for event
while((qstate = _m_read_queue(tid, msg, modal)))
{
//the queue is empty
if(-1 == qstate)
{
if(false == _m_wait_for_queue(tid))
proc_.timer_proc(tid);
}
else
{
proc_.event_proc(display_, msg);
}
}
}
private:
void _m_msg_driver()
{
int fd_X11 = ConnectionNumber(display_);
msg_packet_tag msg_pack;
XEvent event;
while(is_work_)
{
int pending;
{
nana::detail::platform_scope_guard psg;
pending = ::XPending(display_);
if(pending)
{
::XNextEvent(display_, &event);
if(::XFilterEvent(&event, None))
continue;
}
}
if(0 == pending)
{
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(fd_X11, &fdset);
struct timeval tv;
tv.tv_usec = 10000;
tv.tv_sec = 0;
::select(fd_X11 + 1, &fdset, 0, 0, &tv);
}
else
{
switch(proc_.filter_proc(event, msg_pack))
{
case 0:
msg_pack.kind = msg_pack.kind_xevent;
msg_pack.u.xevent = event;
case 1:
_m_msg_dispatch(msg_pack);
}
}
}
}
private:
static Window _m_event_window(const XEvent& event)
{
switch(event.type)
{
case MapNotify:
case UnmapNotify:
return event.xmap.window;
}
return event.xkey.window;
}
static Window _m_window(const msg_packet_tag& pack)
{
switch(pack.kind)
{
case msg_packet_tag::kind_xevent:
return _m_event_window(pack.u.xevent);
case msg_packet_tag::kind_mouse_drop:
return pack.u.mouse_drop.window;
default:
break;
}
return 0;
}
void _m_msg_dispatch(const msg_packet_tag &msg)
{
std::lock_guard<decltype(table_.mutex)> lock(table_.mutex);
auto i = table_.wnd_table.find(_m_window(msg));
if(i != table_.wnd_table.end())
{
thread_binder * const thr = i->second;
std::lock_guard<decltype(thr->mutex)> lock(thr->mutex);
thr->msg_queue.push_back(msg);
thr->cond.notify_one();
}
}
//_m_read_queue
//@brief:Read the event from a specified thread queue.
//@return: 0 = exit the queue, 1 = fetch the msg, -1 = no msg
int _m_read_queue(unsigned tid, msg_packet_tag& msg, Window modal)
{
bool stop_driver = false;
{
std::lock_guard<decltype(table_.mutex)> lock(table_.mutex);
//Find the thread whether it is registered for the window.
auto i = table_.thr_table.find(tid);
if(i != table_.thr_table.end())
{
if(i->second->window.size())
{
msg_queue_type & queue = i->second->msg_queue;
if(queue.size())
{
msg = queue.front();
queue.pop_front();
//Check whether the event dispatcher is used for the modal window
//and when the modal window is closing, the event dispatcher would
//stop event pumping.
if((modal == msg.u.packet_window) && (msg.kind == msg.kind_cleanup))
return 0;
return 1;
}
else
return -1;
}
delete i->second;
table_.thr_table.erase(i);
stop_driver = (table_.thr_table.size() == 0);
}
}
if(stop_driver)
{
is_work_ = false;
thrd_->join();
thrd_.reset();
}
return 0;
}
//_m_wait_for_queue
// wait for the insertion of queue.
//return@ it returns true if the queue is not empty, otherwise the wait is timeout.
bool _m_wait_for_queue(unsigned tid)
{
thread_binder * thr = nullptr;
{
std::lock_guard<decltype(table_.mutex)> lock(table_.mutex);
auto i = table_.thr_table.find(tid);
if(i != table_.thr_table.end())
{
if(i->second->msg_queue.size())
return true;
thr = i->second;
}
}
//Waits for notifying the condition variable, it indicates a new msg is pushing into the queue.
std::unique_lock<decltype(thr->mutex)> lock(thr->mutex);
return (thr->cond.wait_for(lock, std::chrono::milliseconds(10)) != std::cv_status::timeout);
}
private:
Display * display_;
volatile bool is_work_;
std::unique_ptr<std::thread> thrd_;
struct table_tag
{
std::recursive_mutex mutex;
std::map<unsigned, thread_binder*> thr_table;
std::map<Window, thread_binder*> wnd_table;
}table_;
struct proc_tag
{
timer_proc_type timer_proc;
event_proc_type event_proc;
event_filter_type filter_proc;
}proc_;
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,32 @@
#ifndef NANA_DETAIL_MSG_PACKET_HPP
#define NANA_DETAIL_MSG_PACKET_HPP
#include <X11/Xlib.h>
#include <vector>
#include <nana/deploy.hpp>
namespace nana
{
namespace detail
{
struct msg_packet_tag
{
enum kind_t{kind_xevent, kind_mouse_drop, kind_cleanup};
kind_t kind;
union
{
XEvent xevent;
Window packet_window; //Avaiable if the packet is not kind_xevent
struct mouse_drop_tag
{
Window window;
int x;
int y;
std::vector<nana::string> * files;
}mouse_drop;
}u;
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,317 @@
/*
* Platform Specification Implementation
* Copyright(C) 2003-2013 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: nana/detail/platform_spec.hpp
*
* This file provides basis class and data structrue that required by nana
* This file should not be included by any header files.
*/
#ifndef NANA_DETAIL_PLATFORM_SPEC_HPP
#define NANA_DETAIL_PLATFORM_SPEC_HPP
#include <thread>
#include <mutex>
#include <memory>
#include <condition_variable>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <nana/gui/basis.hpp>
#include <nana/paint/image.hpp>
#include <nana/paint/graphics.hpp>
#include <nana/gui/detail/event_code.hpp>
#include <vector>
#include <map>
#include "msg_packet.hpp"
#if defined(NANA_UNICODE)
#include <X11/Xft/Xft.h>
#include <iconv.h>
#include <fstream>
#endif
namespace nana
{
namespace detail
{
class msg_dispatcher;
#if defined(NANA_UNICODE)
class conf
{
public:
conf(const char * file);
bool open(const char* file);
std::string value(const char* key);
private:
std::ifstream ifs_;
};
class charset_conv
{
public:
charset_conv(const char* tocode, const char* fromcode);
~charset_conv();
std::string charset(const std::string& str) const;
std::string charset(const char * buf, std::size_t len) const;
private:
iconv_t handle_;
};
#endif
struct font_tag
{
nana::string name;
unsigned height;
unsigned weight;
bool italic;
bool underline;
bool strikeout;
#if defined(NANA_UNICODE)
XftFont * handle;
#else
XFontSet handle;
#endif
};
struct drawable_impl_type
{
typedef std::shared_ptr<font_tag> font_ptr_t;
drawable_impl_type();
~drawable_impl_type();
void fgcolor(unsigned color);
Pixmap pixmap;
GC context;
font_ptr_t font;
nana::point line_begin_pos;
struct string_spec
{
unsigned tab_length;
unsigned tab_pixels;
unsigned whitespace_pixels;
}string;
#if defined(NANA_UNICODE)
XftDraw * xftdraw;
XftColor xft_fgcolor;
XftColor xft_bgcolor;
const std::string charset(const nana::string& str, const std::string& strcode);
#endif
private:
unsigned fgcolor_;
#if defined(NANA_UNICODE)
struct conv_tag
{
iconv_t handle;
std::string code;
}conv_;
#endif
};
struct atombase_tag
{
Atom wm_protocols;
//window manager support
Atom wm_change_state;
Atom wm_delete_window;
//ext
Atom net_wm_state;
Atom net_wm_state_skip_taskbar;
Atom net_wm_state_fullscreen;
Atom net_wm_state_maximized_horz;
Atom net_wm_state_maximized_vert;
Atom net_wm_state_modal;
Atom net_wm_window_type;
Atom net_wm_window_type_normal;
Atom net_wm_window_type_utility;
Atom net_wm_window_type_dialog;
Atom motif_wm_hints;
Atom clipboard;
Atom text;
Atom text_uri_list;
Atom utf8_string;
Atom targets;
Atom xdnd_aware;
Atom xdnd_enter;
Atom xdnd_position;
Atom xdnd_status;
Atom xdnd_action_copy;
Atom xdnd_drop;
Atom xdnd_selection;
Atom xdnd_typelist;
Atom xdnd_finished;
};
struct caret_tag;
class timer_runner;
class platform_scope_guard
{
public:
platform_scope_guard();
~platform_scope_guard();
};
class platform_spec
{
typedef platform_spec self_type;
struct window_context_t
{
native_window_type owner;
std::vector<native_window_type> * owned;
};
public:
int error_code;
public:
typedef drawable_impl_type::font_ptr_t font_ptr_t;
typedef void (*timer_proc_type)(unsigned tid);
typedef void (*event_proc_type)(Display*, msg_packet_tag&);
typedef ::nana::event_code event_code;
typedef ::nana::native_window_type native_window_type;
platform_spec();
~platform_spec();
const font_ptr_t& default_native_font() const;
void default_native_font(const font_ptr_t&);
unsigned font_size_to_height(unsigned) const;
unsigned font_height_to_size(unsigned) const;
font_ptr_t make_native_font(const nana::char_t* name, unsigned height, unsigned weight, bool italic, bool underline, bool strick_out);
Display* open_display();
void close_display();
void lock_xlib();
void unlock_xlib();
Window root_window();
int screen_depth();
Visual* screen_visual();
Colormap& colormap();
static self_type& instance();
const atombase_tag & atombase() const;
void make_owner(native_window_type owner, native_window_type wd);
native_window_type get_owner(native_window_type) const;
void remove(native_window_type);
void write_keystate(const XKeyEvent&);
void read_keystate(XKeyEvent&);
XIC caret_input_context(native_window_type) const;
void caret_open(native_window_type, unsigned width, unsigned height);
void caret_close(native_window_type);
void caret_pos(native_window_type, int x, int y);
void caret_visible(native_window_type, bool);
void caret_flash(caret_tag&);
bool caret_update(native_window_type, nana::paint::graphics& root_graph, bool is_erase_caret_from_root_graph);
static bool caret_reinstate(caret_tag&);
void set_error_handler();
int rev_error_handler();
//grab
//register a grab window while capturing it if it is unviewable.
//when native_interface::show a window that is registered as a grab
//window, the native_interface grabs the window.
Window grab(Window);
void set_timer(std::size_t id, std::size_t interval, void (*timer_proc)(std::size_t id));
void kill_timer(std::size_t id);
void timer_proc(unsigned tid);
//Message dispatcher
void msg_insert(native_window_type);
void msg_set(timer_proc_type, event_proc_type);
void msg_dispatch(native_window_type modal);
//X Selections
void* request_selection(native_window_type requester, Atom type, size_t & bufsize);
void write_selection(native_window_type owner, Atom type, const void* buf, size_t bufsize);
//Icon storage
//@biref: The image object should be kept for a long time till the window is closed,
// the image object is release in remove() method.
const nana::paint::graphics& keep_window_icon(native_window_type, const nana::paint::image&);
private:
static int _m_msg_filter(XEvent&, msg_packet_tag&);
void _m_caret_routine();
private:
Display* display_;
Colormap colormap_;
atombase_tag atombase_;
font_ptr_t def_font_ptr_;
XKeyEvent key_state_;
int (*def_X11_error_handler_)(Display*, XErrorEvent*);
Window grab_;
std::recursive_mutex xlib_locker_;
struct caret_holder_tag
{
volatile bool exit_thread;
std::unique_ptr<std::thread> thr;
std::map<native_window_type, caret_tag*> carets;
}caret_holder_;
std::map<native_window_type, window_context_t> wincontext_;
std::map<native_window_type, nana::paint::graphics> iconbase_;
struct timer_runner_tag
{
timer_runner * runner;
std::recursive_mutex mutex;
bool delete_declared;
timer_runner_tag();
}timer_;
struct selection_tag
{
struct item_t
{
Atom type;
Window requestor;
void* buffer;
size_t bufsize;
std::mutex cond_mutex;
std::condition_variable cond;
};
std::vector<item_t*> items;
struct content_tag
{
std::string * utf8_string;
}content;
}selection_;
struct xdnd_tag
{
Atom good_type;
int timestamp;
Window wd_src;
nana::point pos;
}xdnd_;
msg_dispatcher * msg_dispatcher_;
};//end class platform_X11
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,179 @@
/*
* Platform Specification Implementation
* Copyright(C) 2003-2013 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: nana/detail/platform_spec.hpp
*
* This file provides basis class and data structrue that required by nana
* This file should not be included by any header files.
*/
#ifndef NANA_DETAIL_PLATFORM_SPEC_HPP
#define NANA_DETAIL_PLATFORM_SPEC_HPP
#include <nana/deploy.hpp>
#include <nana/gui/basis.hpp>
#include <nana/paint/image.hpp>
#include <nana/gui/detail/event_code.hpp>
#include <windows.h>
#include <map>
#include <memory>
namespace nana
{
namespace detail
{
//struct messages
//@brief: This defines some messages that are used for remote thread invocation.
// Some Windows APIs are window-thread-dependent, the operation in other thread
// must be posted to its own thread.
struct messages
{
struct caret
{
int x;
int y;
unsigned width;
unsigned height;
bool visible;
};
struct move_window
{
enum { Pos = 1, Size = 2};
int x;
int y;
unsigned width;
unsigned height;
unsigned ignore; //determinate that pos or size would be ignored.
};
enum
{
tray = 0x501,
async_activate,
async_set_focus,
map_thread_root_buffer,
remote_thread_destroy_window,
remote_thread_move_window,
operate_caret, //wParam: 1=Destroy, 2=SetPos
remote_thread_set_window_pos,
remote_thread_set_window_text,
user,
};
};
struct font_tag
{
nana::string name;
unsigned height;
unsigned weight;
bool italic;
bool underline;
bool strikeout;
HFONT handle;
struct deleter
{
void operator()(const font_tag*) const;
};
};
struct drawable_impl_type
{
typedef std::shared_ptr<font_tag> font_ptr_t;
HDC context;
HBITMAP pixmap;
pixel_rgb_t* pixbuf_ptr;
std::size_t bytes_per_line;
font_ptr_t font;
struct pen_spec
{
HPEN handle;
unsigned color;
int style;
int width;
void set(HDC context, int style, int width, nana::color_t color);
}pen;
struct brush_spec
{
enum t{Solid, HatchBDiagonal};
HBRUSH handle;
t style;
nana::color_t color;
void set(HDC context, t style, nana::color_t color);
}brush;
struct round_region_spec
{
HRGN handle;
nana::rectangle r;
unsigned radius_x;
unsigned radius_y;
void set(const nana::rectangle& r, unsigned radius_x, unsigned radius_y);
}round_region;
struct string_spec
{
unsigned tab_length;
unsigned tab_pixels;
unsigned whitespace_pixels;
}string;
drawable_impl_type();
~drawable_impl_type();
void fgcolor(nana::color_t);
private:
unsigned fgcolor_;
};
class platform_spec
{
public:
typedef drawable_impl_type::font_ptr_t font_ptr_t;
typedef ::nana::event_code event_code;
typedef ::nana::native_window_type native_window_type;
class co_initializer
{
public:
co_initializer();
~co_initializer();
private:
HMODULE ole32_;
};
platform_spec();
const font_ptr_t& default_native_font() const;
void default_native_font(const font_ptr_t&);
unsigned font_size_to_height(unsigned) const;
unsigned font_height_to_size(unsigned) const;
font_ptr_t make_native_font(const nana::char_t* name, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out);
static platform_spec& instance();
void keep_window_icon(native_window_type, const nana::paint::image&);
void release_window_icon(native_window_type);
private:
font_ptr_t def_font_ptr_;
std::map<native_window_type, nana::paint::image> iconbase_;
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,95 @@
/*
* Exception Definition
* Copyright(C) 2003-2013 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: nana/exceptions.hpp
*/
#ifndef NANA_EXCEPTIONS_H
#define NANA_EXCEPTIONS_H
#include <exception>
#include <string>
namespace nana
{
/**
* nana::threads::thread::exit throws this exception to exit thread
* this exception is not allowed to be catch by programmer,
* otherwise the thread may not exit
*/
class thrd_exit: public std::exception
{
public:
thrd_exit(unsigned retval);
~thrd_exit() throw();
const char* what() const throw();
unsigned retval() const;
private:
unsigned retval_;
};
/**
* nana::text::settings_t throws this exception if it dose not found a given member
* in a scope
*/
class bad_member: public std::exception
{
public:
bad_member(const std::string& what);
~bad_member() throw();
const char* what() const throw();
private:
std::string what_;
};
/**
* nana::text::settings_t throws this exception if there is a syntax error
*/
class bad_syntax: public std::exception
{
public:
bad_syntax(const std::string& what);
~bad_syntax() throw();
const char* what() const throw();
private:
std::string what_;
};
class bad_error: public std::exception
{
public:
bad_error(const std::string& what);
~bad_error() throw();
const char* what() const throw();
private:
std::string what_;
};
class bad_handle: public std::exception
{
public:
bad_handle(const std::string& what);
~bad_handle() throw();
const char* what() const throw();
private:
std::string what_;
};
class bad_window
:public std::exception
{
public:
bad_window(const char* what);
~bad_window() throw();
const char* what() const throw();
private:
std::string what_;
};
}// end namespace nana
#endif

2654
include/nana/extrlib/png.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,596 @@
/* pngconf.h - machine configurable file for libpng
*
* libpng version 1.5.8 - February 1, 2012
*
* Copyright (c) 1998-2012 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
*/
/* Any machine specific code is near the front of this file, so if you
* are configuring libpng for a machine, you may want to read the section
* starting here down to where it starts to typedef png_color, png_text,
* and png_info.
*/
#ifndef PNGCONF_H
#define PNGCONF_H
#ifndef PNG_BUILDING_SYMBOL_TABLE
/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C
* definition file for machine specific limits, this may impact the
* correctness of the definitons below (see uses of INT_MAX).
*/
# ifndef PNG_NO_LIMITS_H
# include <limits.h>
# endif
/* For the memory copy APIs (i.e. the standard definitions of these),
* because this file defines png_memcpy and so on the base APIs must
* be defined here.
*/
# ifdef BSD
# include <strings.h>
# else
# include <string.h>
# endif
/* For png_FILE_p - this provides the standard definition of a
* FILE
*/
# ifdef PNG_STDIO_SUPPORTED
# include <stdio.h>
# endif
#endif
/* This controls optimization of the reading of 16 and 32 bit values
* from PNG files. It can be set on a per-app-file basis - it
* just changes whether a macro is used to the function is called.
* The library builder sets the default, if read functions are not
* built into the library the macro implementation is forced on.
*/
#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
# define PNG_USE_READ_MACROS
#endif
#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS)
# if PNG_DEFAULT_READ_MACROS
# define PNG_USE_READ_MACROS
# endif
#endif
/* COMPILER SPECIFIC OPTIONS.
*
* These options are provided so that a variety of difficult compilers
* can be used. Some are fixed at build time (e.g. PNG_API_RULE
* below) but still have compiler specific implementations, others
* may be changed on a per-file basis when compiling against libpng.
*/
/* The PNGARG macro protects us against machines that don't have function
* prototypes (ie K&R style headers). If your compiler does not handle
* function prototypes, define this macro and use the included ansi2knr.
* I've always been able to use _NO_PROTO as the indicator, but you may
* need to drag the empty declaration out in front of here, or change the
* ifdef to suit your own needs.
*/
#ifndef PNGARG
# ifdef OF /* zlib prototype munger */
# define PNGARG(arglist) OF(arglist)
# else
# ifdef _NO_PROTO
# define PNGARG(arglist) ()
# else
# define PNGARG(arglist) arglist
# endif /* _NO_PROTO */
# endif /* OF */
#endif /* PNGARG */
/* Function calling conventions.
* =============================
* Normally it is not necessary to specify to the compiler how to call
* a function - it just does it - however on x86 systems derived from
* Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems
* and some others) there are multiple ways to call a function and the
* default can be changed on the compiler command line. For this reason
* libpng specifies the calling convention of every exported function and
* every function called via a user supplied function pointer. This is
* done in this file by defining the following macros:
*
* PNGAPI Calling convention for exported functions.
* PNGCBAPI Calling convention for user provided (callback) functions.
* PNGCAPI Calling convention used by the ANSI-C library (required
* for longjmp callbacks and sometimes used internally to
* specify the calling convention for zlib).
*
* These macros should never be overridden. If it is necessary to
* change calling convention in a private build this can be done
* by setting PNG_API_RULE (which defaults to 0) to one of the values
* below to select the correct 'API' variants.
*
* PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout.
* This is correct in every known environment.
* PNG_API_RULE=1 Use the operating system convention for PNGAPI and
* the 'C' calling convention (from PNGCAPI) for
* callbacks (PNGCBAPI). This is no longer required
* in any known environment - if it has to be used
* please post an explanation of the problem to the
* libpng mailing list.
*
* These cases only differ if the operating system does not use the C
* calling convention, at present this just means the above cases
* (x86 DOS/Windows sytems) and, even then, this does not apply to
* Cygwin running on those systems.
*
* Note that the value must be defined in pnglibconf.h so that what
* the application uses to call the library matches the conventions
* set when building the library.
*/
/* Symbol export
* =============
* When building a shared library it is almost always necessary to tell
* the compiler which symbols to export. The png.h macro 'PNG_EXPORT'
* is used to mark the symbols. On some systems these symbols can be
* extracted at link time and need no special processing by the compiler,
* on other systems the symbols are flagged by the compiler and just
* the declaration requires a special tag applied (unfortunately) in a
* compiler dependent way. Some systems can do either.
*
* A small number of older systems also require a symbol from a DLL to
* be flagged to the program that calls it. This is a problem because
* we do not know in the header file included by application code that
* the symbol will come from a shared library, as opposed to a statically
* linked one. For this reason the application must tell us by setting
* the magic flag PNG_USE_DLL to turn on the special processing before
* it includes png.h.
*
* Four additional macros are used to make this happen:
*
* PNG_IMPEXP The magic (if any) to cause a symbol to be exported from
* the build or imported if PNG_USE_DLL is set - compiler
* and system specific.
*
* PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to
* 'type', compiler specific.
*
* PNG_DLL_EXPORT Set to the magic to use during a libpng build to
* make a symbol exported from the DLL. Not used in the
* public header files; see pngpriv.h for how it is used
* in the libpng build.
*
* PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come
* from a DLL - used to define PNG_IMPEXP when
* PNG_USE_DLL is set.
*/
/* System specific discovery.
* ==========================
* This code is used at build time to find PNG_IMPEXP, the API settings
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
* import processing is possible. On Windows/x86 systems it also sets
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\
( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\
defined(_M_X64) || defined(_M_IA64) )
/* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes
* builds under Cygwin or MinGW. Also includes Watcom builds but these need
* special treatment because they are not compatible with GCC or Visual C
* because of different calling conventions.
*/
# if PNG_API_RULE == 2
/* If this line results in an error, either because __watcall is not
* understood or because of a redefine just below you cannot use *this*
* build of the library with the compiler you are using. *This* build was
* build using Watcom and applications must also be built using Watcom!
*/
# define PNGCAPI __watcall
# endif
# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
# define PNGCAPI __cdecl
# if PNG_API_RULE == 1
# define PNGAPI __stdcall
# endif
# else
/* An older compiler, or one not detected (erroneously) above,
* if necessary override on the command line to get the correct
* variants for the compiler.
*/
# ifndef PNGCAPI
# define PNGCAPI _cdecl
# endif
# if PNG_API_RULE == 1 && !defined(PNGAPI)
# define PNGAPI _stdcall
# endif
# endif /* compiler/api */
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
# endif
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
(defined(__BORLANDC__) && __BORLANDC__ < 0x500)
/* older Borland and MSC
* compilers used '__export' and required this to be after
* the type.
*/
# ifndef PNG_EXPORT_TYPE
# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
# endif
# define PNG_DLL_EXPORT __export
# else /* newer compiler */
# define PNG_DLL_EXPORT __declspec(dllexport)
# ifndef PNG_DLL_IMPORT
# define PNG_DLL_IMPORT __declspec(dllimport)
# endif
# endif /* compiler */
#else /* !Windows/x86 */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
# define PNGAPI _System
# else /* !Windows/x86 && !OS/2 */
/* Use the defaults, or define PNG*API on the command line (but
* this will have to be done for every compile!)
*/
# endif /* other system, !OS/2 */
#endif /* !Windows/x86 */
/* Now do all the defaulting . */
#ifndef PNGCAPI
# define PNGCAPI
#endif
#ifndef PNGCBAPI
# define PNGCBAPI PNGCAPI
#endif
#ifndef PNGAPI
# define PNGAPI PNGCAPI
#endif
/* PNG_IMPEXP may be set on the compilation system command line or (if not set)
* then in an internal header file when building the library, otherwise (when
* using the library) it is set here.
*/
#ifndef PNG_IMPEXP
# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT)
/* This forces use of a DLL, disallowing static linking */
# define PNG_IMPEXP PNG_DLL_IMPORT
# endif
# ifndef PNG_IMPEXP
# define PNG_IMPEXP
# endif
#endif
/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat
* 'attributes' as a storage class - the attributes go at the start of the
* function definition, and attributes are always appended regardless of the
* compiler. This considerably simplifies these macros but may cause problems
* if any compilers both need function attributes and fail to handle them as
* a storage class (this is unlikely.)
*/
#ifndef PNG_FUNCTION
# define PNG_FUNCTION(type, name, args, attributes) attributes type name args
#endif
#ifndef PNG_EXPORT_TYPE
# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
#endif
/* The ordinal value is only relevant when preprocessing png.h for symbol
* table entries, so we discard it here. See the .dfn files in the
* scripts directory.
*/
#ifndef PNG_EXPORTA
# define PNG_EXPORTA(ordinal, type, name, args, attributes)\
PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \
extern attributes)
#endif
/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument,
* so make something non-empty to satisfy the requirement:
*/
#define PNG_EMPTY /*empty list*/
#define PNG_EXPORT(ordinal, type, name, args)\
PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
/* Use PNG_REMOVED to comment out a removed interface. */
#ifndef PNG_REMOVED
# define PNG_REMOVED(ordinal, type, name, args, attributes)
#endif
#ifndef PNG_CALLBACK
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
#endif
/* Support for compiler specific function attributes. These are used
* so that where compiler support is available incorrect use of API
* functions in png.h will generate compiler warnings.
*
* Added at libpng-1.2.41.
*/
#ifndef PNG_NO_PEDANTIC_WARNINGS
# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
# define PNG_PEDANTIC_WARNINGS_SUPPORTED
# endif
#endif
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
/* Support for compiler specific function attributes. These are used
* so that where compiler support is available incorrect use of API
* functions in png.h will generate compiler warnings. Added at libpng
* version 1.2.41.
*/
# if defined(__GNUC__)
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
# endif
# ifndef PNG_NORETURN
# define PNG_NORETURN __attribute__((__noreturn__))
# endif
# ifndef PNG_ALLOCATED
# define PNG_ALLOCATED __attribute__((__malloc__))
# endif
# ifndef PNG_DEPRECATED
# define PNG_DEPRECATED __attribute__((__deprecated__))
# endif
# ifndef PNG_PRIVATE
# if 0 /* Doesn't work so we use deprecated instead*/
# define PNG_PRIVATE \
__attribute__((warning("This function is not exported by libpng.")))
# else
# define PNG_PRIVATE \
__attribute__((__deprecated__))
# endif
# endif
# endif /* __GNUC__ */
# if defined(_MSC_VER) && (_MSC_VER >= 1300)
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT /* not supported */
# endif
# ifndef PNG_NORETURN
# define PNG_NORETURN __declspec(noreturn)
# endif
# ifndef PNG_ALLOCATED
# if (_MSC_VER >= 1400)
# define PNG_ALLOCATED __declspec(restrict)
# endif
# endif
# ifndef PNG_DEPRECATED
# define PNG_DEPRECATED __declspec(deprecated)
# endif
# ifndef PNG_PRIVATE
# define PNG_PRIVATE __declspec(deprecated)
# endif
# endif /* _MSC_VER */
#endif /* PNG_PEDANTIC_WARNINGS */
#ifndef PNG_DEPRECATED
# define PNG_DEPRECATED /* Use of this function is deprecated */
#endif
#ifndef PNG_USE_RESULT
# define PNG_USE_RESULT /* The result of this function must be checked */
#endif
#ifndef PNG_NORETURN
# define PNG_NORETURN /* This function does not return */
#endif
#ifndef PNG_ALLOCATED
# define PNG_ALLOCATED /* The result of the function is new memory */
#endif
#ifndef PNG_PRIVATE
# define PNG_PRIVATE /* This is a private libpng function */
#endif
#ifndef PNG_FP_EXPORT /* A floating point API. */
# ifdef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
PNG_EXPORT(ordinal, type, name, args)
# else /* No floating point APIs */
# define PNG_FP_EXPORT(ordinal, type, name, args)
# endif
#endif
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
# ifdef PNG_FIXED_POINT_SUPPORTED
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
PNG_EXPORT(ordinal, type, name, args)
# else /* No fixed point APIs */
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
# endif
#endif
/* The following uses const char * instead of char * for error
* and warning message functions, so some compilers won't complain.
* If you do not want to use const, define PNG_NO_CONST here.
*
* This should not change how the APIs are called, so it can be done
* on a per-file basis in the application.
*/
#ifndef PNG_CONST
# ifndef PNG_NO_CONST
# define PNG_CONST const
# else
# define PNG_CONST
# endif
#endif
/* Some typedefs to get us started. These should be safe on most of the
* common platforms. The typedefs should be at least as large as the
* numbers suggest (a png_uint_32 must be at least 32 bits long), but they
* don't have to be exactly that size. Some compilers dislike passing
* unsigned shorts as function parameters, so you may be better off using
* unsigned int for png_uint_16.
*/
#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL)
typedef unsigned int png_uint_32;
typedef int png_int_32;
#else
typedef unsigned long png_uint_32;
typedef long png_int_32;
#endif
typedef unsigned short png_uint_16;
typedef short png_int_16;
typedef unsigned char png_byte;
#ifdef PNG_NO_SIZE_T
typedef unsigned int png_size_t;
#else
typedef size_t png_size_t;
#endif
#define png_sizeof(x) (sizeof (x))
/* The following is needed for medium model support. It cannot be in the
* pngpriv.h header. Needs modification for other compilers besides
* MSC. Model independent support declares all arrays and pointers to be
* large using the far keyword. The zlib version used must also support
* model independent data. As of version zlib 1.0.4, the necessary changes
* have been made in zlib. The USE_FAR_KEYWORD define triggers other
* changes that are needed. (Tim Wegner)
*/
/* Separate compiler dependencies (problem here is that zlib.h always
* defines FAR. (SJT)
*/
#ifdef __BORLANDC__
# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
# define LDATA 1
# else
# define LDATA 0
# endif
/* GRR: why is Cygwin in here? Cygwin is not Borland C... */
# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
# define PNG_MAX_MALLOC_64K /* only used in build */
# if (LDATA != 1)
# ifndef FAR
# define FAR __far
# endif
# define USE_FAR_KEYWORD
# endif /* LDATA != 1 */
/* Possibly useful for moving data out of default segment.
* Uncomment it if you want. Could also define FARDATA as
* const if your compiler supports it. (SJT)
# define FARDATA FAR
*/
# endif /* __WIN32__, __FLAT__, __CYGWIN__ */
#endif /* __BORLANDC__ */
/* Suggest testing for specific compiler first before testing for
* FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM,
* making reliance oncertain keywords suspect. (SJT)
*/
/* MSC Medium model */
#ifdef FAR
# ifdef M_I86MM
# define USE_FAR_KEYWORD
# define FARDATA FAR
# include <dos.h>
# endif
#endif
/* SJT: default case */
#ifndef FAR
# define FAR
#endif
/* At this point FAR is always defined */
#ifndef FARDATA
# define FARDATA
#endif
/* Typedef for floating-point numbers that are converted
* to fixed-point with a multiple of 100,000, e.g., gamma
*/
typedef png_int_32 png_fixed_point;
/* Add typedefs for pointers */
typedef void FAR * png_voidp;
typedef PNG_CONST void FAR * png_const_voidp;
typedef png_byte FAR * png_bytep;
typedef PNG_CONST png_byte FAR * png_const_bytep;
typedef png_uint_32 FAR * png_uint_32p;
typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p;
typedef png_int_32 FAR * png_int_32p;
typedef PNG_CONST png_int_32 FAR * png_const_int_32p;
typedef png_uint_16 FAR * png_uint_16p;
typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p;
typedef png_int_16 FAR * png_int_16p;
typedef PNG_CONST png_int_16 FAR * png_const_int_16p;
typedef char FAR * png_charp;
typedef PNG_CONST char FAR * png_const_charp;
typedef png_fixed_point FAR * png_fixed_point_p;
typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p;
typedef png_size_t FAR * png_size_tp;
typedef PNG_CONST png_size_t FAR * png_const_size_tp;
#ifdef PNG_STDIO_SUPPORTED
typedef FILE * png_FILE_p;
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
typedef double FAR * png_doublep;
typedef PNG_CONST double FAR * png_const_doublep;
#endif
/* Pointers to pointers; i.e. arrays */
typedef png_byte FAR * FAR * png_bytepp;
typedef png_uint_32 FAR * FAR * png_uint_32pp;
typedef png_int_32 FAR * FAR * png_int_32pp;
typedef png_uint_16 FAR * FAR * png_uint_16pp;
typedef png_int_16 FAR * FAR * png_int_16pp;
typedef PNG_CONST char FAR * FAR * png_const_charpp;
typedef char FAR * FAR * png_charpp;
typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
#ifdef PNG_FLOATING_POINT_SUPPORTED
typedef double FAR * FAR * png_doublepp;
#endif
/* Pointers to pointers to pointers; i.e., pointer to array */
typedef char FAR * FAR * FAR * png_charppp;
/* png_alloc_size_t is guaranteed to be no smaller than png_size_t,
* and no smaller than png_uint_32. Casts from png_size_t or png_uint_32
* to png_alloc_size_t are not necessary; in fact, it is recommended
* not to use them at all so that the compiler can complain when something
* turns out to be problematic.
* Casts in the other direction (from png_alloc_size_t to png_size_t or
* png_uint_32) should be explicitly applied; however, we do not expect
* to encounter practical situations that require such conversions.
*/
#if defined(__TURBOC__) && !defined(__FLAT__)
typedef unsigned long png_alloc_size_t;
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
typedef unsigned long png_alloc_size_t;
# else
/* This is an attempt to detect an old Windows system where (int) is
* actually 16 bits, in that case png_malloc must have an argument with a
* bigger size to accomodate the requirements of the library.
*/
# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \
(!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL)
typedef DWORD png_alloc_size_t;
# else
typedef png_size_t png_alloc_size_t;
# endif
# endif
#endif
#endif /* PNGCONF_H */

View File

@@ -0,0 +1,189 @@
/* libpng STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
/* Libpng 1.5.8 - February 1, 2012 */
/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
/* and license in png.h */
/* pnglibconf.h */
/* Derived from: scripts/pnglibconf.dfa */
/* If you edit this file by hand you must obey the rules expressed in */
/* pnglibconf.dfa with respect to the dependencies between the following */
/* symbols. It is much better to generate a new file using */
/* scripts/libpngconf.mak */
#ifndef PNGLCONF_H
#define PNGLCONF_H
/* settings */
#define PNG_API_RULE 0
#define PNG_CALLOC_SUPPORTED
#define PNG_COST_SHIFT 3
#define PNG_DEFAULT_READ_MACROS 1
#define PNG_GAMMA_THRESHOLD_FIXED 5000
#define PNG_MAX_GAMMA_8 11
#define PNG_QUANTIZE_BLUE_BITS 5
#define PNG_QUANTIZE_GREEN_BITS 5
#define PNG_QUANTIZE_RED_BITS 5
#define PNG_sCAL_PRECISION 5
#define PNG_USER_CHUNK_CACHE_MAX 0
#define PNG_USER_CHUNK_MALLOC_MAX 0
#define PNG_USER_HEIGHT_MAX 1000000
#define PNG_USER_WIDTH_MAX 1000000
#define PNG_WEIGHT_SHIFT 8
#define PNG_ZBUF_SIZE 8192
/* end of settings */
/* options */
#define PNG_16BIT_SUPPORTED
#define PNG_ALIGN_MEMORY_SUPPORTED
#define PNG_BENIGN_ERRORS_SUPPORTED
#define PNG_bKGD_SUPPORTED
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
#define PNG_CHECK_cHRM_SUPPORTED
#define PNG_cHRM_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#define PNG_CONVERT_tIME_SUPPORTED
#define PNG_EASY_ACCESS_SUPPORTED
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
#define PNG_ERROR_TEXT_SUPPORTED
#define PNG_FIXED_POINT_SUPPORTED
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
#define PNG_FLOATING_POINT_SUPPORTED
#define PNG_FORMAT_AFIRST_SUPPORTED
#define PNG_FORMAT_BGR_SUPPORTED
#define PNG_gAMA_SUPPORTED
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
#define PNG_hIST_SUPPORTED
#define PNG_iCCP_SUPPORTED
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
#define PNG_iTXt_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_oFFs_SUPPORTED
#define PNG_pCAL_SUPPORTED
#define PNG_pHYs_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED
#define PNG_READ_BGR_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
#define PNG_READ_hIST_SUPPORTED
#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED
#define PNG_READ_iTXt_SUPPORTED
#define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
#define PNG_READ_pCAL_SUPPORTED
#define PNG_READ_pHYs_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
#define PNG_READ_sCAL_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
#define PNG_READ_sPLT_SUPPORTED
#define PNG_READ_sRGB_SUPPORTED
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_READ_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
#define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_TEXT_SUPPORTED
#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_TRANSFORMS_SUPPORTED
#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED
#define PNG_SAVE_INT_32_SUPPORTED
#define PNG_sBIT_SUPPORTED
#define PNG_sCAL_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED
#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
#define PNG_SETJMP_SUPPORTED
#define PNG_SET_USER_LIMITS_SUPPORTED
#define PNG_sPLT_SUPPORTED
#define PNG_sRGB_SUPPORTED
#define PNG_STDIO_SUPPORTED
#define PNG_tEXt_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
#define PNG_tIME_SUPPORTED
#define PNG_tRNS_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED
#define PNG_USER_MEM_SUPPORTED
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
#define PNG_WARNINGS_SUPPORTED
#define PNG_WRITE_16BIT_SUPPORTED
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED
#define PNG_WRITE_FILTER_SUPPORTED
#define PNG_WRITE_FLUSH_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_hIST_SUPPORTED
#define PNG_WRITE_iCCP_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED
#define PNG_WRITE_iTXt_SUPPORTED
#define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
#define PNG_WRITE_pCAL_SUPPORTED
#define PNG_WRITE_pHYs_SUPPORTED
#define PNG_WRITE_sBIT_SUPPORTED
#define PNG_WRITE_sCAL_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED
#define PNG_WRITE_sPLT_SUPPORTED
#define PNG_WRITE_sRGB_SUPPORTED
#define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED
#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_TEXT_SUPPORTED
#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_TRANSFORMS_SUPPORTED
#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
#define PNG_zTXt_SUPPORTED
/* end of options */
#endif /* PNGLCONF_H */

1732
include/nana/extrlib/zlib.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,255 @@
/*
* A File Iterator 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/file_iterator.hpp
* @description:
* file_iterator is a toolkit for applying each file and directory in a
* specified path.
*/
#ifndef NANA_FILESYSTEM_FILE_ITERATOR_HPP
#define NANA_FILESYSTEM_FILE_ITERATOR_HPP
#include <iterator>
#include <memory>
#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 nana
{
namespace filesystem
{
struct fileinfo
{
fileinfo();
#ifdef NANA_WINDOWS
fileinfo(const WIN32_FIND_DATA& wfd);
#elif NANA_LINUX
fileinfo(const nana::string& filename, const struct stat &);
#endif
nana::string name;
unsigned long size;
bool directory;
};
template<typename FileInfo>
class basic_file_iterator
:public std::iterator<std::input_iterator_tag, FileInfo>
{
public:
typedef FileInfo value_type;
basic_file_iterator():end_(true), handle_(nullptr){}
basic_file_iterator(const nana::string& file_path)
:end_(false), handle_(nullptr)
{
_m_prepare(file_path);
}
const value_type&
operator*() const { return value_; }
const value_type*
operator->() const { return &(operator*()); }
basic_file_iterator& operator++()
{ _m_read(); return *this; }
basic_file_iterator operator++(int)
{
basic_file_iterator tmp = *this;
_m_read();
return tmp;
}
bool equal(const basic_file_iterator& x) const
{
if(end_ && (end_ == x.end_)) return true;
return (value_.name == x.value_.name);
}
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_);
#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), fst);
}
else
{
value_.name = 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_);
}
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(nana::charset(dnt->d_name), fst);
else
value_.name = 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_;
#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_;
value_type value_;
};
template<typename Value_Type>
inline bool operator==(const basic_file_iterator<Value_Type> & x, const basic_file_iterator<Value_Type> & y)
{
return x.equal(y);
}
template<typename Value_Type>
inline bool operator!=(const basic_file_iterator<Value_Type> & x, const basic_file_iterator<Value_Type> & y)
{
return !x.equal(y);
}
typedef basic_file_iterator<fileinfo> file_iterator;
}//end namespace filesystem
}//end namespace nana
#endif

View File

@@ -0,0 +1,65 @@
#ifndef NANA_FILESYSTEM_FS_UTILITY_HPP
#define NANA_FILESYSTEM_FS_UTILITY_HPP
#include <nana/deploy.hpp>
#include <ctime>
namespace nana
{
namespace filesystem
{
struct error
{
enum
{
none = 0
};
};
struct attribute
{
long long bytes;
bool is_directory;
tm modified;
};
bool file_attrib(const nana::string& file, attribute&);
long long filesize(const nana::string& file);
bool mkdir(const nana::string& dir, bool & if_exist);
bool modified_file_time(const nana::string& file, struct tm&);
nana::string path_user();
nana::string path_current();
bool rmfile(const nana::char_t* file);
bool rmdir(const nana::char_t* dir, bool fails_if_not_empty);
nana::string root(const nana::string& path);
class path
{
public:
struct type
{ enum{not_exist, file, directory};
};
path();
path(const nana::string&);
bool empty() const;
path root() const;
int what() const;
nana::string name() const;
private:
#if defined(NANA_WINDOWS)
nana::string text_;
#else
std::string text_;
#endif
};
}//end namespace filesystem
}//end namespace nana
#endif

22
include/nana/fwd.hpp Normal file
View File

@@ -0,0 +1,22 @@
/*
* Forward Declarations
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/fwd.hpp
*
*/
#ifndef NANA_FWD_HPP
#define NANA_FWD_HPP
namespace nana
{
class filebox;
class msgbox;
}//end namespace nana
#endif //NANA_FWD_HPP

1
include/nana/gui.hpp Normal file
View File

@@ -0,0 +1 @@
#include "gui/wvl.hpp"

View File

@@ -0,0 +1,82 @@
/*
* An Animation Implementation
* Copyright(C) 2003-2013 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: nana/gui/animation.hpp
*/
#ifndef NANA_GUI_ANIMATION_HPP
#define NANA_GUI_ANIMATION_HPP
#include <nana/paint/image.hpp>
#include <functional>
#include <memory>
namespace nana
{
class animation;
/// Holds the frames and frame builders. Have reference semantics for efficiency.
class frameset
{
friend class animation;
public:
/// function which builds frames.
typedef std::function<bool(std::size_t pos, paint::graphics&, nana::size&)> framebuilder;
struct impl;
public:
frameset();
void push_back(const paint::image&); ///< Inserts frames at the end.
void push_back(paint::image&&);
void push_back(framebuilder& fb, std::size_t length); ///< Insters a framebuilder and the number of frames that it generates.
void push_back(framebuilder&& fb, std::size_t length); ///< Insters a framebuilder and the number of frames that it generates.
private:
std::shared_ptr<impl> impl_;
};
/// Easy way to display an animation or create an animated GUI
class animation
{
struct branch_t
{
frameset frames;
std::function<std::size_t(const std::string&, std::size_t, std::size_t&)> condition;
};
struct impl;
class performance_manager;
public:
animation();
void push_back(const frameset& frms);
/*
void branch(const std::string& name, const frameset& frms)
{
impl_->branches[name].frames = frms;
}
void branch(const std::string& name, const frameset& frms, std::function<std::size_t(const std::string&, std::size_t, std::size_t&)> condition)
{
auto & br = impl_->branches[name];
br.frames = frms;
br.condition = condition;
}
*/
void looped(bool enable); ///< Enables or disables the animation repeating playback.
void play();
void pause();
void output(window wd, const nana::point& pos);
private:
impl * impl_;
};
} //end namespace nana
#endif //NANA_GUI_ANIMATION_HPP

241
include/nana/gui/basis.hpp Normal file
View File

@@ -0,0 +1,241 @@
/*
* Basis Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/basis.hpp
*
* This file provides basis class and data structrue that required by gui
*/
#ifndef NANA_GUI_BASIS_HPP
#define NANA_GUI_BASIS_HPP
#include "../basic_types.hpp"
#include "../traits.hpp" //metacomp::fixed_type_set
namespace nana
{
namespace detail
{
struct native_window_handle_impl{};
struct window_handle_impl{};
struct event_handle_impl{};
}
enum class checkstate
{
unchecked, checked, partial
};
enum class window_border
{
none,
left, right, top, bottom,
top_left, top_right, bottom_left, bottom_right
};
enum class bground_mode
{
none,
basic,
blend
};
namespace category
{
enum class flags
{
super,
widget = 0x1,
lite_widget = 0x3,
root = 0x5,
frame = 0x9
};
//wait for constexpr
struct widget_tag{ static const flags value = flags::widget; };
struct lite_widget_tag : widget_tag{ static const flags value = flags::lite_widget;};
struct root_tag : widget_tag{ static const flags value = flags::root; };
struct frame_tag: widget_tag{ static const flags value = flags::frame; };
}// end namespace category
typedef detail::native_window_handle_impl * native_window_type;
typedef detail::window_handle_impl* window; ///< \see [What is window class ](https://sourceforge.net/p/nanapro/discussion/general/thread/bd0fabfb/)
typedef detail::event_handle_impl* event_handle;
struct keyboard
{
enum t{
//Control Code for ASCII
select_all = 0x1,
end_of_text = 0x3, //Ctrl+C
backspace = 0x8, tab = 0x9,
enter_n = 0xA, enter = 0xD, enter_r = 0xD,
alt = 0x12,
sync_idel = 0x16, //Ctrl+V
cancel = 0x18, //Ctrl+X
end_of_medium = 0x19, //Ctrl+Y
substitute = 0x1A, //Ctrl+Z
escape = 0x1B,
//The following names are intuitive name of ASCII control codes
copy = 0x3, //end_of_text
paste = 0x16, //sync_idel
cut = 0x18, //cancel
redo = 0x19, //end_of_medium
undo = 0x1A, //substitue
//System Code for OS
os_pageup = 0x21, os_pagedown,
os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down,
os_insert = 0x2D, os_del
};
};
namespace color
{
enum
{
white = 0xFFFFFF,
blue = 0x0000FF,
green = 0x00FF00,
red = 0xFF0000,
button_face_shadow_start = 0xF5F4F2,
button_face_shadow_end = 0xD5D2CA,
button_face = 0xD4D0C8,
dark_border = 0x404040,
gray_border = 0x808080,
highlight = 0x1CC4F7
};
};
enum class cursor
{
hand = 60, ///< displays a hand to indicate a text or an element is clickable
arrow = 68, ///< the default shape
wait = 150, ///< indicates the system is currently busy
iterm = 152, ///< A text caret. Displays a caret to indicate the UI is input able
size_we = 108,
size_ns = 116,
size_top_left = 134,
size_top_right = 136,
size_bottom_left = 12,
size_bottom_right = 14
};
enum class mouse
{
any_button,
left_button,
middle_button,
right_button
};
enum class z_order_action
{
none,
bottom, ///< brings a window at the bottom of z-order.
top, ///< brings a widget at the top of the z-order.
topmost, ///< brings a window at the top of the z-order and stays here.
foreground ///< brings a window to the foreground.
};
/// Window appearance structure defined to specify the appearance of a form
struct appearance
{
bool taskbar;
bool floating;
bool no_activate;
bool minimize;
bool maximize;
bool sizable;
bool decoration;
appearance();
appearance(bool has_decoration, bool taskbar, bool floating, bool no_activate, bool min, bool max, bool sizable);
};
/// Provided to generate an appearance object with better readability and understandability
struct appear
{
struct minimize{};
struct maximize{};
struct sizable{};
struct taskbar{};
struct floating{};
struct no_activate{};
/// Create an appearance of a window with "decoration"
template< typename Minimize = null_type,
typename Maximize = null_type,
typename Sizable = null_type,
typename Floating = null_type,
typename NoActive = null_type>
struct decorate
{
typedef meta::fixed_type_set<Minimize, Maximize, Sizable, Floating, NoActive> set_type;
operator appearance() const
{
return appearance( true, true,
set_type::template count<floating>::value,
set_type::template count<no_activate>::value,
set_type::template count<minimize>::value,
set_type::template count<maximize>::value,
set_type::template count<sizable>::value
);
}
};
/// Create an appearance of a window without "decoration"
template < typename Taskbar = null_type,
typename Floating = null_type,
typename NoActive = null_type,
typename Minimize = null_type,
typename Maximize = null_type,
typename Sizable = null_type>
struct bald
{
typedef meta::fixed_type_set<Taskbar, Floating, NoActive, Minimize, Maximize, Sizable> set_type;
operator appearance() const
{
return appearance( false,
set_type::template count<taskbar>::value,
set_type::template count<floating>::value,
set_type::template count<no_activate>::value,
set_type::template count<minimize>::value,
set_type::template count<maximize>::value,
set_type::template count<sizable>::value
);
}
};
/// Create a window with decoration depending on the first non-type template parameter
template < bool HasDecoration = true,
typename Sizable = null_type,
typename Taskbar = null_type,
typename Floating = null_type,
typename NoActive = null_type>
struct optional
{
typedef meta::fixed_type_set<Taskbar, Floating, NoActive> set_type;
operator appearance() const
{
return appearance(HasDecoration,
set_type::template count<taskbar>::value,
set_type::template count<floating>::value,
set_type::template count<no_activate>::value,
true, true,
set_type::template count<sizable>::value);
}
};
};//end namespace apper
}//end namespace nana
#endif

View File

@@ -0,0 +1,241 @@
/*
* A Basic Window Widget Definition
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/basic_window.hpp
*/
#ifndef NANA_GUI_DETAIL_BASIC_WINDOW_HPP
#define NANA_GUI_DETAIL_BASIC_WINDOW_HPP
#include "drawer.hpp"
#include "events_holder.hpp"
#include "../basis.hpp"
#include <nana/basic_types.hpp>
#include <nana/system/platform.hpp>
#include <nana/gui/effects.hpp>
#include <memory>
namespace nana{
class widget; //declaration ofr nana/widgets/widget.hpp
namespace detail
{
struct basic_window;
class caret_descriptor
{
public:
typedef basic_window core_window_t;
caret_descriptor(core_window_t*, unsigned width, unsigned height);
~caret_descriptor();
void set_active(bool);
core_window_t* window() const;
void position(int x, int y);
void effective_range(::nana::rectangle);
::nana::point position() const;
void visible(bool isshow);
bool visible() const;
::nana::size size() const;
void size(const ::nana::size&);
void update();
private:
void _m_visible(bool isshow);
private:
core_window_t* wd_;
::nana::point point_;
::nana::size size_;
::nana::size paint_size_;
bool visible_;
bool real_visible_state_;
bool out_of_range_;
::nana::rectangle effective_range_;
};//end class caret_descriptor
//tab_type
//@brief: Define some constant about tab category, these flags can be combine with operator |
struct tab_type
{
enum t
{
none, //process by nana
tabstop, //move to the next tabstop window
eating, //process by current window
};
};
//struct basic_window
//@brief: a window data structure descriptor
struct basic_window
: public events_holder
{
typedef std::vector<basic_window*> container;
struct root_context
{
bool focus_changed;
};
enum class update_state
{
none, lazy, refresh
};
struct edge_nimbus_action
{
basic_window * window;
bool rendered;
};
//basic_window
//@brief: constructor for the root window
basic_window(basic_window* owner, widget*, category::root_tag**);
template<typename Category>
basic_window(basic_window* parent, const rectangle& r, widget* wdg, Category**)
: widget_ptr(wdg), other(Category::value)
{
drawer.bind(this);
if(parent)
{
_m_init_pos_and_size(parent, r);
_m_initialize(parent);
}
}
~basic_window();
//bind_native_window
//@brief: bind a native window and baisc_window
void bind_native_window(native_window_type, unsigned width, unsigned height, unsigned extra_width, unsigned extra_height, paint::graphics&);
void frame_window(native_window_type);
bool is_ancestor_of(const basic_window* wd) const;
bool visible_parents() const;
bool belong_to_lazy() const;
public:
//Override event_holder
bool set_events(const std::shared_ptr<general_events>&) override;
general_events * get_events() const override;
private:
void _m_init_pos_and_size(basic_window* parent, const rectangle&);
void _m_initialize(basic_window* parent);
public:
#if defined(NANA_LINUX)
point pos_native;
#endif
point pos_root; //coordinate for root window
point pos_owner;
size dimension;
::nana::size min_track_size;
::nana::size max_track_size;
bool visible;
unsigned extra_width;
unsigned extra_height;
basic_window *parent;
basic_window *owner;
::nana::string title;
::nana::detail::drawer drawer; //Self Drawer with owen graphics
basic_window* root_widget; //A pointer refers to the root basic window, if the window is a root, the pointer refers to itself.
paint::graphics* root_graph; //Refer to the root buffer graphics
cursor predef_cursor;
widget* const widget_ptr;
struct flags_type
{
bool enabled :1;
bool dbl_click :1;
bool capture :1; //if mouse button is down, it always receive mouse move even the mouse is out of its rectangle
bool modal :1;
bool take_active:1; //If take_active is false, other.active_window still keeps the focus.
bool refreshing :1;
bool destroying :1;
bool dropable :1; //Whether the window has make mouse_drop event.
bool fullscreen :1; //When the window is maximizing whether it fit for fullscreen.
bool borderless :1;
unsigned Reserved :22;
unsigned char tab; //indicate a window that can receive the keyboard TAB
mouse_action action;
}flags;
struct
{
caret_descriptor* caret;
std::shared_ptr<general_events> events_ptr;
general_events* attached_events;
}together;
struct
{
color_t foreground;
color_t background;
color_t active;
}color;
struct
{
effects::edge_nimbus edge_nimbus;
effects::bground_interface * bground;
double bground_fade_rate;
}effect;
struct other_tag
{
struct attr_frame_tag
{
native_window_type container{nullptr};
std::vector<native_window_type> attach;
};
struct attr_root_tag
{
container frames; //initialization is null, it will be created while creating a frame widget. Refer to WindowManager::create_frame
container tabstop;
std::vector<edge_nimbus_action> effects_edge_nimbus;
basic_window* focus{nullptr};
basic_window* menubar{nullptr};
root_context context;
bool ime_enabled{false};
#if defined(NANA_WINDOWS)
cursor running_cursor{ nana::cursor::arrow };
#endif
cursor state_cursor{nana::cursor::arrow};
basic_window* state_cursor_window{ nullptr };
};
const category::flags category;
basic_window *active_window; //if flags.take_active is false, the active_window still keeps the focus,
//if the active_window is null, the parent of this window keeps focus.
paint::graphics glass_buffer; //if effect.bground is avaiable. Refer to window_layout::make_bground.
update_state upd_state;
union
{
attr_root_tag * root;
attr_frame_tag * frame;
}attribute;
other_tag(category::flags);
~other_tag();
}other;
native_window_type root; //root Window handle
unsigned thread_id; //the identifier of the thread that created the window.
unsigned index;
container children;
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,102 @@
/*
* A Bedrock Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/bedrock.hpp
*/
#ifndef NANA_GUI_DETAIL_BEDROCK_HPP
#define NANA_GUI_DETAIL_BEDROCK_HPP
#include "window_manager.hpp"
#include "events_operation.hpp"
#include "runtime_manager.hpp"
#include "general_events.hpp"
#include "internal_scope_guard.hpp"
namespace nana
{
namespace detail
{
struct native_interface;
class element_store;
//class bedrock
//@brief: bedrock is a fundamental core component, it provides a abstract to the OS platform
// and some basic functions.
class bedrock
{
bedrock();
public:
typedef native_interface interface_type;
typedef window_manager window_manager_t;
typedef window_manager_t::core_window_t core_window_t;
struct thread_context;
~bedrock();
void pump_event(window, bool is_modal);
void map_thread_root_buffer(core_window_t* );
static int inc_window(unsigned tid = 0);
thread_context* open_thread_context(unsigned tid = 0);
thread_context* get_thread_context(unsigned tid = 0);
void remove_thread_context(unsigned tid = 0);
static bedrock& instance();
::nana::category::flags category(core_window_t*);
core_window_t* focus();
native_window_type root(core_window_t*);
void set_menubar_taken(core_window_t*);
core_window_t* get_menubar_taken();
bool close_menu_if_focus_other_window(native_window_type focus);
void set_menu(native_window_type menu_window, bool is_keyboard_condition);
native_window_type get_menu(native_window_type owner, bool is_keyboard_condition);
native_window_type get_menu();
void remove_menu();
void empty_menu();
void get_key_state(arg_keyboard&);
bool set_keyboard_shortkey(bool yes);
bool whether_keyboard_shortkey() const;
element_store& get_element_store() const;
public:
void event_expose(core_window_t *, bool exposed);
void event_move(core_window_t*, int x, int y);
bool event_msleave(core_window_t*);
void thread_context_destroy(core_window_t*);
void thread_context_lazy_refresh();
void update_cursor(core_window_t*);
void set_cursor(core_window_t*, nana::cursor, thread_context*);
void define_state_cursor(core_window_t*, nana::cursor, thread_context*);
void undefine_state_cursor(core_window_t*, thread_context*);
public:
window_manager_t wd_manager;
events_operation evt_operation;
runtime_manager<core_window_t*, bedrock> rt_manager;
bool emit(event_code, core_window_t*, const arg_mouse&, bool ask_update, thread_context*);
bool emit(event_code, core_window_t*, const event_arg_interface&, bool ask_update, thread_context*);
bool emit_drawer(event_code, core_window_t*, const event_arg_interface&, thread_context*);
private:
void _m_emit_core(event_code, core_window_t*, bool draw_only, const event_arg_interface&);
void _m_event_filter(event_code, core_window_t*, thread_context*);
void _m_except_handler();
private:
static bedrock bedrock_object;
struct private_impl;
private_impl *impl_;
};//end class bedrock
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,165 @@
/*
* A Drawer Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/drawer.hpp
*/
#ifndef NANA_GUI_DETAIL_DRAWER_HPP
#define NANA_GUI_DETAIL_DRAWER_HPP
#include <vector>
#include "general_events.hpp"
#include <nana/paint/graphics.hpp>
#include <nana/paint/image.hpp>
#include <functional>
namespace nana
{
class widget;
class drawer_trigger
: ::nana::noncopyable, ::nana::nonmovable
{
public:
typedef widget& widget_reference;
typedef paint::graphics& graph_reference;
virtual ~drawer_trigger();
virtual void attached(widget_reference, graph_reference); //none-const
virtual void detached(); //none-const
virtual void typeface_changed(graph_reference);
virtual void refresh(graph_reference);
virtual void resizing(graph_reference, const arg_resizing&);
virtual void resized(graph_reference, const arg_resized&);
virtual void move(graph_reference, const arg_move&);
virtual void click(graph_reference, const arg_mouse&);
virtual void dbl_click(graph_reference, const arg_mouse&);
virtual void mouse_enter(graph_reference, const arg_mouse&);
virtual void mouse_move(graph_reference, const arg_mouse&);
virtual void mouse_leave(graph_reference, const arg_mouse&);
virtual void mouse_down(graph_reference, const arg_mouse&);
virtual void mouse_up(graph_reference, const arg_mouse&);
virtual void mouse_wheel(graph_reference, const arg_wheel&);
virtual void mouse_dropfiles(graph_reference, const arg_dropfiles&);
virtual void focus(graph_reference, const arg_focus&);
virtual void key_press(graph_reference, const arg_keyboard&);
virtual void key_char(graph_reference, const arg_keyboard&);
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};
};
namespace detail
{
struct basic_window;
namespace dynamic_drawing
{
//declaration
class object;
}
//@brief: Every window has a drawer, the drawer holds a drawer_trigger for
// a widget.
class drawer
: nana::noncopyable, nana::nonmovable
{
enum{
event_size = static_cast<int>(event_code::end)
};
enum class method_state
{
unknown,
overrided,
not_overrided
};
public:
~drawer();
void bind(basic_window*);
void typeface_changed();
void click(const arg_mouse&);
void dbl_click(const arg_mouse&);
void mouse_enter(const arg_mouse&);
void mouse_move(const arg_mouse&);
void mouse_leave(const arg_mouse&);
void mouse_down(const arg_mouse&);
void mouse_up(const arg_mouse&);
void mouse_wheel(const arg_wheel&);
void mouse_dropfiles(const arg_dropfiles&);
void resizing(const arg_resizing&);
void resized(const arg_resized&);
void move(const arg_move&);
void focus(const arg_focus&);
void key_press(const arg_keyboard&);
void key_char(const arg_keyboard&);
void key_release(const arg_keyboard&);
void shortkey(const arg_keyboard&);
void map(window); //Copy the root buffer to screen
void refresh();
drawer_trigger* realizer() const;
void attached(widget&, drawer_trigger&);
drawer_trigger* detached();
public:
void clear();
void* draw(std::function<void(paint::graphics&)> &&, bool diehard);
void erase(void* diehard);
private:
void _m_bground_pre();
void _m_bground_end();
void _m_draw_dynamic_drawing_object();
void _m_use_refresh();
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 (method_state::not_overrided != mth_state_[pos])
{
_m_bground_pre();
if (method_state::unknown == mth_state_[pos])
{
realizer_->_m_reset_overrided();
(realizer_->*mfptr)(graphics, arg);
mth_state_[pos] = (realizer_->_m_overrided() ? method_state::overrided : method_state::not_overrided);
}
else
(realizer_->*mfptr)(graphics, arg);
_m_use_refresh();
_m_draw_dynamic_drawing_object();
_m_bground_end();
}
}
}
public:
nana::paint::graphics graphics;
private:
basic_window* core_window_{nullptr};
drawer_trigger* realizer_{nullptr};
std::vector<dynamic_drawing::object*> dynamic_drawing_objects_;
bool refreshing_{false};
method_state mth_state_[event_size];
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,69 @@
/*
* Dynamic Drawing Object Implementation
* Copyright(C) 2003-2013 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: nana/gui/detail/dynamic_drawing_object.hpp
*
* !DON'T INCLUDE THIS HEADER FILE IN YOUR SOURCE CODE
*/
#ifndef NANA_GUI_DETAIL_DYNAMIC_DRAWING_OBJECT_HPP
#define NANA_GUI_DETAIL_DYNAMIC_DRAWING_OBJECT_HPP
#include <nana/paint/graphics.hpp>
#include <nana/paint/image.hpp>
namespace nana
{
namespace detail
{
namespace dynamic_drawing
{
class object
{
object(const object&) = delete;
object& operator=(const object&) = delete;
public:
object(){}
virtual ~object(){}
virtual bool diehard() const
{
return false;
}
virtual void draw(nana::paint::graphics&) const = 0;
};
//user_draw_function
class user_draw_function
: public object
{
public:
user_draw_function(std::function<void(paint::graphics&)> && f, bool diehard)
: diehard_(diehard), fn_(std::move(f))
{}
void draw(paint::graphics& graph) const
{
fn_(graph);
}
bool diehard() const
{
return diehard_;
}
private:
bool diehard_;
std::function<void(paint::graphics&)> fn_;
};
}//end namespace dynamic_drawing
}
}//end namespace nana
#endif

View File

@@ -0,0 +1,152 @@
#ifndef NANA_GUI_DETAIL_EFFECTS_RENDERER_HPP
#define NANA_GUI_DETAIL_EFFECTS_RENDERER_HPP
#include <nana/gui/effects.hpp>
#include <nana/paint/graphics.hpp>
#include <nana/paint/pixel_buffer.hpp>
#include <nana/gui/layout_utility.hpp>
namespace nana{
namespace detail
{
template<typename CoreWindow>
class edge_nimbus_renderer
{
edge_nimbus_renderer(){}
public:
typedef CoreWindow core_window_t;
typedef window_layout window_layer;
typedef nana::paint::graphics & graph_reference;
static edge_nimbus_renderer& instance()
{
static edge_nimbus_renderer object;
return object;
}
std::size_t weight() const
{
return 2;
}
bool render(core_window_t * wd)
{
bool rendered = false;
core_window_t * root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
if(nimbus.size())
{
core_window_t * focused = root_wd->other.attribute.root->focus;
native_window_type native = root_wd->root;
std::size_t pixels = weight();
auto graph = root_wd->root_graph;
std::vector<core_window_t*> erase;
std::vector<rectangle> r_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;
r_set.push_back(r);
action.rendered = true;
}
else if(action.rendered)
{
action.rendered = false;
erase.push_back(action.window);
}
}
//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);
}
auto visual_iterator = r_set.begin();
//Render
for(auto & action : nimbus)
{
if(action.rendered)
_m_render_edge_nimbus(action.window, *(visual_iterator++));
}
}
return rendered;
}
private:
static bool _m_edge_nimbus(core_window_t * focused_wd, core_window_t * wd)
{
if((focused_wd == wd) && (static_cast<unsigned>(wd->effect.edge_nimbus) & static_cast<unsigned>(effects::edge_nimbus::active)))
return true;
else if((static_cast<unsigned>(wd->effect.edge_nimbus) & static_cast<unsigned>(effects::edge_nimbus::over)) && (wd->flags.action == mouse_action::over))
return true;
return false;
}
void _m_render_edge_nimbus(core_window_t* wd, const nana::rectangle & visual)
{
nana::rectangle r(visual);
r.pare_off(-static_cast<int>(weight()));
nana::rectangle good_r;
if(overlap(r, nana::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))
{
auto graph = wd->root_graph;
nana::paint::pixel_buffer pixbuf(graph->handle(), r);
pixel_rgb_t px0, px1, px2, px3;
px0 = pixbuf.pixel(0, 0);
px1 = pixbuf.pixel(r.width - 1, 0);
px2 = pixbuf.pixel(0, r.height - 1);
px3 = pixbuf.pixel(r.width - 1, r.height - 1);
good_r.x = good_r.y = 1;
good_r.width = r.width - 2;
good_r.height = r.height - 2;
pixbuf.rectangle(good_r, wd->color.active, 0.95, false);
good_r.x = good_r.y = 0;
good_r.width = r.width;
good_r.height = r.height;
pixbuf.rectangle(good_r, wd->color.active, 0.4, false);
pixbuf.pixel(0, 0, px0);
pixbuf.pixel(r.width - 1, 0, px1);
pixbuf.pixel(0, r.height - 1, px2);
pixbuf.pixel(r.width - 1, r.height - 1, px3);
pixbuf.paste(wd->root, r.x, r.y);
std::vector<typename window_layer::wd_rectangle> overlaps;
if(window_layer::read_overlaps(wd, visual, overlaps))
{
for(auto & wdr : overlaps)
graph->paste(wd->root, wdr.r, wdr.r.x, wdr.r.y);
}
}
else
wd->root_graph->paste(wd->root, visual, visual.x, visual.y);
}
}
};
}
}//end namespace nana
#endif

View File

@@ -0,0 +1,52 @@
/*
* The Store for the Storage Of Elements
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/element_store.hpp
*/
#ifndef NANA_GUI_DETAIL_ELEMENT_STORE_HPP
#define NANA_GUI_DETAIL_ELEMENT_STORE_HPP
#include <nana/gui/element.hpp>
#include <nana/pat/cloneable.hpp>
#include <map>
#include <string>
namespace nana
{
namespace detail
{
class element_store
{
typedef ::nana::element::element_interface element_interface;
typedef pat::cloneable< ::nana::element::element_interface> cloneable_element;
struct data
{
cloneable_element object;
::nana::element::element_interface * fast_ptr;
data();
};
struct store
{
std::map<std::string, data> table;
};
public:
element_interface * const * bground(const std::string&);
void bground(const std::string&, const pat::cloneable<element_interface>&);
void bground(const std::string&, pat::cloneable<element_interface>&&);
private:
store bground_;
};
}//end namespace detail
}
#endif

View File

@@ -0,0 +1,48 @@
/*
* Definitions of General Events Code
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2016 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: nana/gui/detail/event_code.hpp
*
*/
#ifndef NANA_DETAIL_EVENT_CODE_HPP
#define NANA_DETAIL_EVENT_CODE_HPP
namespace nana
{
enum class event_code
{
click, ///< A mouse click event.
dbl_click, ///< A mouse double click event.
mouse_enter, ///< A mouse enters a widget.
mouse_move, ///< A mouse moves over a widget.
mouse_leave, ///< A mouse leaves a widget.
mouse_down, ///< A mouse button is pressed on a widget.
mouse_up, ///< A mouse button is released on a widget.
mouse_wheel, ///< A mouse scrolls the wheel on a widget.
mouse_drop, ///< A mouse release over a window that is registered as recipient of drag and drop.
expose, ///<
resizing, ///< A widget's size is sizing. In this event, A widget's size can be overrided with a new size.
resized, ///< A widget's size is changing.
move, ///<
unload, ///< A form is closed by clicking the X button, only works for root widget.
destroy, ///< A widget is about to be destroyed.
focus, ///< A widget's focus is changed.
key_press, ///< A keyboard is pressed on a focus widget.
key_char, ///< The focus widget received a character.
key_release, ///< A keyboard is released on a focus widget.
shortkey, ///< The widgets received a shortkey message.
elapse, ///< Unoperational events? . A widget received a tick that is sended by timer.
end ///< End indicator, it's not an event.
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,20 @@
#ifndef NANA_DETAIL_EVENTS_HOLDER_HPP
#define NANA_DETAIL_EVENTS_HOLDER_HPP
#include <memory>
namespace nana
{
struct general_events;
namespace detail
{
class events_holder
{
public:
virtual ~events_holder(){}
virtual bool set_events(const std::shared_ptr<general_events>&) = 0;
virtual general_events* get_events() const = 0;
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,35 @@
#ifndef NANA_DETAIL_EVENTS_OPERATION_HPP
#define NANA_DETAIL_EVENTS_OPERATION_HPP
#include <nana/gui/detail/general_events.hpp>
#include <unordered_set>
#include <unordered_map>
#if defined(NANA_MINGW) && defined(STD_THREAD_NOT_SUPPORTED)
#include <nana/std_mutex.hpp>
#else
#include <mutex>
#endif
namespace nana
{
namespace detail
{
class events_operation
{
public:
void make(window, const std::shared_ptr<general_events> &);
void umake(window);
void register_evt(event_handle);
void cancel(event_handle);
void erase(event_handle);
std::size_t size() const;
private:
mutable std::recursive_mutex mutex_;
std::unordered_set<event_handle> register_;
std::unordered_map<window, std::shared_ptr<general_events>> evt_table_;
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,497 @@
/*
* Definition of General Events
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/general_events.hpp
*/
#ifndef NANA_DETAIL_GENERAL_EVENTS_HPP
#define NANA_DETAIL_GENERAL_EVENTS_HPP
#include <nana/gui/basis.hpp>
#include "event_code.hpp"
#include "internal_scope_guard.hpp"
#include <type_traits>
#include <functional>
#include <memory>
#include <vector>
#include <algorithm>
namespace nana
{
namespace detail
{
class event_interface
{
public:
virtual ~event_interface(){}
virtual void remove(event_handle) = 0;
};
class docker_interface
{
public:
virtual ~docker_interface(){}
virtual event_interface* get_event() const = 0;
};
class event_arg_interface
{
public:
virtual ~event_arg_interface(){}
};
void events_operation_register(event_handle);
void events_operation_cancel(event_handle);
}//end namespace detail
struct general_events;
template<typename Arg>
class basic_event : public detail::event_interface
{
public:
typedef const typename std::remove_reference<Arg>::type & arg_reference;
private:
struct docker
: public detail::docker_interface
{
basic_event * const event_ptr;
std::function<void(arg_reference)> invoke;
bool flag_entered = false;
bool flag_deleted = false;
docker(basic_event * s, std::function<void(arg_reference)> && ivk)
: event_ptr(s), invoke(std::move(ivk))
{}
docker(basic_event * s, const std::function<void(arg_reference)> & ivk)
: event_ptr(s), invoke(ivk)
{}
~docker()
{
detail::events_operation_cancel(reinterpret_cast<event_handle>(this));
}
detail::event_interface * get_event() const override
{
return event_ptr;
}
};
public:
template<typename Function>
event_handle connect_front(Function && fn)
{
internal_scope_guard lock;
if (nullptr == dockers_)
dockers_.reset(new std::vector<std::unique_ptr<docker>>);
typedef typename std::remove_reference<Function>::type prototype;
std::unique_ptr<docker> dck(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn))));
auto evt = reinterpret_cast<event_handle>(static_cast<detail::docker_interface*>(dck.get()));
dockers_->emplace(dockers_->begin(), std::move(dck));
detail::events_operation_register(evt);
return evt;
}
event_handle connect(void (*fn)(arg_reference))
{
return connect([fn](arg_reference arg){
fn(arg);
});
}
template<typename Function>
event_handle connect(Function && fn)
{
internal_scope_guard lock;
if (nullptr == dockers_)
dockers_.reset(new std::vector<std::unique_ptr<docker>>);
typedef typename std::remove_reference<Function>::type prototype;
std::unique_ptr<docker> dck(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn))));
auto evt = reinterpret_cast<event_handle>(static_cast<detail::docker_interface*>(dck.get()));
dockers_->emplace_back(std::move(dck));
detail::events_operation_register(evt);
return evt;
}
template<typename Function>
event_handle operator()(Function&& fn)
{
return connect(std::forward<Function>(fn));
}
std::size_t length() const
{
internal_scope_guard lock;
return (nullptr == dockers_ ? 0 : dockers_->size());
}
void emit(arg_reference& arg) const
{
internal_scope_guard lock;
if (nullptr == dockers_)
return;
//Make a copy to allow create/destroy a new event handler when the call of emit in an event.
const std::size_t fixed_size = 10;
docker* fixed_buffer[fixed_size];
docker** transitory = fixed_buffer;
std::unique_ptr<docker*[]> variable_buffer;
auto& dockers = *dockers_;
if (dockers.size() > fixed_size)
{
variable_buffer.reset(new docker*[dockers.size()]);
transitory = variable_buffer.get();
}
auto output = transitory;
for (auto & dck : dockers)
{
(*output++) = dck.get();
}
for (; transitory != output; ++transitory)
{
std::unique_ptr<docker> p(*transitory);
auto i = std::find(dockers.begin(), dockers.end(), p);
if (i != dockers.end())
{
(*transitory)->flag_entered = true;
(*transitory)->invoke(arg);
(*transitory)->flag_entered = false;
if ((*transitory)->flag_deleted)
dockers.erase(i);
}
p.release();
}
}
void clear()
{
internal_scope_guard lock;
if (dockers_)
dockers_.reset();
}
void remove(event_handle evt)
{
internal_scope_guard lock;
if (dockers_)
{
auto i = std::find_if(dockers_->begin(), dockers_->end(), [evt](const std::unique_ptr<docker>& sp)
{
return (reinterpret_cast<detail::docker_interface*>(evt) == sp.get());
});
if (i != dockers_->end())
{
if (i->get()->flag_entered)
i->get()->flag_deleted = true;
else
dockers_->erase(i);
}
}
}
private:
template<typename Fn, bool IsBind>
struct factory
{
static std::function<void(arg_reference)> build(Fn && fn)
{
return std::move(fn);
}
static std::function<void(arg_reference)> build(const Fn & fn)
{
return fn;
}
};
template<typename Fn>
struct factory<Fn, false>
{
typedef typename std::remove_reference<arg_reference>::type arg_type;
typedef typename std::remove_reference<Fn>::type fn_type;
template<typename Tfn>
static std::function<void(arg_reference)> build(Tfn && fn)
{
typedef typename std::remove_reference<Tfn>::type type;
return build_second(std::forward<Tfn>(fn), &type::operator());
}
template<typename Tfn, typename Ret>
static std::function<void(arg_reference)> build_second(Tfn&& fn, Ret(fn_type::*)())
{
return [fn](arg_reference) mutable
{
fn();
};
}
static std::function<void(arg_reference)> build_second(fn_type&& fn, void(fn_type::*)(arg_reference))
{
return std::move(fn);
}
template<typename Tfn, typename Ret>
static std::function<void(arg_reference)> build_second(Tfn&& fn, Ret(fn_type::*)()const)
{
return [fn](arg_reference) mutable
{
fn();
};
}
static std::function<void(arg_reference)> build_second(fn_type&& fn, void(fn_type::*)(arg_reference) const)
{
return std::move(fn);
}
template<typename Tfn, typename Ret, typename Arg2>
static std::function<void(arg_reference)> build_second(Tfn&& fn, Ret(fn_type::*)(Arg2))
{
static_assert(std::is_convertible<arg_type, Arg2>::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function.");
return[fn](arg_reference arg) mutable
{
fn(arg);
};
}
template<typename Tfn, typename Ret, typename Arg2>
static std::function<void(arg_reference)> build_second(Tfn&& fn, Ret(fn_type::*)(Arg2)const)
{
static_assert(std::is_convertible<arg_type, Arg2>::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function.");
return [fn](arg_reference arg) mutable
{
fn(arg);
};
}
};
template<typename Ret, typename Arg2>
struct factory < std::function<Ret(Arg2)>, false>
{
typedef typename std::remove_reference<arg_reference>::type arg_type;
static_assert(std::is_convertible<arg_type, Arg2>::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function.");
static std::function<void(arg_reference)> build(const std::function<Ret(Arg2)>& fn)
{
return [fn](arg_reference arg) mutable{
fn(arg);
};
}
static std::function<void(arg_reference)> build_second(std::function<void(arg_reference)> && fn)
{
return std::move(fn);
}
};
template<typename Ret>
struct factory < std::function<Ret()>, false>
{
static std::function<void(arg_reference)> build(const std::function<Ret()>& fn)
{
return[fn](arg_reference) mutable{
fn();
};
}
};
template<typename Ret>
struct factory < Ret(*)(), false>
{
static std::function<void(arg_reference)> build(Ret(*fn)())
{
return[fn](arg_reference) mutable{
fn();
};
}
};
template<typename Ret, typename Arg2>
struct factory < Ret(*)(Arg2), false>
{
typedef typename std::remove_reference<arg_reference>::type arg_type;
static_assert(std::is_convertible<arg_type, Arg2>::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function.");
static std::function<void(arg_reference)> build(Ret(*fn)(Arg2))
{
return[fn](arg_reference arg) mutable {
fn(arg);
};
}
};
template<typename Ret>
struct factory < Ret(), false>
{
static std::function<void(arg_reference)> build(Ret(*fn)())
{
return[fn](arg_reference){
fn();
};
}
};
template<typename Ret, typename Arg2>
struct factory < Ret(Arg2), false>
{
typedef typename std::remove_reference<arg_reference>::type arg_type;
static_assert(std::is_convertible<arg_type, Arg2>::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function.");
static std::function<void(arg_reference)> build(Ret(*fn)(Arg))
{
return[fn](arg_reference arg){
fn(arg);
};
}
};
private:
std::unique_ptr<std::vector<std::unique_ptr<docker>>> dockers_;
};
struct arg_mouse
: public detail::event_arg_interface
{
event_code evt_code;
::nana::window window_handle;
::nana::point pos;
bool left_button;
bool mid_button;
bool right_button;
bool shift;
bool ctrl;
};
struct arg_wheel : public arg_mouse
{
enum class wheel{
vertical,
horizontal
};
wheel which; ///<which wheel is rotated
bool upwards; ///< true if the wheel is rotated to the top/left, depends on which. false otherwise.
unsigned distance; //expressed in multiples or divisions of 120
};
struct arg_dropfiles : public detail::event_arg_interface
{
::nana::window window_handle;
::nana::point pos;
std::vector<nana::string> files;
};
struct arg_expose : public detail::event_arg_interface
{
::nana::window window_handle;
bool exposed;
};
struct arg_focus : public detail::event_arg_interface
{
::nana::window window_handle;
::nana::native_window_type receiver;
bool getting;
};
struct arg_keyboard : public detail::event_arg_interface
{
event_code evt_code;
::nana::window window_handle;
mutable nana::char_t key;
mutable bool ignore;
bool ctrl;
bool shift;
};
struct arg_move : public detail::event_arg_interface
{
::nana::window window_handle;
int x;
int y;
};
struct arg_resized : public detail::event_arg_interface
{
::nana::window window_handle;
unsigned width;
unsigned height;
};
struct arg_resizing : public detail::event_arg_interface
{
::nana::window window_handle;
window_border border;
mutable unsigned width;
mutable unsigned height;
};
struct arg_unload : public detail::event_arg_interface
{
::nana::window window_handle;
mutable bool cancel;
};
struct arg_destroy : public detail::event_arg_interface
{
::nana::window window_handle;
};
struct general_events
{
virtual ~general_events(){}
basic_event<arg_mouse> mouse_enter;
basic_event<arg_mouse> mouse_move;
basic_event<arg_mouse> mouse_leave;
basic_event<arg_mouse> mouse_down;
basic_event<arg_mouse> mouse_up;
basic_event<arg_mouse> click;
basic_event<arg_mouse> dbl_click;
basic_event<arg_wheel> mouse_wheel;
basic_event<arg_dropfiles> mouse_dropfiles;
basic_event<arg_expose> expose;
basic_event<arg_focus> focus;
basic_event<arg_keyboard> key_press;
basic_event<arg_keyboard> key_release;
basic_event<arg_keyboard> key_char;
basic_event<arg_keyboard> shortkey;
basic_event<arg_move> move;
basic_event<arg_resizing> resizing;
basic_event<arg_resized> resized;
basic_event<arg_destroy> destroy;
};
namespace detail
{
struct events_root_extension
: public general_events
{
basic_event<arg_unload> unload;
};
}//end namespace detail
namespace dev
{
template<typename Widget>
struct event_mapping
{
typedef general_events type;
};
}//end namespace dev
}//end namespace nana
#endif

View File

@@ -0,0 +1,287 @@
/*
* Handle Manager Implementation
* Copyright(C) 2003-2013 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: nana/gui/detail/handle_manager.hpp
*
* @description:
* this manages all the window handles
*/
#ifndef NANA_GUI_DETAIL_HANDLE_MANAGER_HPP
#define NANA_GUI_DETAIL_HANDLE_MANAGER_HPP
#include <nana/traits.hpp>
#include <nana/config.hpp>
#if defined(NANA_MINGW) && defined(STD_THREAD_NOT_SUPPORTED)
#include <nana/std_mutex.hpp>
#else
#include <mutex>
#endif
#include <map>
#include <iterator>
#include <algorithm>
namespace nana
{
namespace detail
{
template<typename Key, typename Value, std::size_t CacheSize>
class cache
: noncopyable
{
public:
typedef Key key_type;
typedef Value value_type;
typedef std::pair<key_type, value_type> pair_type;
typedef std::size_t size_type;
cache()
:addr_(reinterpret_cast<pair_type*>(::operator new(sizeof(pair_type) * CacheSize)))
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
bitmap_[i] = 0;
seq_[i] = nana::npos;
}
}
~cache()
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
if(bitmap_[i])
addr_[i].~pair_type();
}
::operator delete(addr_);
}
bool insert(key_type k, value_type v)
{
size_type pos = _m_find_key(k);
if(pos != nana::npos)
{
addr_[pos].second = v;
}
else
{
//No key exists
pos = _m_find_pos();
if(pos == nana::npos)
{ //No room, and remove the last pair
pos = seq_[CacheSize - 1];
(addr_ + pos)->~pair_type();
}
if(seq_[0] != nana::npos)
{//Need to move
for(int i = CacheSize - 1; i > 0; --i)
seq_[i] = seq_[i - 1];
}
seq_[0] = pos;
new (addr_ + pos) pair_type(k, v);
bitmap_[pos] = 1;
}
return v;
}
value_type * get(key_type k)
{
size_type pos = _m_find_key(k);
if(pos != nana::npos)
return &(addr_[pos].second);
return 0;
}
private:
size_type _m_find_key(key_type k) const
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
if(bitmap_[i] && (addr_[i].first == k))
return i;
}
return nana::npos;
}
size_type _m_find_pos() const
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
if(bitmap_[i] == 0)
return i;
}
return nana::npos;
}
private:
char bitmap_[CacheSize];
size_type seq_[CacheSize];
pair_type * addr_;
};
//handle_manager
//@brief
// handle_manager maintains handles of a type. removing a handle dose not destroy it,
// it will be inserted to a trash queue for deleting at a safe time.
// For efficiency, this class is not a thread-safe.
template<typename HandleType, typename Condition, typename Deleter>
class handle_manager
: nana::noncopyable
{
public:
typedef HandleType handle_type;
typedef Condition cond_type;
typedef Deleter deleter_type;
typedef std::map<handle_type, unsigned> handle_map_t;
typedef std::pair<handle_type, unsigned> holder_pair;
~handle_manager()
{
delete_trash(0);
}
void insert(handle_type handle, unsigned tid)
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
holder_[handle] = tid;
is_queue<std::is_same<cond_type, nana::null_type>::value, std::vector<handle_type> >::insert(handle, queue_);
cacher_.insert(handle, true);
}
void operator()(const handle_type handle)
{
remove(handle);
}
void remove(const handle_type handle)
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
auto i = static_cast<const handle_map_t&>(holder_).find(handle);
if(holder_.cend() != i)
{
is_queue<std::is_same<cond_type, nana::null_type>::value, std::vector<handle_type> >::erase(handle, queue_);
cacher_.insert(handle, false);
trash_.emplace_back(i->first, i->second);
holder_.erase(i);
}
}
void delete_trash(unsigned tid)
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(trash_.size())
{
deleter_type del_functor;
if(tid == 0)
{
for(auto & m : trash_)
del_functor(m.first);
trash_.clear();
}
else
{
for(auto i = trash_.begin(), end = trash_.end(); i != end;)
{
if(tid == i->second)
{
del_functor(i->first);
i = trash_.erase(i);
end = trash_.end();
}
else
++i;
}
}
}
}
handle_type last() const
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(queue_.size())
return queue_.back();
return handle_type();
}
std::size_t size() const
{
return holder_.size();
}
handle_type get(unsigned index) const
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(index < queue_.size())
return queue_[index];
return handle_type();
}
bool available(const handle_type handle) const
{
if (nullptr == handle)
return false;
std::lock_guard<decltype(mutex_)> lock(mutex_);
bool * v = cacher_.get(handle);
if(v) return *v;
return cacher_.insert(handle, (holder_.count(handle) != 0));
}
void all(std::vector<handle_type> & v) const
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
std::copy(queue_.cbegin(), queue_.cend(), std::back_inserter(v));
}
private:
template<bool IsQueueOperation, typename Container>
struct is_queue
{
public:
static void insert(handle_type handle, Container& queue)
{
if(cond_type::is_queue(handle))
queue.push_back(handle);
}
static void erase(handle_type handle, Container& queue)
{
if(cond_type::is_queue(handle))
{
auto i = std::find(queue.begin(), queue.end(), handle);
if(i != queue.end())
queue.erase(i);
}
}
};
template<typename Container>
struct is_queue<true, Container>
{
public:
static void insert(handle_type handle, Container& queue){}
static void erase(handle_type handle, Container& queue){}
};
private:
mutable std::recursive_mutex mutex_;
mutable cache<const handle_type, bool, 5> cacher_;
handle_map_t holder_;
std::vector<handle_type> queue_;
std::vector<holder_pair> trash_;
};//end class handle_manager
}//end namespace detail
}// end namespace nana
#endif

View File

@@ -0,0 +1,55 @@
/*
* Inner Forward Declaration
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/inner_fwd.hpp
*
*/
#ifndef NANA_GUI_INNER_FWD_HPP
#define NANA_GUI_INNER_FWD_HPP
#include <nana/deploy.hpp>
namespace nana{
namespace detail
{
struct signals
{
enum class code
{
caption,
read_caption,
destroy,
size,
end
};
union
{
const nana::char_t* caption;
nana::string * str;
struct
{
unsigned width;
unsigned height;
}size;
}info;
};
class signal_invoker_interface
{
public:
virtual ~signal_invoker_interface()
{}
virtual void call_signal(signals::code, const signals&) = 0;
};
}
}
#endif //NANA_GUI_INNER_FWD_HPP

View File

@@ -0,0 +1,201 @@
/*
* Implementations of Inner Forward Declaration
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/inner_fwd_implement.hpp
*
*/
#ifndef NANA_GUI_INNER_FWD_IMPLEMENT_HPP
#define NANA_GUI_INNER_FWD_IMPLEMENT_HPP
#include "inner_fwd.hpp"
#include "basic_window.hpp"
#include "../../paint/graphics.hpp"
#include <map>
#include <algorithm>
namespace nana{
namespace detail
{
class shortkey_container
{
struct item_type
{
window handle;
std::vector<unsigned long> keys;
};
public:
void clear()
{
keybase_.clear();
}
bool make(window wd, unsigned long key)
{
if (wd == nullptr) return false;
if (key < 0x61) key += (0x61 - 0x41);
for (auto & m : keybase_)
{
if (m.handle == wd)
{
m.keys.push_back(key);
return true;
}
}
item_type m;
m.handle = wd;
m.keys.push_back(key);
keybase_.push_back(m);
return true;
}
void umake(window wd)
{
if (wd == nullptr) return;
auto i = std::find_if(keybase_.begin(), keybase_.end(), [wd](const item_type& m){
return (m.handle == wd);
});
if (i != keybase_.end())
keybase_.erase(i);
}
std::vector<unsigned long> keys(window wd) const
{
std::vector<unsigned long> v;
if (wd)
{
for (auto & m : keybase_)
{
if (m.handle == wd)
{
v = m.keys;
break;
}
}
}
return v;
}
window find(unsigned long key) const
{
if (key < 0x61) key += (0x61 - 0x41);
for (auto & m : keybase_)
{
for (auto n : m.keys)
{
if (key == n)
return m.handle;
}
}
return nullptr;
}
private:
std::vector<item_type> keybase_;
};
struct root_misc
{
typedef basic_window core_window_t;
core_window_t * window;
nana::paint::graphics root_graph;
shortkey_container shortkeys;
struct condition_tag
{
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)
: window(wd),
root_graph(width, height)
{}
};//end struct root_misc
class root_register
{
public:
root_misc* insert(native_window_type wd, const root_misc& misc)
{
recent_ = wd;
auto ret = table_.insert(std::make_pair(wd, misc));
misc_ptr_ = &(ret.first->second);
return misc_ptr_;
}
root_misc * find(native_window_type wd)
{
if (wd == recent_)
return misc_ptr_;
recent_ = wd;
auto i = table_.find(wd);
if (i != table_.end())
misc_ptr_ = &(i->second);
else
misc_ptr_ = nullptr;
return misc_ptr_;
}
void erase(native_window_type wd)
{
table_.erase(wd);
recent_ = wd;
misc_ptr_ = nullptr;
}
private:
//Cached
mutable native_window_type recent_{nullptr};
mutable root_misc * misc_ptr_{nullptr};
std::map<native_window_type, root_misc> table_;
};
class signal_manager
{
typedef basic_window core_window_t;
public:
void make(core_window_t* wd, signal_invoker_interface* si)
{
if (si)
table_[wd].reset(si);
else
table_.erase(wd);
}
void umake(core_window_t * wd)
{
table_.erase(wd);
}
void call_signal(core_window_t * wd, signals::code code, const signals& s)
{
auto i = table_.find(wd);
if (i != table_.end())
i->second->call_signal(code, s);
}
private:
std::map<core_window_t*, std::unique_ptr<signal_invoker_interface>> table_;
};
}
}//end namespace nana
#endif //NANA_GUI_INNER_FWD_IMPLEMENT_HPP

View File

@@ -0,0 +1,31 @@
/*
* Forward Declaration of Internal Scope Guard
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/internal_scope_guard.hpp
*/
#ifndef NANA_GUI_DETAIL_INTERNAL_SCOPE_GUARD_HPP
#define NANA_GUI_DETAIL_INTERNAL_SCOPE_GUARD_HPP
namespace nana
{
//Implemented in bedrock
class internal_scope_guard
{
internal_scope_guard(const internal_scope_guard&) = delete;
internal_scope_guard(internal_scope_guard&&) = delete;
internal_scope_guard& operator=(const internal_scope_guard&) = delete;
internal_scope_guard& operator=(internal_scope_guard&&) = delete;
public:
internal_scope_guard();
~internal_scope_guard();
};
}
#endif

View File

@@ -0,0 +1,89 @@
/*
* Platform Implementation
* Copyright(C) 2003-2013 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: nana/gui/detail/native_window_interface.hpp
*/
#ifndef NANA_GUI_DETAIL_NATIVE_WINDOW_INTERFACE_HPP
#define NANA_GUI_DETAIL_NATIVE_WINDOW_INTERFACE_HPP
#include "../basis.hpp"
#include <nana/paint/image.hpp>
namespace nana
{
namespace detail
{
struct native_interface
{
struct window_result
{
native_window_type native_handle;
unsigned width; //client size
unsigned height; //client size
unsigned extra_width; //extra border size, it is useful in Windows, ignore in X11 always 0
unsigned extra_height; //extra border size, it is useful in Windows, ignore in X11 always 0
};
static nana::size screen_size();
static rectangle screen_area_from_point(const point&);
static window_result create_window(native_window_type, bool nested, const rectangle&, const appearance&);
static native_window_type create_child_window(native_window_type, const rectangle&);
#if defined(NANA_X11)
static void set_modal(native_window_type);
#endif
static void enable_dropfiles(native_window_type, bool);
static void enable_window(native_window_type, bool);
static bool window_icon(native_window_type, const paint::image&);
static void activate_owner(native_window_type);
static void activate_window(native_window_type);
static void close_window(native_window_type);
static void show_window(native_window_type, bool show, bool active);
static void restore_window(native_window_type);
static void zoom_window(native_window_type, bool ask_for_max);
static void refresh_window(native_window_type);
static bool is_window(native_window_type);
static bool is_window_visible(native_window_type);
static bool is_window_zoomed(native_window_type, bool ask_for_max);
static nana::point window_position(native_window_type);
static void move_window(native_window_type, int x, int y);
static void move_window(native_window_type, const rectangle&);
static void bring_to_top(native_window_type);
static void set_window_z_order(native_window_type, native_window_type wd_after, z_order_action action_if_no_wd_after);
static void window_size(native_window_type, const size&);
static void get_window_rect(native_window_type, rectangle&);
static void window_caption(native_window_type, const nana::string&);
static nana::string window_caption(native_window_type);
static void capture_window(native_window_type, bool);
static nana::point cursor_position();
static native_window_type get_owner_window(native_window_type);
//For Caret
static void caret_create(native_window_type, unsigned width, unsigned height);
static void caret_destroy(native_window_type);
static void caret_pos(native_window_type, int x, int y);
static void caret_visible(native_window_type, bool);
static void set_focus(native_window_type);
static native_window_type get_focus_window();
static bool calc_screen_point(native_window_type, nana::point&);
static bool calc_window_point(native_window_type, nana::point&);
static native_window_type find_window(int x, int y);
static nana::size check_track_size(nana::size sz, unsigned extra_width, unsigned extra_height, bool true_for_max);
};
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,100 @@
/*
* A Runtime Manager Implementation
* Copyright(C) 2003-2013 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: nana/gui/detail/runtime_manager.hpp
*
*/
#ifndef NANA_GUI_DETAIL_RUNTIME_MANAGER_HPP
#define NANA_GUI_DETAIL_RUNTIME_MANAGER_HPP
#include <map>
namespace nana
{
namespace detail
{
template<typename Window, typename Bedrock>
class runtime_manager
{
public:
typedef Window window_handle;
template<typename Form, typename... Args>
Form* create_form(Args&&... args)
{
widget_placer<Form> * holder = new widget_placer<Form>;
if (holder->create(std::forward<Args>(args)...))
{
holder_[holder->get_handle()] = holder;
return holder->get();
}
delete holder;
return nullptr;
}
void remove_if_exists(window_handle wd)
{
auto i = holder_.find(wd);
if(i != holder_.cend())
{
delete i->second;
holder_.erase(i);
}
}
private:
class widget_holder
{
public:
virtual ~widget_holder(){}
virtual window_handle get_handle() const = 0;
};
template<typename Form>
class widget_placer : public widget_holder
{
public:
widget_placer()
: form_(nullptr)
{}
~widget_placer()
{
delete form_;
}
template<typename... Args>
bool create(Args&&... args)
{
if (nullptr == form_)
form_ = new Form(std::forward<Args>(args)...);
return (form_ && !form_->empty());
}
Form* get() const
{
return form_;
}
window_handle get_handle() const override
{
return reinterpret_cast<window_handle>(form_ ? form_->handle() : nullptr);
}
private:
Form * form_;
};
private:
std::map<window_handle, widget_holder*> holder_;
}; //end class runtime_manager
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,88 @@
/*
* Window Layout Implementation
* Copyright(C) 2003-2013 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: nana/gui/detail/window_layout.hpp
*
*/
#ifndef NANA_GUI_DETAIL_WINDOW_LAYOUT_HPP
#define NANA_GUI_DETAIL_WINDOW_LAYOUT_HPP
#include <nana/gui/basis.hpp>
#include <vector>
namespace nana
{
namespace paint
{
class image;
class graphics;
}
}
namespace nana{
namespace detail
{
struct basic_window;
//class window_layout
class window_layout
{
public:
typedef basic_window core_window_t;
struct wd_rectangle
{
core_window_t * window;
rectangle r;
};
public:
static void paint(core_window_t*, bool is_redraw, bool is_child_refreshed);
static bool maproot(core_window_t*, bool have_refreshed, bool is_child_refreshed);
static void paste_children_to_graphics(core_window_t*, nana::paint::graphics& graph);
//read_visual_rectangle
//@brief: Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget,
// the visual rectangle is a rectangular block that a window should be displayed on screen.
// The result is a rectangle that is a visible area for its ancesters.
static bool read_visual_rectangle(core_window_t*, nana::rectangle& visual);
//read_overlaps
// reads the overlaps that are overlapped a rectangular block
static bool read_overlaps(core_window_t*, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks);
static bool enable_effects_bground(core_window_t *, bool enabled);
//make_bground
// update the glass buffer of a glass window.
static void make_bground(core_window_t* const);
private:
//_m_paste_children
//@brief:paste children window to the root graphics directly. just paste the visual rectangle
static void _m_paste_children(core_window_t*, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos);
static void _m_paint_glass_window(core_window_t*, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other);
//_m_notify_glasses
//@brief: Notify the glass windows that are overlapped with the specified vis_rect
static void _m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& r_visual);
private:
struct data_section
{
std::vector<core_window_t*> effects_bground_windows;
};
static data_section data_sect;
};//end class window_layout
}//end namespace detail
}//end namespace nana
#endif //NANA_GUI_DETAIL_WINDOW_LAYOUT_HPP

View File

@@ -0,0 +1,225 @@
/*
* Window Manager Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/detail/window_manager.hpp
*
* <Knowledge: 1, 2007-8-17, "Difference between destroy and destroy_handle">
* destroy method destroys a window handle and the handles of its children, but it doesn't delete the handle which type is a root window or a frame
* destroy_handle method just destroys the handle which type is a root window or a frame
*
*/
#ifndef NANA_GUI_DETAIL_WINDOW_MANAGER_HPP
#define NANA_GUI_DETAIL_WINDOW_MANAGER_HPP
#include <vector>
#include "window_layout.hpp"
#include "event_code.hpp"
#include "inner_fwd.hpp"
#include <functional>
#if defined(STD_THREAD_NOT_SUPPORTED)
#include <nana/std_mutex.hpp>
#else
#include <mutex>
#endif
namespace nana
{
class widget; //forward declaration
namespace paint
{
class image;
}
}
namespace nana{
namespace detail
{
template<typename T>
class signal_invoker_mf
: public signal_invoker_interface
{
public:
signal_invoker_mf(T& obj, void(T::*mf)(signals::code, const signals&))
: obj_(obj),
mf_(mf)
{}
void call_signal(signals::code code, const signals& s) override
{
(obj_.*mf_)(code, s);
}
private:
T& obj_;
void(T::*mf_)(signals::code, const signals&);
};
struct root_misc;
class window_manager
{
class revertible_mutex
: public std::recursive_mutex
{
struct thr_refcnt
{
unsigned tid;
std::size_t refcnt;
};
public:
revertible_mutex();
void lock();
bool try_lock();
void unlock();
void revert();
void forward();
private:
thr_refcnt thr_;
std::vector<thr_refcnt> stack_;
};
public:
typedef native_window_type native_window;
typedef revertible_mutex mutex_type;
typedef basic_window core_window_t;
typedef std::vector<core_window_t*> cont_type;
typedef window_layout wndlayout_type;
window_manager();
~window_manager();
static bool is_queue(core_window_t*);
std::size_t number_of_core_window() const;
mutex_type & internal_lock() const;
void all_handles(std::vector<core_window_t*>&) const;
template<typename T, typename Concept>
void attach_signal(core_window_t* wd, T& obj, void(Concept::*mf)(signals::code, const signals&))
{
return _m_attach_signal(wd, new signal_invoker_mf<Concept>(obj, mf));
}
void signal_fire_caption(core_window_t*, const nana::char_t*);
nana::string signal_fire_caption(core_window_t*);
void event_filter(core_window_t*, bool is_make, event_code);
void default_icon(const nana::paint::image&);
bool available(core_window_t*);
bool available(core_window_t *, core_window_t*);
bool available(native_window_type);
core_window_t* create_root(core_window_t* owner, bool nested, rectangle, const appearance&, widget*);
core_window_t* create_widget(core_window_t* parent, const rectangle&, bool is_lite, widget*);
core_window_t* create_frame(core_window_t* parent, const rectangle&, widget*);
bool insert_frame(core_window_t* frame, native_window);
bool insert_frame(core_window_t* frame, core_window_t*);
void close(core_window_t*);
//destroy
//@brief: Delete the window handle
void destroy(core_window_t*);
//destroy_handle
//@brief: Delete window handle, the handle type must be a root and a frame.
void destroy_handle(core_window_t*);
void icon(core_window_t*, const paint::image&);
//show
//@brief: show or hide a window
bool show(core_window_t* wd, bool visible);
core_window_t* find_window(native_window_type root, int x, int y);
//move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window
bool move(core_window_t*, int x, int y, bool passive);
bool move(core_window_t*, const rectangle&);
bool size(core_window_t*, nana::size, bool passive, bool ask_update);
core_window_t* root(native_window_type) const;
//Copy the root buffer that wnd specified into DeviceContext
void map(core_window_t*);
bool update(core_window_t*, bool redraw, bool force);
void refresh_tree(core_window_t*);
bool do_lazy_refresh(core_window_t*, bool force_copy_to_screen);
bool get_graphics(core_window_t*, nana::paint::graphics&);
bool get_visual_rectangle(core_window_t*, nana::rectangle&);
::nana::widget* get_widget(core_window_t*) const;
std::vector<core_window_t*> get_children(core_window_t*) const;
bool set_parent(core_window_t* wd, core_window_t* new_parent);
core_window_t* set_focus(core_window_t*, bool root_has_been_focused);
core_window_t* capture_redirect(core_window_t*);
void capture_ignore_children(bool ignore);
bool capture_window_entered(int root_x, int root_y, bool& prev);
core_window_t * capture_window() const;
core_window_t* capture_window(core_window_t*, bool value);
void enable_tabstop(core_window_t*);
core_window_t* tabstop(core_window_t*, bool forward) const; //forward means move to next in logic.
void remove_trash_handle(unsigned tid);
bool enable_effects_bground(core_window_t*, bool);
bool calc_window_point(core_window_t*, nana::point&);
root_misc* root_runtime(native_window_type) const;
bool register_shortkey(core_window_t*, unsigned long key);
void unregister_shortkey(core_window_t*, bool with_children);
std::vector<std::pair<core_window_t*, unsigned long>> shortkeys(core_window_t*, bool with_children);
core_window_t* find_shortkey(native_window_type, unsigned long key);
private:
void _m_attach_signal(core_window_t*, signal_invoker_interface*);
void _m_disengage(core_window_t*, core_window_t* for_new);
void _m_destroy(core_window_t*);
void _m_move_core(core_window_t*, const point& delta);
core_window_t* _m_find(core_window_t*, const point&);
static bool _m_effective(core_window_t*, const point& root_pos);
private:
mutable mutex_type mutex_;
struct wdm_private_impl;
wdm_private_impl * const impl_;
signals signals_;
struct attribute
{
struct captured
{
core_window_t *window;
bool inside;
bool ignore_children;
std::vector<std::pair<core_window_t*, bool> > history;
}capture;
}attr_;
struct menu_tag
{
native_window_type window;
native_window_type owner;
bool has_keyboard;
}menu_;
};//end class window_manager
}//end namespace detail
}//end namespace nana
#endif

View File

@@ -0,0 +1,29 @@
#ifndef NANA_GUI_DRAGGER_HPP
#define NANA_GUI_DRAGGER_HPP
#include "programming_interface.hpp"
namespace nana
{
/// \brief Helper class that allows the user to drag windows.
///
/// If a user presses the mouse on the specified window and moves the mouse, the specified window is dragged.
/// The drag target window and trigger window can be set more than once.
/// See [Is it possible to make event inside event handler?](https://nanapro.codeplex.com/discussions/444121)
/// and [How to make widget movable by mouse the best way](https://nanapro.codeplex.com/discussions/444058)
class dragger
: nana::noncopyable
{
class dragger_impl_t;
public:
dragger();
~dragger();
void target(window);
void target(window, const rectangle& restrict_area, nana::arrange);
void remove_target(window);
void trigger(window);
private:
dragger_impl_t * impl_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,49 @@
/*
* A Drawing Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/drawing.hpp
*/
#ifndef NANA_GUI_DRAWING_HPP
#define NANA_GUI_DRAWING_HPP
#include "widgets/widget.hpp"
#include "../traits.hpp"
namespace nana
{
/// \brief Draw pictures on a widget by specifying a drawing method that will be employed everytime the widget refreshes.
/// By the end of drawing, the picture may not be displayed immediately.
/// If a picture need to be displayed immediately call nana::gui::API::refresh_window() .
class drawing
:private nana::noncopyable
{
public:
typedef struct{}* diehard_t; ///< A handle to a drawing method
typedef std::function<void(paint::graphics&)> draw_fn_t; ///< A function to draw
drawing(window w); ///< Create a drawing object for a widget w
virtual ~drawing(); ///< Just for polymorphism
bool empty() const; ///< Returns true if the drawing object is invalid.
void update() const;
void draw(const draw_fn_t&); ///< Draws things that are defined by draw_fn_t.
void draw(draw_fn_t&&); ///< Draws things that are defined by draw_fn_t.
/// Draws things that are defined by draw_fn_t but will not be deleted when clear() is called.
diehard_t draw_diehard(const draw_fn_t&);
/// Draws things that are defined by draw_fn_t but will not be deleted when clear() is called.
diehard_t draw_diehard(draw_fn_t&&);
void erase(diehard_t); ///< Erases a diehard drawing method.
void clear(); ///< Erases all.
private:
window handle_;
};//end class drawing
}//end namespace nana
#endif

View File

@@ -0,0 +1,67 @@
/*
* Background Effects Implementation
* Copyright(C) 2003-2013 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: nana/gui/effects.hpp
*
*/
#ifndef NANA_GUI_EFFECTS_HPP
#define NANA_GUI_EFFECTS_HPP
#include <cstddef>
#include <nana/paint/graphics.hpp>
namespace nana
{
namespace effects
{
enum class edge_nimbus
{
none, active = 0x1, over = 0x2
};
class bground_interface
{
public:
typedef paint::graphics & graph_reference;
virtual ~bground_interface() = 0;
virtual void take_effect(window, graph_reference) const = 0;
};
class bground_factory_interface
{
friend class effects_accessor;
public:
virtual ~bground_factory_interface() = 0;
private:
virtual bground_interface * create() const = 0;
};
class bground_transparent
: public bground_factory_interface
{
public:
bground_transparent(std::size_t percent);
private:
virtual bground_interface* create() const;
private:
std::size_t percent_;
};
class bground_blur
: public bground_factory_interface
{
public:
bground_blur(std::size_t radius);
private:
virtual bground_interface * create() const;
private:
std::size_t radius_;
};
}
}//end namespace nana
#endif

View File

@@ -0,0 +1,194 @@
/*
* Elements of GUI Gadgets
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/element.hpp
*/
#ifndef NANA_GUI_ELEMENT_HPP
#define NANA_GUI_ELEMENT_HPP
#include <nana/paint/graphics.hpp>
#include <nana/pat/cloneable.hpp>
#include <vector>
#include <map>
namespace nana
{
namespace paint
{
//forward declaration
class image;
}
namespace element
{
class element_interface
{
public:
typedef paint::graphics & graph_reference;
virtual ~element_interface()
{}
virtual bool draw(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const nana::rectangle&, element_state) = 0;
};
class crook_interface
{
public:
typedef paint::graphics & graph_reference;
typedef checkstate state;
struct data
{
state check_state;
bool radio;
};
virtual ~crook_interface()
{}
virtual bool draw(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const nana::rectangle&, element_state, const data&) = 0;
};
class provider
{
public:
template<typename ElementInterface>
struct factory_interface
{
virtual ~factory_interface(){}
virtual ElementInterface* create() const = 0;
virtual void destroy(ElementInterface*) const = 0;
};
template<typename Element, typename ElementInterface>
class factory
: public factory_interface<ElementInterface>
{
public:
typedef factory_interface<ElementInterface> interface_type;
ElementInterface * create() const override
{
return (new Element);
}
void destroy(ElementInterface * p) const override
{
delete p;
}
};
void add_crook(const std::string& name, const pat::cloneable<factory_interface<crook_interface>>&);
crook_interface* const * keeper_crook(const std::string& name);
};
template<typename UserElement>
void add_crook(const std::string& name)
{
typedef provider::factory<UserElement, crook_interface> factory_t;
provider().add_crook(name, pat::cloneable<typename factory_t::interface_type>(factory_t()));
}
class crook;
}//end namespace element
template<typename Element> class facade;
template<>
class facade<element::crook>
: public element::element_interface
{
public:
typedef ::nana::paint::graphics & graph_reference;
typedef element::crook_interface::state state;
facade();
facade(const char* name);
facade & reverse();
facade & check(state);
state checked() const;
facade& radio(bool);
bool radio() const;
void switch_to(const char*);
public:
//Implement element_interface
bool draw(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const nana::rectangle& r, element_state) override;
private:
element::crook_interface::data data_;
element::crook_interface* const * keeper_;
};
namespace element
{
void set_bground(const char* name, const pat::cloneable<element_interface>&);
void set_bground(const char* name, pat::cloneable<element_interface> &&);
class cite_bground
{
public:
typedef paint::graphics& graph_reference;
typedef pat::cloneable<element_interface> cloneable_element;
cite_bground(const char*);
void set(const cloneable_element&);
void set(const char*);
bool draw(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const nana::rectangle&, element_state);
private:
cloneable_element holder_;
element_interface * place_ptr_;
element_interface * const * ref_ptr_;
};
class bground
: public element_interface
{
public:
typedef paint::graphics& graph_reference;
bground();
bground(const bground&);
~bground();
bground& operator=(const bground&);
bground& image(const paint::image&, bool vertical, const nana::rectangle& valid_area); ///< Set a picture for the background
bground& image(const paint::graphics&, bool vertical, const nana::rectangle& valid_area); ///< Set a picture for the background
void states(const std::vector<element_state> &); ///< Set the state sequence of the background picture.
void states(std::vector<element_state> &&); ///< Set the state sequence of the background picture.
void reset_states();
void join(element_state target, element_state joiner);
void stretch_parts(unsigned left, unsigned top, unsigned right, unsigned bottom);
//Implement the methods of element_interface.
virtual bool draw(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const nana::rectangle&, element_state);
private:
struct draw_method;
struct draw_image;
struct draw_graph;
draw_method * method_;
bool vertical_;
nana::rectangle valid_area_;
std::vector<element_state> states_;
std::map<element_state, element_state> join_;
bool stretch_all_;
unsigned left_, top_, right_, bottom_;
}; //end class bground
}//end namespace element
}//end namespace nana
#endif //NANA_GUI_ELEMENT_HPP

View File

@@ -0,0 +1,60 @@
#ifndef NANA_GUI_FILEBOX_HPP
#define NANA_GUI_FILEBOX_HPP
#include <nana/gui/wvl.hpp>
namespace nana
{ /// Create an Open or Save dialog box to let user select the name of a file.
class filebox
: nana::noncopyable
{
struct implement;
public:
typedef std::vector<std::pair<nana::string, nana::string>> filters;
filebox(window owner, bool is_open_mode);
~filebox();
/** @brief specify a title for the dialog
* @param string a text for title
*/
nana::string title( nana::string new_title); ///< . Set a new title for the dialog and \return the old title
/** @brief specify a suggestion directory
* @param string a path of initial directory
* @note the behavior of init_path is different between Win7 and Win2K/XP/Vista, but its behavior under Linux is conformed with Win7.
*/
filebox& init_path(const nana::string&); ///< Suggested init path used to locate a directory when the filebox starts.
filebox& init_file(const nana::string&); ///< Init file, if it contains a path, the init path is replaced by the path of init file.
/// \brief Add a filetype filter.
/// To specify multiple filter in a single description, use a semicolon to separate the patterns(for example,"*.TXT;*.DOC;*.BAK").
filebox& add_filter(const nana::string& description, ///< for example. "Text File"
const nana::string& filetype ///< filter pattern(for example, "*.TXT")
);
filebox& add_filter(const filters &ftres)
{
for (auto &f : ftres)
add_filter(f.first, f.second);
return *this;
};
nana::string path() const;
nana::string file() const;
/** @brief Display the filebox dialog
*/
bool show() const;
/** @brief Display the filebox dialog
* @note A function object method alternative to show()
*/
bool operator()() const
{
return show();
}
private:
implement * impl_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,43 @@
/*
* Utility Implementation
* Copyright(C) 2003-2013 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: nana/gui/layout_utility.hpp
*
*
*/
#ifndef NANA_GUI_LAYOUT_UTILITY_HPP
#define NANA_GUI_LAYOUT_UTILITY_HPP
#include "basis.hpp"
namespace nana
{
//overlap test if overlaped between r1 and r2
bool overlap(const rectangle& r1, const rectangle& r2);
// overlap, compute the overlap area between r1 and r2. the r is for root
bool overlap(const rectangle& r1, const rectangle& r2, rectangle& r);
bool overlap(const rectangle& ir, const size& valid_input_area, const rectangle & dr, const size& valid_dst_area, rectangle& output_src_r, rectangle& output_dst_r);
bool intersection(const rectangle & r, point pos_beg, point pos_end, point& good_pos_beg, point& good_pos_end);
/// Zoom the input_s to fit for ref_s
void fit_zoom(const size& input_s, const size& ref_s, size& result_s);
//zoom
//@brief: Calculate the scaled rectangle by refer dst rectangle, that scale factor is same as that between scaled and refer.
void zoom(const rectangle& refer, const rectangle& scaled, const rectangle& refer_dst, rectangle& r);
//covered
//@brief: Tests a rectangle whether it is wholly covered by another.
bool covered(const rectangle& underlying, //Rectangle 1 is must under rectangle 2
const rectangle& cover);
}//end namespace nana
#endif

View File

@@ -0,0 +1,96 @@
/*
* A Message Box Class
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2013 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: nana/gui/msgbox.hpp
*/
#ifndef NANA_GUI_MSGBOX_HPP
#define NANA_GUI_MSGBOX_HPP
#include <sstream>
#include <nana/gui/basis.hpp>
namespace nana
{
/// Prefabricated modal dialog box (with text, icon and actions buttons) that inform and instruct the user.
class msgbox
{
public:
/// Identifiers of icons.
enum icon_t{icon_none, icon_information, icon_warning, icon_error, icon_question};
/// Identifiers of buttons.
enum button_t{ok, yes_no, yes_no_cancel};
/// Identifiers of buttons that a user clicked.
enum pick_t{pick_ok, pick_yes, pick_no, pick_cancel};
/// Default construct that creates a message box with default title and default button, the default button is OK.
msgbox();
/// Copy construct from an existing msgbox object.
msgbox(const msgbox&);
/// Assign from an existing msgbox object.
msgbox& operator=(const msgbox&);
/// Construct that creates a message box with a specified title and default button.
msgbox(const nana::string&);
/// Construct that creates a message box with an owner window and a specified title.
msgbox(window, const nana::string&);
/// Construct that creates a message box with an owner windoow, a specified title and buttons.
msgbox(window, const nana::string&, button_t);
/// Sets an icon for informing user.
msgbox& icon(icon_t);
/// Clears the text message buffer.
void clear();
/// Writes a string to the buffer.
msgbox & operator<<(const nana::string&);
/// Writes a string to the buffer.
msgbox & operator<<(const nana::char_t*);
/// Writes a string to the buffer.
msgbox & operator<<(const nana::charset&);
// Calls a manipulator to the stream.
msgbox & operator<<(std::ostream& (*)(std::ostream&));
/// Write a streamizable object to the buffer.
template<typename T>
msgbox & operator<<(const T& t)
{
sstream_<<t;
return *this;
}
/// \brief Displays the message that buffered in the stream.
/// @return, the button that user clicked.
pick_t show() const;
/// A function object method alternative to show()
pick_t operator()() const
{
return show();
}
private:
std::stringstream sstream_;
window wd_;
nana::string title_;
button_t button_;
icon_t icon_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,67 @@
/*
* Definition of Notifier
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/notifier.hpp
*/
#ifndef NANA_GUI_NOTIFIER_HPP
#define NANA_GUI_NOTIFIER_HPP
#include <nana/gui/basis.hpp>
#include <nana/gui/detail/general_events.hpp>
namespace nana
{
class notifier;
struct arg_notifier
{
event_code evt_code;
notifier* notifier_ptr;
nana::point pos;
bool left_button;
bool mid_button;
bool right_button;
operator arg_mouse() const;
};
namespace detail
{
struct notifier_events
{
basic_event<arg_notifier> mouse_move;
basic_event<arg_notifier> mouse_down;
basic_event<arg_notifier> mouse_up;
basic_event<arg_notifier> mouse_leave;
basic_event<arg_notifier> dbl_click;
};
}
class notifier
{
struct implement;
notifier(const notifier&) = delete;
notifier(notifier&&) = delete;
notifier& operator=(const notifier&) = delete;
notifier& operator=(notifier&&) = delete;
public:
notifier(window);
~notifier();
void close();
void text(const nana::string&);
void icon(const nana::string& icon_file);
void insert_icon(const nana::string& icon_file);
void period(unsigned millisecond);
detail::notifier_events& events();
window handle() const;
private:
implement * impl_;
};
}//end namespace nana
#endif

130
include/nana/gui/place.hpp Normal file
View File

@@ -0,0 +1,130 @@
/*
* An Implementation of Place for Layout
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/place.cpp
*
* @contributions:
* min/max and splitter bar initial weight by qPCR4vir.
*/
#ifndef NANA_GUI_PLACE_HPP
#define NANA_GUI_PLACE_HPP
#include <nana/gui/basis.hpp>
#include <utility>
#include <memory>
#include <functional>
namespace nana
{
class widget;
namespace detail
{
class place_agent
{
public:
virtual ~place_agent() = default;
virtual std::unique_ptr<nana::widget> create(nana::window) const = 0;
};
}
template<typename Widget>
class agent
: public detail::place_agent
{
public:
agent(std::function<void(Widget&)> initializer)
: init_(std::move(initializer))
{}
agent(const nana::char_t* text)
: text_(text)
{}
agent(nana::string text, std::function<void(Widget&)> initializer = {})
: text_(std::move(text)), init_(std::move(initializer))
{}
private:
std::unique_ptr<nana::widget> create(nana::window handle) const override
{
std::unique_ptr<Widget> ptr(new Widget(handle));
ptr->caption(text_);
if (init_)
init_(*ptr);
return std::move(ptr);
}
private:
nana::string text_;
std::function<void(Widget&)> init_;
};
/// Layout managment - an object of class place is attached to a widget, and it automatically positions and resizes the children widgets.
class place
: ::nana::noncopyable
{
struct implement;
class field_interface
{
field_interface(const field_interface&) = delete;
field_interface& operator=(const field_interface&) = delete;
field_interface(field_interface&&) = delete;
field_interface& operator=(field_interface&&) = delete;
public:
field_interface() = default;
virtual ~field_interface() = default;
virtual field_interface& operator<<(const nana::char_t* label) = 0;
virtual field_interface& operator<<(nana::string label) = 0;
virtual field_interface& operator<<(window) = 0;
virtual field_interface& fasten(window) = 0;
template<typename Widget>
field_interface& operator<<(const agent<Widget>& ag)
{
_m_add_agent(ag);
return *this;
}
private:
virtual void _m_add_agent(const detail::place_agent&) = 0;
};
public:
/// reference to a field manipulator which refers to a field object created by place
typedef field_interface & field_reference;
place();
place(window);///< Attaches to a specified widget.
~place();
/** @brief Bind to a window
* @param handle A handle to a window which the place wants to attach.
* @remark It will throw an exception if the place has already binded to a window.
*/
void bind(window handle);
window window_handle() const;
void div(const char* s); ///< Divides the attached widget into fields.
field_reference field(const char* name);///< Returns a field with the specified name.
void field_visible(const char* filed_name, bool visible); ///<<Shows/Hides an existing field.
bool field_visible(const char* field_name) const; ///<Determines whether the specified field is visible.
void field_display(const char* field_name, bool display); ///<Displays/Discards an existing field.
bool field_display(const char* field_name) const; ///<Determines whether the specified field is displayed.
void collocate(); ///< Layouts the widgets.
void erase(window handle); ///< Erases a window from field.
field_reference operator[](const char* name); ///< Returns a field with the specified name. Equal to field();
private:
implement * impl_;
};
}//end namespace nana
#endif //#ifndef NANA_GUI_PLACE_HPP

View File

@@ -0,0 +1,260 @@
/*
* Nana GUI Programming Interface Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/programming_interface.hpp
*/
#ifndef NANA_GUI_PROGRAMMING_INTERFACE_HPP
#define NANA_GUI_PROGRAMMING_INTERFACE_HPP
#include <nana/config.hpp>
#include GUI_BEDROCK_HPP
#include "effects.hpp"
#include "detail/general_events.hpp"
#include <nana/paint/image.hpp>
#include <memory>
namespace nana
{
class drawer_trigger;
class widget;
namespace API
{
void effects_edge_nimbus(window, effects::edge_nimbus);
effects::edge_nimbus effects_edge_nimbus(window);
void effects_bground(window, const effects::bground_factory_interface&, double fade_rate);
bground_mode effects_bground_mode(window);
void effects_bground_remove(window);
//namespace dev
//@brief: The interfaces defined in namespace dev are used for developing the nana.gui
namespace dev
{
template<typename Object, typename Concept>
void attach_signal(window wd, Object& object, void (Concept::*f)(::nana::detail::signals::code, const ::nana::detail::signals&))
{
using namespace ::nana::detail;
bedrock::instance().wd_manager.attach_signal(reinterpret_cast<bedrock::core_window_t*>(wd), object, f);
}
bool set_events(window, const std::shared_ptr<general_events>&);
void attach_drawer(widget&, drawer_trigger&);
nana::string window_caption(window);
void window_caption(window, nana::string);
window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached);
window create_widget(window, const rectangle&, widget* attached);
window create_lite_widget(window, const rectangle&, widget* attached);
window create_frame(window, const rectangle&, widget* attached);
paint::graphics* window_graphics(window);
}//end namespace dev
namespace detail
{
general_events* get_general_events(window);
}//end namespace detail
void exit();
nana::string transform_shortkey_text(nana::string text, nana::string::value_type &shortkey, nana::string::size_type *skpos);
bool register_shortkey(window, unsigned long);
void unregister_shortkey(window);
nana::size screen_size();
rectangle screen_area_from_point(const point&);
nana::point cursor_position();
rectangle make_center(unsigned width, unsigned height); ///< Retrieves a rectangle which is in the center of the screen.
rectangle make_center(window, unsigned width, unsigned height); ///< Retrieves a rectangle which is in the center of the window
template<typename Widget=::nana::widget, typename EnumFunction>
void enum_widgets(window wd, bool recursive, EnumFunction && ef)
{
static_assert(std::is_convertible<Widget, ::nana::widget>::value, "enum_widgets<Widget>: The specified Widget is not a widget type.");
typedef ::nana::detail::basic_window core_window_t;
auto & brock = ::nana::detail::bedrock::instance();
internal_scope_guard lock;
auto children = brock.wd_manager.get_children(reinterpret_cast<core_window_t*>(wd));
for (auto child : children)
{
auto wgt = dynamic_cast<Widget*>(brock.wd_manager.get_widget(child));
if (nullptr == wgt)
continue;
ef(*wgt);
if (recursive)
enum_widgets<Widget>(wd, recursive, std::forward<EnumFunction>(ef));
}
}
void window_icon_default(const paint::image&);
void window_icon(window, const paint::image&);
bool empty_window(window); ///< Determines whether a window is existing.
void enable_dropfiles(window, bool);
/// \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
/// nana::native_window_type and HWND through reinterpret_cast operator. Under X System, a conversion can
/// be employed between nana::native_window_type and Window through reinterpret_cast operator.
/// \return If the function succeeds, the return value is the native window handle to the Nana.GUI window. If fails return zero.
native_window_type root(window);
window root(native_window_type); ///< Retrieves the native window of a Nana.GUI window.
void fullscreen(window, bool);
bool enabled_double_click(window, bool);
bool insert_frame(window frame, native_window_type);
native_window_type frame_container(window frame);
native_window_type frame_element(window frame, unsigned index);
void close_window(window);
void show_window(window, bool show); ///< Sets a window visible state.
void restore_window(window);
void zoom_window(window, bool ask_for_max);
bool visible(window);
window get_parent_window(window);
window get_owner_window(window);
bool set_parent_window(window, window new_parent);
template<typename Widget=::nana::widget>
typename ::nana::dev::event_mapping<Widget>::type & events(window wd)
{
typedef typename ::nana::dev::event_mapping<Widget>::type event_type;
internal_scope_guard lock;
auto * general_evt = detail::get_general_events(wd);
if (nullptr == general_evt)
throw std::invalid_argument("API::events(): bad parameter window handle, no events object or invalid window handle.");
if (std::is_same<decltype(*general_evt), event_type>::value)
return *static_cast<event_type*>(general_evt);
auto * widget_evt = dynamic_cast<event_type*>(general_evt);
if (nullptr == widget_evt)
throw std::invalid_argument("API::events(): bad template parameter Widget, the widget type and window handle do not match.");
return *widget_evt;
}
template<typename EventArg, typename std::enable_if<std::is_base_of< ::nana::detail::event_arg_interface, EventArg>::value>::type* = nullptr>
bool emit_event(event_code evt_code, window wd, const EventArg& arg)
{
auto & brock = ::nana::detail::bedrock::instance();
return brock.emit(evt_code, reinterpret_cast< ::nana::detail::bedrock::core_window_t*>(wd), arg, true, brock.get_thread_context());
}
void umake_event(event_handle);
nana::point window_position(window);
void move_window(window, int x, int y);
void move_window(window wd, const rectangle&);
void bring_to_top(window);
bool set_window_z_order(window wd, window wd_after, z_order_action action_if_no_wd_after);
nana::size window_size(window);
void window_size(window, const size&);
bool window_rectangle(window, rectangle&);
bool track_window_size(window, const size&, bool true_for_max); ///< Sets the minimum or maximum tracking size of a window.
void window_enabled(window, bool);
bool window_enabled(window);
/** @brief A widget drawer draws the widget surface in answering an event.
*
* This function will tell the drawer to copy the graphics into window after event answering.
* Tells Nana.GUI to copy the buffer of event window to screen after the event is processed.
* This function only works for a drawer_trigger, when a drawer_trigger receives an event,
* after drawing, a drawer_trigger should call lazy_refresh to tell the Nana.GUI to refresh
* the window to the screen after the event process finished.
*/
void lazy_refresh();
/** @brief: calls refresh() of a widget's drawer. if currently state is lazy_refresh, Nana.GUI may paste the drawing on the window after an event processing.
* @param window: specify a window to be refreshed.
*/
void refresh_window(window); ///< Refreshs the window and display it immediately calling the refresh method of its drawer_trigger..
void refresh_window_tree(window); ///< Refreshs the specified window and all it<69>s children windows, then display it immediately
void update_window(window); ///< Copies the off-screen buffer to the screen for immediate display.
void window_caption(window, const nana::string& title);
nana::string window_caption(window);
void window_cursor(window, cursor);
cursor window_cursor(window);
void activate_window(window);
bool is_focus_window(window);
window focus_window();
void focus_window(window);
window capture_window();
window capture_window(window, bool); ///< Enables or disables the window to grab the mouse input
void capture_ignore_children(bool ignore); ///< Enables or disables the captured window whether redirects the mouse input to its children if the mouse is over its children.
void modal_window(window); ///< Blocks the routine til the specified window is closed.
void wait_for(window);
color_t foreground(window);
color_t foreground(window, color_t);
color_t background(window);
color_t background(window, color_t);
color_t active(window);
color_t active(window, color_t);
void create_caret(window, unsigned width, unsigned height);
void destroy_caret(window);
void caret_effective_range(window, const rectangle&);
void caret_pos(window, int x, int y);
nana::point caret_pos(window);
nana::size caret_size(window);
void caret_size(window, const size&);
void caret_visible(window, bool is_show);
bool caret_visible(window);
void tabstop(window); ///< Sets the window that owns the tabstop.
/// treu: The focus is not to be changed when Tab key is pressed, and a key_char event with tab will be generated.
void eat_tabstop(window, bool);
window move_tabstop(window, bool next); ///< Sets the focus to the window which tabstop is near to the specified window.
bool glass_window(window); /// \deprecated
bool glass_window(window, bool); /// \deprecated
/// Sets the window active state. If a window active state is false, the window will not obtain the focus when a mouse clicks on it wich will be obteined by take_if_has_active_false.
void take_active(window, bool has_active, window take_if_has_active_false);
bool window_graphics(window, nana::paint::graphics&);
bool root_graphics(window, nana::paint::graphics&);
bool get_visual_rectangle(window, nana::rectangle&);
void typeface(window, const nana::paint::font&);
paint::font typeface(window);
bool calc_screen_point(window, point&); ///<Converts window coordinates to screen coordinates
bool calc_window_point(window, point&); ///<Converts screen coordinates to window coordinates.
window find_window(const nana::point& mspos);
void register_menu_window(window, bool has_keyboard);
bool attach_menubar(window menubar);
void detach_menubar(window menubar);
void restore_menubar_taken_window();
bool is_window_zoomed(window, bool ask_for_max); ///<Tests a window whether it is maximized or minimized.
void widget_borderless(window, bool); ///<Enables or disables a borderless widget.
bool widget_borderless(window); ///<Tests a widget whether it is borderless.
nana::mouse_action mouse_action(window);
nana::element_state element_state(window);
}//end namespace API
}//end namespace nana
#endif

View File

@@ -0,0 +1,28 @@
/*
* State Cursor
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/state_cursor.hpp
*/
#include <nana/gui/basis.hpp>
namespace nana
{
class state_cursor
{
state_cursor(const state_cursor&) = delete;
state_cursor& operator=(const state_cursor&) = delete;
public:
state_cursor(window, cursor);
state_cursor(state_cursor&&);
state_cursor& operator=(state_cursor&&);
~state_cursor();
private:
window handle_;
};
}

View File

@@ -0,0 +1,60 @@
/*
* A Timer Implementation
* Copyright(C) 2003-2013 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: nana/gui/timer.hpp
* @description:
* A timer can repeatedly call a piece of code. The duration between
* calls is specified in milliseconds. Timer is defferent from other graphics
* controls, it has no graphics interface.
*/
#ifndef NANA_GUI_TIMER_HPP
#define NANA_GUI_TIMER_HPP
#include <nana/gui/detail/general_events.hpp>
namespace nana
{
/// Can repeatedly call a piece of code.
struct arg_elapse
{
long long id; //timer identifier;
};
class timer
{
struct implement;
timer(const timer&) = delete;
timer& operator=(const timer&) = delete;
timer(timer&&) = delete;
timer& operator=(timer&&) = delete;
public:
timer();
~timer();
template<typename Function>
void elapse(Function && fn)
{
elapse_.connect(std::forward<Function>(fn));
}
void reset();
void start();
bool started() const;
void stop();
void interval(unsigned milliseconds); ///< Set the duration between calls (millisec ??)
unsigned interval() const;
private:
nana::basic_event<arg_elapse> elapse_;
implement * const impl_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,76 @@
/*
* A Tooltip Implementation
* Copyright(C) 2003-2013 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: nana/gui/widgets/tooltip.hpp
*/
#ifndef NANA_GUI_WIDGETS_TOOLTIP_HPP
#define NANA_GUI_WIDGETS_TOOLTIP_HPP
#include "widgets/widget.hpp"
namespace nana
{
///tooltip_interface
///An interface for user-defined tooltip window.
class tooltip_interface
{
public:
virtual ~tooltip_interface(){}
virtual bool tooltip_empty() const = 0;
virtual nana::size tooltip_size() const = 0;
virtual void tooltip_text(const nana::string&) = 0;
virtual void tooltip_move(const nana::point& screen_pos, bool ignore_pos) = 0;
virtual void duration(std::size_t) = 0;
};
class tooltip
{
class factory_interface
{
public:
virtual ~factory_interface(){}
virtual tooltip_interface* create() = 0;
virtual void destroy(tooltip_interface*) = 0;
};
template<typename TooltipWindow>
class factory
: public factory_interface
{
tooltip_interface * create() override
{
return new TooltipWindow;
}
void destroy(tooltip_interface* p) override
{
delete p;
}
};
public:
typedef factory_interface factory_if_type;
template<typename TooltipWindow>
static void make_factory()
{
_m_hold_factory(new factory<TooltipWindow>);
}
tooltip(){}
tooltip(window w, const nana::string &tip){set(w,tip);}
static void set(window, const nana::string&);
static void show(window, point pos, const nana::string&, std::size_t duration);
static void close();
private:
static void _m_hold_factory(factory_interface*);
};//class tooltip
}//namespace nana
#endif

View File

@@ -0,0 +1,113 @@
/*
* A Button Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/button.hpp
*/
#ifndef NANA_GUI_WIDGET_BUTTON_HPP
#define NANA_GUI_WIDGET_BUTTON_HPP
#include "widget.hpp"
#include <nana/gui/element.hpp>
namespace nana{
namespace drawerbase
{
namespace button
{
/// Draw the button
class trigger: public drawer_trigger
{
public:
trigger();
~trigger();
void emit_click();
void icon(const nana::paint::image&);
bool enable_pushed(bool);
bool pushed(bool);
bool pushed() const;
void omitted(bool);
bool focus_color(bool);
element::cite_bground & cite();
private:
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
void mouse_enter(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void key_char(graph_reference, const arg_keyboard&) override;
void key_press(graph_reference, const arg_keyboard&) override;
void focus(graph_reference, const arg_focus&) override;
private:
void _m_draw(graph_reference);
void _m_draw_title(graph_reference, bool enabled);
void _m_draw_background(graph_reference);
void _m_draw_border(graph_reference);
private:
widget* widget_;
paint::graphics* graph_;
element::cite_bground cite_;
struct attr_tag
{
element_state e_state;
bool omitted;
bool focused;
bool pushed;
bool keep_pressed;
bool enable_pushed;
bool focus_color;
paint::image * icon;
color_t bgcolor;
color_t fgcolor;
}attr_;
};
}//end namespace button
}//end namespace drawerbase
/// Define a button widget and provides the interfaces to be operational
class button
: public widget_object<category::widget_tag, drawerbase::button::trigger>
{
typedef widget_object<category::widget_tag, drawerbase::button::trigger> base_type;
public:
button();
button(window, bool visible);
button(window, const nana::string& caption, bool visible = true);
button(window, const nana::char_t* caption, bool visible = true);
button(window, const nana::rectangle& = rectangle(), bool visible = true);
button& icon(const nana::paint::image&);
button& enable_pushed(bool);
bool pushed() const;
button& pushed(bool);
button& omitted(bool); ///< Enables/Disables omitting displaying the caption if the text is too long.
button& enable_focus_color(bool); ///< Enables/Disables showing the caption with a special color to indicate the button is focused.
button& set_bground(const pat::cloneable<element::element_interface>&); ///< Sets a user-defined background element.
button& set_bground(const std::string&); ///< Sets a pre-defined background element by a name.
button& transparent(bool enable);
bool transparent() const;
button& edge_effects(bool enable);
private:
void _m_shortkey();
private:
//Overrides widget virtual functions
void _m_complete_creation() override;
void _m_caption(nana::string&&) override;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,247 @@
/*
* A Categorize Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/categorize.hpp
*/
#ifndef NANA_GUI_WIDGET_CATEGORIZE_HPP
#define NANA_GUI_WIDGET_CATEGORIZE_HPP
#include <nana/gui/widgets/widget.hpp>
#include <nana/pat/cloneable.hpp>
#include <nana/any.hpp>
namespace nana
{
template<typename T> class categorize;
template<typename ValueType>
struct arg_categorize
{
categorize<ValueType> & widget;
ValueType & value;
arg_categorize(categorize<ValueType> & wdg, ValueType& v)
: widget(wdg), value(v)
{}
};
namespace drawerbase
{
namespace categorize
{
template<typename T>
struct categorize_events
: public general_events
{
basic_event<arg_categorize<T>> selected;
};
class event_agent_interface
{
public:
virtual ~event_agent_interface(){}
virtual void selected(::nana::any&) = 0;
};
template<typename T>
class event_agent
: public event_agent_interface
{
public:
event_agent(::nana::categorize<T>& wdg)
: widget_(wdg)
{}
void selected(::nana::any & var)
{
auto vp = var.get<T>();
T null_val;
arg_categorize<T> arg(widget_, vp ? *vp : null_val);
widget_.events().selected.emit(arg);
}
private:
::nana::categorize<T> & widget_;
};
class renderer
{
public:
typedef nana::paint::graphics & graph_reference;
struct ui_element
{
enum t
{
none, //Out of the widget
somewhere, item_root, item_name, item_arrow
};
t what;
std::size_t index;
ui_element();
};
virtual ~renderer() = 0;
virtual void background(graph_reference, window wd, const nana::rectangle&, const ui_element&) = 0;
virtual void root_arrow(graph_reference, const nana::rectangle&, mouse_action) = 0;
virtual void item(graph_reference, const nana::rectangle&, std::size_t index, const nana::string& name, unsigned textheight, bool has_child, mouse_action) = 0;
virtual void border(graph_reference) = 0;
};
class trigger
: public drawer_trigger
{
class scheme;
public:
typedef renderer::ui_element ui_element;
trigger();
~trigger();
void insert(const nana::string&, nana::any);
bool childset(const nana::string&, nana::any);
bool childset_erase(const nana::string&);
bool clear();
//splitstr
//@brief: Sets the splitstr. If the parameter will be ingored if it is an empty string.
void splitstr(const nana::string&);
const nana::string& splitstr() const;
void path(const nana::string&);
nana::string path() const;
template<typename T>
void create_event_agent(::nana::categorize<T>& wdg)
{
event_agent_.reset(new event_agent<T>(wdg));
_m_event_agent_ready();
}
nana::any & value() const;
private:
void _m_event_agent_ready() const;
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void refresh(graph_reference) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
private:
std::unique_ptr<event_agent_interface> event_agent_;
scheme * scheme_;
};
}//end namespace categorize
}//end namespace drawerbase
/// \brief Represent an architecture of categories and what category is chosen.
/// The categorize widget can be used for representing a path of a directory or the order of a hierarchy.
template<typename T>
class categorize
: public widget_object<category::widget_tag, drawerbase::categorize::trigger, drawerbase::categorize::categorize_events<T>>
{
public:
typedef T value_type; ///< The type of objects stored
typedef drawerbase::categorize::renderer renderer; ///< The interface for user-defined renderer.
categorize()
{
this->get_drawer_trigger().create_event_agent(*this);
}
categorize(window wd, const rectangle& r = rectangle(), bool visible = true)
{
this->get_drawer_trigger().template create_event_agent(*this);
this->create(wd, r, visible);
}
categorize(window wd, bool visible)
: categorize(wd, ::nana::rectangle(), visible)
{
}
categorize(window wd, const nana::string& text, bool visible = true)
: categorize(wd, ::nana::rectangle(), visible)
{
this->caption(text);
}
categorize(window wd, const nana::char_t* text, bool visible = true)
: categorize(wd, ::nana::rectangle(), visible)
{
this->caption(text);
}
/// Insert a new category with a specified name and the object of value type.
/// The new category would be inserted as a child in current category,
/// and after inserting, the new category is replaced of the current category as a new current one.
categorize& insert(const nana::string& name, const value_type& value)
{
this->get_drawer_trigger().insert(name, value);
API::update_window(*this);
return *this;
}
/// Inserts a child category into current category.
categorize& childset(const nana::string& name, const value_type& value)
{
if(this->get_drawer_trigger().childset(name, value))
API::update_window(*this);
return *this;
}
/// Erases a child category with a specified name from current category.
categorize& childset_erase(const nana::string& name)
{
if(this->get_drawer_trigger().childset_erase(name))
API::update_window(*this);
return *this;
}
void clear()
{
if(this->get_drawer_trigger().clear())
API::update_window(*this);
}
/// Sets the splitter string
categorize& splitstr(const nana::string& sstr)
{
this->get_drawer_trigger().splitstr(sstr);
return *this;
}
nana::string splitstr() const
{
return this->get_drawer_trigger().splitstr();
}
/// Retrieves a reference of the current category's value type object. If current category is empty, it throws a exception of std::runtime_error.
value_type& value() const
{
return this->get_drawer_trigger().value();
}
private:
//Overrides widget's virtual functions
void _m_caption(nana::string&& str) override
{
this->get_drawer_trigger().path(str);
API::dev::window_caption(*this, this->get_drawer_trigger().path());
}
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,100 @@
/*
* A CheckBox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/checkbox.hpp
*/
#ifndef NANA_GUI_WIDGET_CHECKBOX_HPP
#define NANA_GUI_WIDGET_CHECKBOX_HPP
#include "widget.hpp"
#include <vector>
#include <memory>
namespace nana {
namespace drawerbase
{
namespace checkbox
{
class drawer
: public drawer_trigger
{
struct implement;
public:
drawer();
~drawer(); //To instance imptr_;
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
void mouse_enter(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
public:
implement * impl() const;
private:
void _m_draw(graph_reference);
void _m_draw_background(graph_reference);
void _m_draw_checkbox(graph_reference, unsigned first_line_height);
void _m_draw_title(graph_reference);
private:
static const int interval = 4;
widget* widget_;
unsigned state_;
std::unique_ptr<implement> imptr_;
implement * impl_;
};
}//end namespace checkbox
}//end namespace drawerbase
class checkbox
: public widget_object<category::widget_tag, drawerbase::checkbox::drawer>
{
public:
checkbox();
checkbox(window, bool visible);
checkbox(window, const nana::string& text, bool visible = true);
checkbox(window, const nana::char_t* text, bool visible = true);
checkbox(window, const rectangle& = rectangle(), bool visible = true);
void element_set(const char* name);
void react(bool want); ///< Enables the reverse check while clicking on the checkbox.
bool checked() const;
void check(bool chk);
/// \brief With the radio mode, users make a choice among a set of mutually exclusive,
/// related options. Users can choose one and only one option.
/// There is a helper class manages checkboxs for radio mode,
/// \see radio_group.
void radio(bool);
void transparent(bool value);
bool transparent() const;
};//end class checkbox
/// for managing checkboxs in radio mode
class radio_group
{
struct element_tag
{
checkbox * uiobj;
event_handle eh_checked;
event_handle eh_destroy;
};
public:
~radio_group();
void add(checkbox&);
std::size_t checked() const; ///< Retrieves the index of the checkbox which is checked.
std::size_t size() const;
private:
void _m_checked(const arg_mouse&);
void _m_destroy(const arg_destroy&);
private:
std::vector<element_tag> ui_container_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,233 @@
/*
* A Combox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/combox.hpp
*/
#ifndef NANA_GUI_WIDGETS_COMBOX_HPP
#define NANA_GUI_WIDGETS_COMBOX_HPP
#include "widget.hpp"
#include "float_listbox.hpp"
#include <nana/key_type.hpp>
#include <nana/concepts.hpp>
#include <functional>
namespace nana
{
/// A list box combined with a textbox - the list box should drop down when the user selects the arrow next to the control
class combox;
struct arg_combox
{
combox & widget;
arg_combox(combox& wdg)
: widget(wdg)
{}
};
namespace drawerbase
{
namespace combox
{
struct combox_events
: public general_events
{
basic_event<arg_combox> selected;
};
class drawer_impl;
class trigger
: public drawer_trigger
{
public:
trigger();
~trigger();
void set_accept(std::function<bool(nana::char_t)>&&);
drawer_impl& get_drawer_impl();
const drawer_impl& get_drawer_impl() const;
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void refresh(graph_reference) override;
void focus(graph_reference, const arg_focus&) override;
void mouse_enter(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_wheel(graph_reference, const arg_wheel&) override;
void key_press(graph_reference, const arg_keyboard&) override;
void key_char(graph_reference, const arg_keyboard&) override;
private:
std::function<bool(nana::char_t)> pred_acceptive_;
drawer_impl * drawer_;
};
class item_proxy
: public std::iterator<std::input_iterator_tag, item_proxy>
{
public:
item_proxy(drawer_impl*, std::size_t pos);
item_proxy& text(const nana::string&);
nana::string text() const;
item_proxy& select();
bool selected() const;
item_proxy& icon(const nana::paint::image&);
nana::paint::image icon() const;
template<typename T>
T * value_ptr() const
{
auto p = _m_anyobj(false);
return (p ? p->get<T>() : nullptr);
}
template<typename T>
T & value() const
{
auto * pany = _m_anyobj(false);
if (nullptr == pany)
throw std::runtime_error("combox::item_proxy.value<T>() is empty");
T * p = pany->get<T>();
if (nullptr == p)
throw std::runtime_error("combox::item_proxy.value<T>() invalid type of value");
return *p;
}
template<typename T>
item_proxy& value(const T& t)
{
*_m_anyobj(true) = t;
return *this;
}
template<typename T>
item_proxy& value(T&& t)
{
*_m_anyobj(true) = std::move(t);
return *this;
}
public:
/// Behavior of Iterator's value_type
bool operator==(const nana::string&) const;
bool operator==(const char*) const;
bool operator==(const wchar_t*) const;
/// Behavior of Iterator
item_proxy & operator=(const item_proxy&);
/// Behavior of Iterator
item_proxy & operator++();
/// Behavior of Iterator
item_proxy operator++(int);
/// Behavior of Iterator
item_proxy& operator*();
/// Behavior of Iterator
const item_proxy& operator*() const;
/// Behavior of Iterator
item_proxy* operator->();
/// Behavior of Iterator
const item_proxy* operator->() const;
/// Behavior of Iterator
bool operator==(const item_proxy&) const;
/// Behavior of Iterator
bool operator!=(const item_proxy&) const;
private:
nana::any * _m_anyobj(bool alloc_if_empty) const;
private:
drawer_impl * impl_;
std::size_t pos_;
};
}//end namespace combox
}//end namespace drawerbase
class combox
: public widget_object<category::widget_tag, drawerbase::combox::trigger, drawerbase::combox::combox_events>,
public nana::concepts::any_objective<std::size_t, 1>
{
public:
typedef float_listbox::item_renderer item_renderer;
typedef drawerbase::combox::item_proxy item_proxy;
combox();
combox(window, bool visible);
combox(window, const nana::string& text, bool visible = true);
combox(window, const nana::char_t* text, bool visible = true);
combox(window, const rectangle& r = rectangle(), bool visible = true);
void clear();
void editable(bool);
bool editable() const;
void set_accept(std::function<bool(nana::char_t)>);
combox& push_back(const nana::string&);
std::size_t the_number_of_options() const;
std::size_t option() const; ///< Index of the last selected, from drop-down list, item.
void option(std::size_t); ///< Select the text specified by index
nana::string text(std::size_t) const;
void erase(std::size_t pos);
template<typename Key>
item_proxy operator[](const Key& kv)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
std::shared_ptr<nana::detail::key_interface> p(new nana::key<key_t, std::less<key_t> >(kv), [](nana::detail::key_interface*p)
{
delete p;
});
return _m_at_key(std::move(p));
}
template<typename Key>
void erase_key(const Key& kv)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
std::unique_ptr<nana::detail::key_interface> p(new nana::key<key_t, std::less<key_t> >(kv));
_m_erase(p.get());
}
template<typename Key>
void erase_key(Key&& kv)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
std::unique_ptr<nana::detail::key_interface> p(new nana::key<key_t, std::less<key_t> >(std::move(kv)));
_m_erase(p.get());
}
/// \brief Set user-defined item renderer object.
/// It is an address therefore the user should not destroy the renderer object
/// after it is set to the combox. Passing null_ptr cancels the user-defined renderer object.
void renderer(item_renderer*);
void image(std::size_t, const nana::paint::image&);
nana::paint::image image(std::size_t) const;
void image_pixels(unsigned); ///<Sets the width of image area. Default is 16 pixels.
private:
item_proxy _m_at_key(std::shared_ptr<nana::detail::key_interface>&&);
void _m_erase(nana::detail::key_interface*);
private:
//Overrides widget's virtual functions
nana::string _m_caption() const override;
void _m_caption(nana::string&&) override;
nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override;
};
}
#endif

View File

@@ -0,0 +1,123 @@
/*
* A date chooser Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/date_chooser.hpp
*/
#ifndef NANA_GUI_WIDGETS_DATE_CHOOSER_HPP
#define NANA_GUI_WIDGETS_DATE_CHOOSER_HPP
#include "widget.hpp"
#include <nana/datetime.hpp>
namespace nana
{
namespace drawerbase
{
namespace date_chooser
{
class trigger : public drawer_trigger
{
public:
static const int topbar_height = 34;
static const int border_size = 3;
enum class transform_action{none, to_left, to_right, to_enter, to_leave};
enum class where{none, left_button, right_button, topbar, textarea};
enum class page{date, month};
struct drawing_basis
{
nana::point refpos;
double line_s;
double row_s;
};
trigger();
bool chose() const;
nana::date read() const;
void week_name(unsigned index, const nana::string&);
void month_name(unsigned index, const nana::string&);
private:
void _m_init_color();
where _m_pos_where(graph_reference, int x, int y);
void _m_draw(graph_reference);
void _m_draw_topbar(graph_reference);
void _m_make_drawing_basis(drawing_basis&, graph_reference, const nana::point& refpos);
void _m_draw_pos(drawing_basis &, graph_reference, int x, int y, const nana::string&, bool primary, bool sel);
void _m_draw_pos(drawing_basis &, graph_reference, int x, int y, int number, bool primary, bool sel);
void _m_draw_ex_days(drawing_basis &, graph_reference, int begx, int begy, bool before);
void _m_draw_days(const nana::point& refpos, graph_reference);
void _m_draw_months(const nana::point& refpos, graph_reference);
bool _m_get_trace(point, int & res);
void _m_perf_transform(transform_action tfid, graph_reference, graph_reference dirtybuf, graph_reference newbuf, const nana::point& refpos);
private:
void refresh(graph_reference);
void attached(widget_reference, graph_reference) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
private:
nana::string weekstr_[7];
nana::string monthstr_[12];
widget * widget_;
bool chose_;
page page_;
where pos_;
nana::point trace_pos_;
drawing_basis dbasis_;
struct
{
int year;
int month;
int day;
}chdate_;
struct
{
int year;
int month;
}chmonth_;
struct color_tag
{
nana::color_t highlight;
nana::color_t selected;
nana::color_t normal;
nana::color_t bkcolor;
}color_;
};
}//end namespace date_chooser
}//end namespace drawerbase
/// \see nana::date
class date_chooser
: public widget_object<category::widget_tag, drawerbase::date_chooser::trigger>
{
public:
date_chooser();
date_chooser(window, bool visible);
date_chooser(window, const nana::string& text, bool visible = true);
date_chooser(window, const nana::char_t* text, bool visible = true);
date_chooser(window, const nana::rectangle& r = rectangle(), bool visible = true);
bool chose() const;
nana::date read() const;
void weekstr(unsigned index, const nana::string&);///<Set the week strings which will be displayed for day, index is in range of [0, 6]
void monthstr(unsigned index, const nana::string&);///<Set the month strings which will be displayed for month. index is in range of [0, 11]
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,84 @@
/*
* Concept of Component Set
* Copyright(C) 2003-2013 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: nana/gui/widgets/detail/compset.hpp
*/
#ifndef NANA_GUI_WIDGETS_DETAIL_COMPSET_HPP
#define NANA_GUI_WIDGETS_DETAIL_COMPSET_HPP
#include <nana/basic_types.hpp>
namespace nana{ namespace widgets{ namespace detail
{
/// A component set used for accessing the components of items of a widget.
template<typename Component, typename ItemAttribute>
class compset
{
public:
/// A type of widget-defined components.
typedef Component component_t;
/// A type of widget-defined item attribute.
typedef ItemAttribute item_attribute_t;
/// A type of a componenet state for rendering.
struct comp_attribute_t
{
nana::rectangle area;
bool mouse_pointed;
};
public:
/// The destrcutor
virtual ~compset(){}
/// Access the widget-defined item attribute.
virtual const item_attribute_t& item_attribute() const = 0;
/// Access a specified component of the item.
virtual bool comp_attribute(component_t, comp_attribute_t &) const = 0;
};
/// A component set placer used for specifying component position and size.
template<typename Component, typename ItemAttribute>
class compset_placer
{
public:
typedef ::nana::paint::graphics & graph_reference;
/// A type of widget-defined components.
typedef Component component_t;
/// A type of widget-defined item attribute.
typedef ItemAttribute item_attribute_t;
public:
/// The destrcutor.
virtual ~compset_placer(){}
/// Enable/Disable the specified component.
virtual void enable(component_t, bool) = 0;
virtual bool enabled(component_t) const = 0;
/// Height of an item, in pixels.
// this method is content-indepented, this feature is easy for implementation.
virtual unsigned item_height(graph_reference) const = 0;
/// Width of an item, in pixels
virtual unsigned item_width(graph_reference, const item_attribute_t&) const = 0;
/// Locate a component through the specified coordinate.
/// @param comp the component of the item.
/// @param attr the attribute of the item.
/// @param r the pointer refers to a rectangle for receiving the position and size of the component.
/// @returns the true when the component is located by the locator.
virtual bool locate(component_t comp, const item_attribute_t& attr, rectangle * r) const = 0;
};
}//end namespace detail
}//end namespace widgets
}//end namespace nana
#endif

View File

@@ -0,0 +1,518 @@
/*
* A Tree Container class implementation
* Copyright(C) 2003-2013 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: nana/gui/widgets/detail/tree_cont.hpp
*/
#ifndef NANA_GUI_WIDGETS_DETAIL_TREE_CONT_HPP
#define NANA_GUI_WIDGETS_DETAIL_TREE_CONT_HPP
#include <stack>
namespace nana
{
namespace widgets
{
namespace detail
{
template<typename T>
struct tree_node
{
typedef std::pair<nana::string, T> value_type;
value_type value;
tree_node *owner;
tree_node *next;
tree_node *child;
tree_node(tree_node* owner)
:owner(owner), next(nullptr), child(nullptr)
{}
~tree_node()
{
if(owner)
{
tree_node * t = owner->child;
if(t != this)
{
while(t->next != this)
t = t->next;
t->next = next;
}
else
owner->child = next;
}
tree_node * t = child;
while(t)
{
tree_node * t_next = t->next;
delete t;
t = t_next;
}
}
};
template<typename UserData>
class tree_cont
{
typedef tree_cont self_type;
public:
typedef UserData element_type;
typedef tree_node<element_type> node_type;
typedef typename node_type::value_type value_type;
tree_cont()
:root_(nullptr)
{}
~tree_cont()
{
clear();
}
void clear()
{
remove(root_.child);
}
bool verify(const node_type* node) const
{
if(node)
{
while(node->owner)
{
if(node->owner == &root_)
return true;
node = node->owner;
}
}
return false;
}
node_type* get_root() const
{
return &root_;
}
node_type* get_owner(const node_type* node) const
{
return (verify(node) && (node->owner != &root_) ? node->owner : nullptr);
}
node_type * node(node_type* node, const nana::string& key)
{
if(node)
{
for(node_type * child = node->child; child; child = child->next)
{
if(child->value.first == key)
return child;
}
}
return nullptr;
}
node_type* insert(node_type* node, const nana::string& key, const element_type& elem)
{
if(nullptr == node)
return insert(key, elem);
if(verify(node))
{
node_type **new_node_ptr;
if(node->child)
{
node_type* child = node->child;
for(; child; child = child->next)
{
if(child->value.first == key)
{
child->value.second = elem;
return child;
}
}
child = node->child;
while(child->next)
child = child->next;
new_node_ptr = &(child->next);
}
else
new_node_ptr = &(node->child);
*new_node_ptr = new node_type(node);
(*new_node_ptr)->value.first = key;
(*new_node_ptr)->value.second = elem;
return (*new_node_ptr);
}
return nullptr;
}
node_type* insert(const nana::string& key, const element_type& elem)
{
auto node = _m_locate<true>(key);
if(node)
node->value.second = elem;
return node;
}
void remove(node_type* node)
{
if(verify(node))
delete node;
}
node_type* find(const nana::string& path) const
{
return _m_locate(path);
}
node_type* ref(const nana::string& path)
{
return _m_locate<true>(path);
}
unsigned indent_size(const node_type* node) const
{
if(node)
{
unsigned indent = 0;
for(;(node = node->owner); ++indent)
{
if(node == &root_) return indent;
}
}
return 0;
}
template<typename Functor>
void for_each(node_type* node, Functor f)
{
if(nullptr == node) node = root_.child;
int state = 0; //0: Sibling, the last is a sibling of node
//1: Owner, the last is the owner of node
//>= 2: Children, the last is is a child of the node that before this node.
while(node)
{
switch(f(*node, state))
{
case 0: return;
case 1:
{
if(node->child)
{
node = node->child;
state = 1;
}
else
return;
continue;
}
break;
}
if(node->next)
{
node = node->next;
state = 0;
}
else
{
state = 1;
if(node == &root_) return;
while(true)
{
++state;
if(node->owner->next)
{
node = node->owner->next;
break;
}
else
node = node->owner;
if(node == &root_) return;
}
}
}
}
template<typename Functor>
void for_each(node_type* node, Functor f) const
{
if(nullptr == node) node = root_.child;
int state = 0; //0: Sibling, the last is a sibling of node
//1: Owner, the last is the owner of node
//>= 2: Children, the last is is a child of the node that before this node.
while(node)
{
switch(f(*node, state))
{
case 0: return;
case 1:
{
if(node->child)
{
node = node->child;
state = 1;
}
else
return;
continue;
}
break;
}
if(node->next)
{
node = node->next;
state = 0;
}
else
{
state = 1;
if(node == &root_) return;
while(true)
{
++state;
if(node->owner->next)
{
node = node->owner->next;
break;
}
else
node = node->owner;
if(node == &root_) return;
}
}
}
}
template<typename PredAllowChild>
unsigned child_size_if(const nana::string& key, PredAllowChild pac) const
{
auto node = _m_locate(key);
return (node ? child_size_if<PredAllowChild>(*node, pac) : 0);
}
template<typename PredAllowChild>
unsigned child_size_if(const node_type& node, PredAllowChild pac) const
{
unsigned size = 0;
const node_type* pnode = node.child;
while(pnode)
{
++size;
if(pnode->child && pac(*pnode))
size += child_size_if<PredAllowChild>(*pnode, pac);
pnode = pnode->next;
}
return size;
}
template<typename PredAllowChild>
unsigned distance_if(const node_type * node, PredAllowChild pac) const
{
if(nullptr == node) return 0;
const node_type * iterator = root_.child;
unsigned off = 0;
std::stack<const node_type* > stack;
while(iterator && iterator != node)
{
++off;
if(iterator->child && pac(*iterator))
{
stack.push(iterator);
iterator = iterator->child;
}
else
iterator = iterator->next;
while((nullptr == iterator) && stack.size())
{
iterator = stack.top()->next;
stack.pop();
}
}
return off;
}
template<typename PredAllowChild>
node_type* advance_if(node_type* node, std::size_t off, PredAllowChild pac)
{
if(nullptr == node) node = root_.child;
std::stack<node_type* > stack;
while(node && off)
{
--off;
if(node->child && pac(*node))
{
stack.push(node);
node = node->child;
}
else
node = node->next;
while(nullptr == node && stack.size())
{
node = stack.top();
stack.pop();
node = node->next;
}
}
return node;
}
private:
//Functor defintions
struct each_make_node
{
each_make_node(self_type& self)
:node(&(self.root_))
{}
bool operator()(const nana::string& key_node)
{
node_type *child = node->child;
node_type *tail = nullptr;
while(child)
{
if(key_node == child->value.first)
{
node = child;
return true;
}
tail = child;
child = child->next;
}
child = new node_type(node);
if(tail)
tail->next = child;
else
node->child = child;
child->value.first = key_node;
node = child;
return true;
}
node_type * node;
};
struct find_key_node
{
find_key_node(const self_type& self)
:node(&self.root_)
{}
bool operator()(const nana::string& key_node)
{
return ((node = _m_find(node->child, key_node)) != nullptr);
}
node_type *node;
};
private:
static node_type* _m_find(node_type* node, const nana::string& key_node)
{
while(node)
{
if(key_node == node->value.first)
return node;
node = node->next;
}
return nullptr;
}
template<typename Function>
void _m_for_each(const nana::string& key, Function function) const
{
if(key.size())
{
nana::string::size_type beg = 0;
auto end = key.find_first_of(STR("\\/"));
while(end != nana::string::npos)
{
if(beg != end)
{
if(function(key.substr(beg, end - beg)) == false)
return;
}
auto next = key.find_first_not_of(STR("\\/"), end);
if(next != nana::string::npos)
{
beg = next;
end = key.find_first_of(STR("\\/"), beg);
}
else
return;
}
function(key.substr(beg, key.size() - beg));
}
}
template<bool CreateIfNotExists>
node_type* _m_locate(const nana::string& key)
{
if(key.size())
{
if(CreateIfNotExists)
{
each_make_node emn(*this);
_m_for_each<each_make_node&>(key, emn);
return emn.node;
}
else
{
find_key_node fkn(*this);
_m_for_each<find_key_node&>(key, fkn);
return const_cast<node_type*>(fkn.node);
}
}
return &root_;
}
node_type* _m_locate(const nana::string& key) const
{
if(key.size())
{
find_key_node fkn(*this);
_m_for_each<find_key_node&>(key, fkn);
return fkn.node;
}
return &root_;
}
private:
mutable node_type root_;
};//end class tree_cont
}//end namespace detail
}//end namespace widgets
}//end namesace nana
#endif

View File

@@ -0,0 +1,107 @@
/*
* A float_listbox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/float_listbox.hpp
*/
#ifndef NANA_GUI_WIDGETS_FLOAT_LISTBOX_HPP
#define NANA_GUI_WIDGETS_FLOAT_LISTBOX_HPP
#include "widget.hpp"
#include <vector>
#include <memory>
namespace nana
{
namespace drawerbase{
namespace float_listbox
{
class item_interface
{
public:
virtual ~item_interface(){}
virtual const nana::paint::image & image() const = 0;
virtual const nana::char_t* text() const = 0;
};
//struct module_def
//@brief: This defines a data structure used for float_listbox
struct module_def
{
std::vector<std::shared_ptr<item_interface>> items;
std::size_t max_items; // the number of items display.
mutable std::size_t index; // the result of the selection.
mutable bool have_selected;
module_def();
};
class item_renderer
{
public:
typedef widget& widget_reference;
typedef paint::graphics& graph_reference;
enum state_t{StateNone, StateHighlighted};
virtual ~item_renderer() = 0;
virtual void image(bool enabled, unsigned pixels) = 0;
virtual void render(widget_reference, graph_reference, const nana::rectangle&, const item_interface*, state_t) = 0;
virtual unsigned item_pixels(graph_reference) const = 0;
};
class drawer_impl;
class trigger
: public drawer_trigger
{
public:
trigger();
~trigger();
drawer_impl& get_drawer_impl();
const drawer_impl& get_drawer_impl() const;
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void refresh(graph_reference) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
private:
class drawer_impl *drawer_;
};
}
}//end namespace drawerbase
class float_listbox
: public widget_object<category::root_tag, drawerbase::float_listbox::trigger>
{
typedef widget_object<category::root_tag, drawerbase::float_listbox::trigger> base_type;
public:
typedef drawerbase::float_listbox::item_renderer item_renderer;
typedef drawerbase::float_listbox::module_def module_type;
typedef drawerbase::float_listbox::item_interface item_interface;
/** @brief Constructor
* @param window A handle to a window which is a owner of float_listbox
* @param rectangle A position and a size of float_listbox
* @param is_ignore_first_mouse_up The flost_listbox will be closed when a mouse_up is emitted, this parameter is specified for ignoring the first mouse_up emitting.
* @remark The float_listbox can be popupped in a mouse_down event, the next mouse_up may be ignored, otherwise the float_listbox will be closed when user releases the button.
*/
float_listbox(window, const rectangle&, bool is_ignore_first_mouse_up);
void set_module(const module_type&, unsigned image_pixels);
void scroll_items(bool upwards);
void move_items(bool upwards, bool circle);
void renderer(item_renderer*);
std::size_t index() const;
};
}
#endif

View File

@@ -0,0 +1,64 @@
/*
* A Form Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/form.hpp
*/
#ifndef NANA_GUI_WIDGET_FORM_HPP
#define NANA_GUI_WIDGET_FORM_HPP
#include "widget.hpp"
namespace nana
{
namespace drawerbase
{
namespace form
{
class trigger: public drawer_trigger
{
public:
trigger();
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
void resized(graph_reference, const arg_resized&) override;
private:
widget* wd_;
};
}//end namespace form
}//end namespace drawerbase
/// \brief Pop-up window. Is different from other window widgets: its default constructor create the window.
/// \see nana::appearance
class form: public widget_object<category::root_tag, drawerbase::form::trigger, detail::events_root_extension>
{
public:
typedef ::nana::appear appear;
/// Creates a window at the point and size specified by rect, and with the specified appearance. Creates a form owned by the desktop.
form(const rectangle& = API::make_center(300, 200), const appearance& = {}); //Default constructor
form(const form&, const ::nana::size& = { 300, 200 }, const appearance& = {}); //Copy constructor
form(window, const ::nana::size& = { 300, 200 }, const appearance& = {});
/// Creates a window at the point and size specified by rect, with the specified appearance. This window is always floating above its owner.
form(window, const rectangle&, const appearance& = {});
};
class nested_form : public widget_object<category::root_tag, drawerbase::form::trigger, detail::events_root_extension>
{
public:
typedef ::nana::appear appear;
nested_form(const form&, const rectangle& = {}, const appearance& = {});
nested_form(const nested_form&, const rectangle& = {}, const appearance& = {});
nested_form(window, const appearance&);
nested_form(window, const rectangle& = {}, const appearance& = {});
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,53 @@
/*
* A Frame Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/frame.hpp
*
* A frame provides a way to contain the platform window in a stdex GUI Window
*/
#ifndef NANA_GUI_WIDGET_FRAME_HPP
#define NANA_GUI_WIDGET_FRAME_HPP
#include "widget.hpp"
namespace nana
{
/**
\brief Container for system native windows. Provides an approach to
display a control that is not written with Nana.GUI in a Nana.GUI window.
Notes:
1. nana::native_window_type is a type of system handle of windows.
2. all the children windows of a nana::frame is topmost to Nana.GUI windows.
3. a simple example. Displaying a Windows Edit Control.
nana::frame frame(parent, 0, 0 200, 100);
HWND frame_handle = reinterpret_cast<HWND>(frame.container());
HWND edit = ::CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"Test",
WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 200, 100,
frame_handle, 0, ::GetModuleHandle(0), 0);
if(edit)
frame.insert(edit);
*/
class frame: public widget_object<category::frame_tag, int, nana::general_events>
{
typedef widget_object<category::frame_tag, int> base_type;
public:
frame();
frame(window, bool visible);
frame(window, const rectangle& = rectangle(), bool visible = true);
bool insert(native_window_type); ///< Inserts a platform native window.
native_window_type element(unsigned index); ///< Returns the child window through index.
native_window_type container() const; ///< Returns the frame container native window handle.
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,78 @@
/*
* A Label Control Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/label.hpp
*/
#ifndef NANA_GUI_WIDGET_LABEL_HPP
#define NANA_GUI_WIDGET_LABEL_HPP
#include "widget.hpp"
namespace nana
{
namespace drawerbase
{
namespace label
{
enum class command /// Defines the event type for format listener.
{
enter, leave, click
};
/// draw the label
class trigger: public drawer_trigger
{
public:
struct impl_t;
trigger();
~trigger();
impl_t * impl() const;
private:
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void click(graph_reference, const arg_mouse&) override;
private:
impl_t * impl_;
};
}//end namespace label
}//end namespace drawerbase
class label
: public widget_object<category::widget_tag, drawerbase::label::trigger>
{
label(const label&) = delete;
label(label&&) = delete;
public:
typedef drawerbase::label::command command;
label();
label(window, bool visible);
label(window, const nana::string& text, bool visible = true);
label(window, const nana::char_t* text, bool visible = true);
label(window, const rectangle& = {}, bool visible = true);
label& transparent(bool); ///< Switchs the label widget to the transparent background mode.
bool transparent() const;
label& format(bool); ///< Switches the format mode of the widget.
label& add_format_listener(std::function<void(command, const nana::string&)>);
/// \briefReturn the size of the text. If *allowed_width_in_pixel* is not zero, returns a
/// "corrected" size that changes lines to fit the text into the specified width
nana::size measure(unsigned allowed_width_in_pixel) const;
label& text_align(align horizontal_align, align_v vertical_align= align_v::top);
private:
//Overrides widget's virtual function
void _m_caption(nana::string&&) override;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,550 @@
/*
* A List Box Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/listbox.hpp
*
*/
#ifndef NANA_GUI_WIDGETS_LISTBOX_HPP
#define NANA_GUI_WIDGETS_LISTBOX_HPP
#include "widget.hpp"
#include <nana/concepts.hpp>
#include <nana/key_type.hpp>
#include <functional>
#include <initializer_list>
namespace nana
{
class listbox;
namespace drawerbase
{
namespace listbox
{
typedef std::size_t size_type;
struct cell
{
struct format
{
::nana::color_t bgcolor;
::nana::color_t fgcolor;
format(color_t bgcolor = 0xFF000000, color_t fgcolor = 0xFF000000);
};
using format_ptr = std::unique_ptr < format > ;
::nana::string text;
format_ptr custom_format;
cell() = default;
cell(const cell&);
cell(cell&&);
cell(nana::string);
cell(nana::string, const format&);
cell(nana::string, color_t bgcolor, color_t fgcolor);
cell& operator=(const cell&);
cell& operator=(cell&&);
};
class oresolver
{
public:
oresolver& operator<<(bool);
oresolver& operator<<(short);
oresolver& operator<<(unsigned short);
oresolver& operator<<(int);
oresolver& operator<<(unsigned int);
oresolver& operator<<(long);
oresolver& operator<<(unsigned long);
oresolver& operator<<(long long);
oresolver& operator<<(unsigned long long);
oresolver& operator<<(float);
oresolver& operator<<(double);
oresolver& operator<<(long double);
oresolver& operator<<(const char*);
oresolver& operator<<(const wchar_t*);
oresolver& operator<<(const std::string&);
oresolver& operator<<(const std::wstring&);
oresolver& operator<<(std::wstring&&);
oresolver& operator<<(cell);
oresolver& operator<<(std::nullptr_t);
std::vector<cell> && move_cells();
private:
std::vector<cell> cells_;
};
class iresolver
{
public:
iresolver(const std::vector<cell>&);
iresolver& operator>>(bool&);
iresolver& operator>>(short&);
iresolver& operator>>(unsigned short&);
iresolver& operator>>(int&);
iresolver& operator>>(unsigned int&);
iresolver& operator>>(long&);
iresolver& operator>>(unsigned long&);
iresolver& operator>>(long long&);
iresolver& operator>>(unsigned long long&);
iresolver& operator>>(float&);
iresolver& operator>>(double&);
iresolver& operator>>(long double&);
iresolver& operator>>(std::string&);
iresolver& operator>>(std::wstring&);
iresolver& operator>>(cell&);
iresolver& operator>>(std::nullptr_t);
private:
const std::vector<cell>& cells_;
std::size_t pos_{0};
};
struct index_pair
{
size_type cat; //The pos of category
size_type item; //the pos of item in a category.
index_pair(size_type cat_pos = 0, size_type item_pos = 0)
: cat(cat_pos),
item(item_pos)
{}
bool empty() const
{
return (npos == cat);
}
void set_both(size_type n)
{
cat = item = n;
}
bool is_category() const
{
return (npos != cat && npos == item);
}
bool is_item() const
{
return (npos != cat && npos != item);
}
bool operator==(const index_pair& r) const
{
return (r.cat == cat && r.item == item);
}
bool operator!=(const index_pair& r) const
{
return !this->operator==(r);
}
bool operator>(const index_pair& r) const
{
return (cat > r.cat) || (cat == r.cat && item > r.item);
}
};
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;
class drawer_header_impl;
class drawer_lister_impl;
class trigger: public drawer_trigger
{
public:
trigger();
~trigger();
essence_t& essence();
essence_t& essence() const;
void draw();
private:
void _m_draw_border();
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void typeface_changed(graph_reference) override;
void refresh(graph_reference) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_wheel(graph_reference, const arg_wheel&) override;
void dbl_click(graph_reference, const arg_mouse&) override;
void resized(graph_reference, const arg_resized&) override;
void key_press(graph_reference, const arg_keyboard&) override;
private:
essence_t * essence_;
drawer_header_impl *drawer_header_;
drawer_lister_impl *drawer_lister_;
};//end class trigger
class item_proxy
: public std::iterator<std::input_iterator_tag, item_proxy>
{
public:
item_proxy(essence_t*);
item_proxy(essence_t*, const index_pair&);
bool empty() const;
item_proxy & check(bool ck);
bool checked() const;
item_proxy & select(bool);
bool selected() const;
item_proxy & bgcolor(nana::color_t);
nana::color_t bgcolor() const;
item_proxy& fgcolor(nana::color_t);
nana::color_t fgcolor() const;
index_pair pos() const;
size_type columns() const;
item_proxy& text(size_type col, cell);
item_proxy& text(size_type col, nana::string);
nana::string text(size_type col) const;
void icon(const nana::paint::image&);
template<typename T>
item_proxy & resolve_from(const T& t)
{
oresolver ores;
ores << t;
auto && cells = ores.move_cells();
auto cols = columns();
cells.resize(cols);
for (auto pos = 0; pos < cols; ++pos)
{
auto & el = cells[pos];
if (el.text.size() == 1 && el.text[0] == nana::char_t(0))
continue;
text(pos, std::move(el));
}
return *this;
}
template<typename T>
void resolve_to(T& t) const
{
iresolver ires(_m_cells());
ires >> t;
}
template<typename T>
T* value_ptr() const
{
auto * pany = _m_value();
return (pany ? pany->get<T>() : nullptr);
}
template<typename T>
T & value() const
{
auto * pany = _m_value();
if(nullptr == pany)
throw std::runtime_error("listbox::item_proxy.value<T>() is empty");
T * p = pany->get<T>();
if(nullptr == p)
throw std::runtime_error("listbox::item_proxy.value<T>() invalid type of value");
return *p;
}
template<typename T>
item_proxy & value(T&& t)
{
*_m_value(true) = std::forward<T>(t);
return *this;
}
/// Behavior of Iterator's value_type
bool operator==(const nana::string& s) const;
bool operator==(const char * s) const;
bool operator==(const wchar_t * s) const;
/// Behavior of Iterator
item_proxy & operator=(const item_proxy&);
/// Behavior of Iterator
item_proxy & operator++();
/// Behavior of Iterator
item_proxy operator++(int);
/// Behavior of Iterator
item_proxy& operator*();
/// Behavior of Iterator
const item_proxy& operator*() const;
/// Behavior of Iterator
item_proxy* operator->();
/// Behavior of Iterator
const item_proxy* operator->() const;
/// Behavior of Iterator
bool operator==(const item_proxy&) const;
/// Behavior of Iterator
bool operator!=(const item_proxy&) const;
//Undocumented method
essence_t * _m_ess() const;
private:
std::vector<cell> & _m_cells() const;
nana::any * _m_value(bool alloc_if_empty);
const nana::any * _m_value() const;
private:
essence_t * ess_;
category_t* cat_{nullptr};
index_pair pos_;
};
class cat_proxy
: public std::iterator < std::input_iterator_tag, cat_proxy >
{
public:
cat_proxy() = default;
cat_proxy(essence_t*, size_type pos);
cat_proxy(essence_t*, category_t*);
/// Append an item at end of the category, set_value determines whether assign T object to the value of item.
template<typename T>
item_proxy append(T&& t, bool set_value = false)
{
oresolver ores;
if (set_value)
ores << t; //copy it if it is rvalue and set_value is true.
else
ores << std::forward<T>(t);
_m_append(ores.move_cells());
item_proxy iter{ ess_, index_pair(pos_, size() - 1) };
if (set_value)
iter.value(std::forward<T>(t));
return iter;
}
void append(std::initializer_list<nana::string>);
size_type columns() const;
cat_proxy& text(nana::string);
nana::string text() const;
/// Behavior of a container
void push_back(nana::string);
item_proxy begin() const;
item_proxy end() const;
item_proxy cbegin() const;
item_proxy cend() const;
item_proxy at(size_type pos) const;
item_proxy back() const;
/// Returns the index of a item by its display pos, the index of the item isn't changed after sorting.
size_type index_by_display_order(size_type disp_order) const;
size_type display_order(size_type pos) const;
size_type position() const;
/// Returns the number of items
size_type size() const;
/// Behavior of Iterator
cat_proxy& operator=(const cat_proxy&);
/// Behavior of Iterator
cat_proxy & operator++();
/// Behavior of Iterator
cat_proxy operator++(int);
/// Behavior of Iterator
cat_proxy& operator*();
/// Behavior of Iterator
const cat_proxy& operator*() const;
/// Behavior of Iterator
cat_proxy* operator->();
/// Behavior of Iterator
const cat_proxy* operator->() const;
/// Behavior of Iterator
bool operator==(const cat_proxy&) const;
/// Behavior of Iterator
bool operator!=(const cat_proxy&) const;
private:
void _m_append(std::vector<cell> && cells);
void _m_cat_by_pos();
private:
essence_t* ess_{nullptr};
category_t* cat_{nullptr};
size_type pos_{0};
};
}
}//end namespace drawerbase
struct arg_listbox
{
mutable drawerbase::listbox::item_proxy item;
bool selected;
};
namespace drawerbase
{
namespace listbox
{
struct listbox_events
: public general_events
{
basic_event<arg_listbox> checked;
basic_event<arg_listbox> selected;
};
}
}//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 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,
*/
class listbox
: public widget_object<category::widget_tag, drawerbase::listbox::trigger, drawerbase::listbox::listbox_events>,
public concepts::any_objective<drawerbase::listbox::size_type, 2>
{
public:
using size_type = drawerbase::listbox::size_type;
using index_pair = drawerbase::listbox::index_pair;
using cat_proxy = drawerbase::listbox::cat_proxy;
using item_proxy = drawerbase::listbox::item_proxy;
using selection = drawerbase::listbox::selection; ///<A container type for items.
using iresolver = drawerbase::listbox::iresolver;
using oresolver = drawerbase::listbox::oresolver;
using cell = drawerbase::listbox::cell;
public:
listbox() = default;
listbox(window, bool visible);
listbox(window, const rectangle& = {}, bool visible = true);
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
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;
listbox& ordered_categories(bool);
template<typename Key>
cat_proxy operator[](const Key & ck)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
std::shared_ptr<nana::detail::key_interface> p(new nana::key<key_t, std::less<key_t>>(ck), [](nana::detail::key_interface* p)
{
delete p;
});
return cat_proxy(&_m_ess(), _m_at_key(p));
}
template<typename Key>
cat_proxy operator[](Key && ck)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
std::shared_ptr<nana::detail::key_interface> p(new nana::key<key_t, std::less<key_t>>(std::move(ck)), [](nana::detail::key_interface* p)
{
delete p;
});
return cat_proxy(&_m_ess(), _m_at_key(p));
}
item_proxy at(const index_pair&) const;
void insert(const index_pair&, nana::string); ///<Insert a new item with a text in the first column.
void checkable(bool);
selection checked() const; ///<Returns the items which are checked.
void clear(size_type cat); ///<Removes all the items from the specified category
void clear(); ///<Removes all the items from all categories
void erase(size_type cat); ///<Erases a category
void erase(); ///<Erases all categories.
item_proxy erase(item_proxy);
template<typename Key>
void erase_key(const Key& kv)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
nana::key<key_t, std::less<key_t> > key(kv);
_m_ease_key(&key);
}
template<typename Key>
void erase_key(Key&& kv)
{
typedef typename nana::detail::type_escape<Key>::type key_t;
nana::key<key_t, std::less<key_t> > key(std::move(kv));
_m_ease_key(&key);
}
///Sets a strick weak ordering comparer for a column
void set_sort_compare(size_type col, std::function<bool(const nana::string&, nana::any*,
const nana::string&, nana::any*, bool reverse)> strick_ordering);
void sort_col(size_type col, bool reverse = false);
size_type sort_col() const;
void unsort();
bool freeze_sort(bool freeze);
selection selected() const; ///<Get the indexs of all the selected items
void show_header(bool);
bool visible_header() const;
void move_select(bool upwards); ///<Selects an item besides the current selected item.
size_type size_categ() const; ///<Get the number of categories
size_type size_item() const; ///<The number of items in the default category
size_type size_item(size_type cat) const; ///<The number of items in category "cat"
private:
drawerbase::listbox::essence_t & _m_ess() const;
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const;
size_type _m_headers() const;
drawerbase::listbox::category_t* _m_at_key(std::shared_ptr<nana::detail::key_interface>);
void _m_ease_key(nana::detail::key_interface*);
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,200 @@
/*
* A Menu implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2009-2014 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: nana/gui/widgets/menu.hpp
*/
#ifndef NANA_GUI_WIDGETS_MENU_HPP
#define NANA_GUI_WIDGETS_MENU_HPP
#include "widget.hpp"
#include <vector>
#include <nana/gui/timer.hpp>
#include <nana/pat/cloneable.hpp>
namespace nana
{
namespace drawerbase
{
namespace menu
{
struct menu_type; //declaration
enum class checks
{
none,
option,
highlight
};
struct menu_item_type
{
/// This class is used as parameter of menu event function.
class item_proxy
{
public:
item_proxy(std::size_t n, menu_item_type &);
item_proxy& enabled(bool);
bool enabled() const;
item_proxy& check_style(checks);
item_proxy& checked(bool);
bool checked() const;
std::size_t index() const;
private:
std::size_t index_;
menu_item_type &item_;
};
/// A callback functor type.
typedef std::function<void(item_proxy&)> event_fn_t;
//Default constructor initializes the item as a splitter
menu_item_type();
menu_item_type(nana::string, const event_fn_t&);
struct
{
bool enabled:1;
bool splitter:1;
bool checked:1;
}flags;
menu_type *sub_menu{nullptr};
nana::string text;
event_fn_t functor;
checks style{checks::none};
paint::image image;
mutable nana::char_t hotkey{0};
};
struct menu_type
{
typedef std::vector<menu_item_type> item_container;
typedef item_container::iterator iterator;
typedef item_container::const_iterator const_iterator;
std::vector<menu_type*> owner;
std::vector<menu_item_type> items;
unsigned max_pixels;
unsigned item_pixels;
nana::point gaps;
};
class renderer_interface
{
public:
typedef nana::paint::graphics & graph_reference;
enum class state
{
normal, active
};
struct attr
{
state item_state;
bool enabled;
bool checked;
checks check_style;
};
virtual ~renderer_interface() = 0;
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_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;
};
}//end namespace menu
}//end namespace drawerbase
class menu
: private noncopyable
{
struct implement;
//let menubar access the private _m_popup() method.
friend class menu_accessor;
public:
typedef drawerbase::menu::checks checks;
typedef drawerbase::menu::renderer_interface renderer_interface;
typedef drawerbase::menu::menu_item_type item_type;
typedef item_type::item_proxy item_proxy;
typedef item_type::event_fn_t event_fn_t; ///< A callback functor type. Prototype: `void(item_proxy&)`
menu(); ///< The default constructor. NO OTHER CONSTRUCTOR.
~menu();
/// Appends an item to the menu.
item_proxy append(const nana::string& text, const event_fn_t& callback= event_fn_t());
void append_splitter();
void clear(); ///< Erases all of the items.
/// Closes the menu. It does not destroy the menu; just close the window for the menu.
void close();
void image(std::size_t index, const paint::image& icon);
void check_style(std::size_t index, checks);
void checked(std::size_t index, bool);
bool checked(std::size_t index) const;
void enabled(std::size_t index, bool);///< Enables or disables the mouse or keyboard input for the item.
bool enabled(std::size_t index) const;
void erase(std::size_t index); ///< Removes the item
bool link(std::size_t index, menu& menu_obj);///< Link a menu to the item as a sub menu.
menu * link(std::size_t index); ///< Retrieves a linked sub menu of the item.
menu *create_sub_menu(std::size_t index);
void popup(window owner, int x, int y); ///< Popup the menu at the owner window.
void popup_await(window owner, int x, int y);
void answerer(std::size_t index, const event_fn_t&); ///< Modify answerer of the specified item.
void destroy_answer(const std::function<void()>&); ///< Sets an answerer for the callback while the menu window is closing.
void gaps(const nana::point&); ///< Sets the gap between a menu and its sub menus.(\See Note4)
void goto_next(bool forward); ///< Moves the focus to the next or previous item.
bool goto_submen();///< Popup the submenu of the current item if it has a sub menu. Returns true if succeeds.
bool exit_submenu(); ///< Closes the current window of the sub menu.
std::size_t size() const; ///< Return the number of items.
int send_shortkey(nana::char_t key);
void pick();
menu& max_pixels(unsigned); ///< Sets the max width in pixels of the item.
unsigned max_pixels() const;
menu& item_pixels(unsigned); ///< Sets the height in pixel for the items.
unsigned item_pixels() const;
void renderer(const pat::cloneable<renderer_interface>&); ///< Sets a user-defined renderer.
const pat::cloneable<renderer_interface>& renderer() const;
private:
void _m_destroy_menu_window();
void _m_popup(window, int x, int y, bool called_by_menubar);
private:
implement * impl_;
};
namespace detail
{
class popuper
{
public:
popuper(menu&, mouse);
popuper(menu&, window owner, const point&, mouse);
void operator()(const arg_mouse&);
private:
menu & mobj_;
window owner_;
bool take_mouse_pos_;
nana::point pos_;
mouse mouse_;
};
}
detail::popuper menu_popuper(menu&, mouse = mouse::right_button);
detail::popuper menu_popuper(menu&, window owner, const point&, mouse = mouse::right_button);
}//end namespace nana
#endif

View File

@@ -0,0 +1,113 @@
/*
* A Menubar implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2009-2014 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: nana/gui/widgets/menubar.hpp
*/
#ifndef NANA_GUI_WIDGETS_MENUBAR_HPP
#define NANA_GUI_WIDGETS_MENUBAR_HPP
#include "widget.hpp"
#include "menu.hpp"
namespace nana
{
namespace drawerbase
{
namespace menubar
{
class item_renderer
{
public:
enum state_t{state_normal, state_highlight, state_selected};
typedef nana::paint::graphics& graph_reference;
item_renderer(window, graph_reference);
virtual void background(const nana::point& pos, const nana::size& size, state_t);
virtual void caption(int x, int y, const nana::string& text);
private:
window handle_;
graph_reference graph_;
};
class trigger
: public drawer_trigger
{
class itembase;
public:
trigger();
~trigger();
nana::menu* push_back(const nana::string&);
nana::menu* at(size_t) const;
std::size_t size() const;
private:
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void focus(graph_reference, const arg_focus&) override;
void key_press(graph_reference, const arg_keyboard&) override;
void key_release(graph_reference, const arg_keyboard&) override;
void shortkey(graph_reference, const arg_keyboard&) override;
private:
void _m_move(bool to_left);
bool _m_popup_menu();
void _m_total_close();
bool _m_close_menu();
void _m_unload_menu_window();
std::size_t _m_item_by_pos(const ::nana::point&);
bool _m_track_mouse(const ::nana::point&);
void _m_draw();
private:
widget *widget_;
nana::paint::graphics *graph_;
itembase* items_;
struct state_type
{
enum behavior_t
{
behavior_none, behavior_focus, behavior_menu,
};
state_type();
std::size_t active;
behavior_t behavior;
bool menu_active;
bool passive_close;
bool nullify_mouse;
nana::menu *menu;
nana::point mouse_pos;
}state_;
};
}//end namespace menubar
}//end namespace drawerbase
/// \brief A toolbar at the top of window for popuping menus.
///
/// The widget sets as shortkey the character behind the first of & in the text, for the item. e.g. "File(&F)" or "&File".
class menubar
: public widget_object<category::widget_tag, drawerbase::menubar::trigger>
{
public:
menubar(); ///< The default constructor delay creation.
menubar(window); ///< Create a menubar at the top of the specified window.
void create(window); ///< Create a menubar at the top of the specified window.
menu& push_back(const nana::string&); ///< Appends a new (empty) menu.
menu& at(size_t index) const; ///< Gets the menu specified by index.
std::size_t length() const; ///< Number of menus.
};//end class menubar
}//end namespace nana
#endif

View File

@@ -0,0 +1,71 @@
/*
* A Panel Implementation
* Nana C++ Library(http://www.nanaro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/panel.hpp
*
* @brief: panel is a widget used for placing some widgets.
*/
#ifndef NANA_GUI_WIDGETS_PANEL_HPP
#define NANA_GUI_WIDGETS_PANEL_HPP
#include "widget.hpp"
#include <type_traits>
namespace nana
{
namespace drawerbase
{
namespace panel
{
class drawer: public drawer_trigger
{
public:
drawer();
private:
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
private:
window window_;
};
}// end namespace panel
}//end namespace drawerbase
/// For placing other widgets, where the bool template parameter determinte if it is widget or lite_widget, wich in actual use make no difference.
template<bool HasBackground>
class panel
: public widget_object<typename std::conditional<HasBackground, category::widget_tag, category::lite_widget_tag>::type,
drawerbase::panel::drawer>
{
public:
panel(){}
panel(window wd, bool visible)
{
this->create(wd, rectangle(), visible);
}
panel(window wd, const nana::rectangle& r = rectangle(), bool visible = true)
{
this->create(wd, r, visible);
}
bool transparent() const
{
return (bground_mode::basic == API::effects_bground_mode(*this));
}
void transparent(bool tr)
{
if(tr)
API::effects_bground(*this, effects::bground_transparent(0), 0);
else
API::effects_bground_remove(*this);
}
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,81 @@
/*
* A Picture Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/picture.hpp
*
* Used for showing a picture
*/
#ifndef NANA_GUI_WIDGET_PICTURE_HPP
#define NANA_GUI_WIDGET_PICTURE_HPP
#include "widget.hpp"
namespace nana
{
namespace xpicture
{
class picture_drawer: public drawer_trigger
{
public:
picture_drawer();
void attached(widget_reference, graph_reference) override;
void load(const nana::char_t* file);
void load(const nana::paint::image&);
void set_shadow_background(unsigned begin_color, unsigned end_color, bool horizontal);
bool bgstyle(bool is_stretch, nana::arrange, int beg, int end);
private:
void refresh(graph_reference) override;
void _m_draw_background();
private:
widget* widget_;
nana::paint::graphics* graph_;
struct runtime_type
{
runtime_type();
unsigned background_shadow_start;
unsigned background_shadow_end;
bool horizontal;
}runtime_;
struct back_image_tag
{
nana::paint::image image;
bool is_stretch;
nana::arrange arg;
int beg, end;
}backimg_;
};
}//end namespace xpicture
/// Rectangle area for displaying a bitmap file
class picture
: public widget_object<category::widget_tag, xpicture::picture_drawer>
{
public:
picture();
picture(window, bool visible);
picture(window, const rectangle& = rectangle(), bool visible = true);
void load(const nana::paint::image&);
/// Sets the background image style.
void bgstyle(bool stretchable, ///< if false the other arguments will be ignored
nana::arrange arg, ///< stretching the image horizontally or vertically
int beg, ///< specify the stretchy area of image.
int end ///< specify the stretchy area of image.
);
/// Fills a gradual change color in background.
void set_shadow_background(unsigned begin_color, unsigned end_color, bool horizontal);
void transparent(bool);
bool transparent() const;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,73 @@
/*
* A Progress Indicator Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/progress.hpp
*/
#ifndef NANA_GUI_WIDGET_PROGRESS_HPP
#define NANA_GUI_WIDGET_PROGRESS_HPP
#include "widget.hpp"
namespace nana
{
namespace drawerbase
{
namespace progress
{
class trigger: public drawer_trigger
{
public:
trigger();
unsigned value() const;
unsigned value(unsigned);
unsigned inc();
unsigned Max() const;
unsigned Max(unsigned);
void unknown(bool);
bool unknown() const;
private:
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
private:
void _m_draw();
void _m_draw_box(graph_reference);
void _m_draw_progress(graph_reference);
bool _m_check_changing(unsigned) const;
private:
static const unsigned border = 2;
widget * widget_;
nana::paint::graphics* graph_;
unsigned draw_width_;
bool has_value_;
bool unknown_;
unsigned max_;
unsigned value_;
}; //end class drawer
}
}//end namespace drawerbase
/// \brief A progressbar widget with two styles: know, and unknow amount value (goal).
/// In unknow style the amount is ignored and the bar is scrolled when value change.
class progress
: public widget_object<category::widget_tag, drawerbase::progress::trigger>
{
public:
progress();
progress(window, bool visible);
progress(window, const rectangle & = rectangle(), bool visible = true);
unsigned value() const;
unsigned value(unsigned val);
unsigned inc();
unsigned amount() const;
unsigned amount(unsigned value);
void unknown(bool);
bool unknown() const;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,444 @@
/*
* A Scroll Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/scroll.hpp
*/
#ifndef NANA_GUI_WIDGET_SCROLL_HPP
#define NANA_GUI_WIDGET_SCROLL_HPP
#include "widget.hpp"
#include <nana/paint/gadget.hpp>
#include <nana/gui/timer.hpp>
namespace nana
{
template<bool Vert> class scroll;
template<bool Vert>
struct arg_scroll
{
scroll<Vert> & widget;
};
namespace drawerbase
{
namespace scroll
{
template<bool Vert>
struct scroll_events
: public general_events
{
basic_event<arg_scroll<Vert>> value_changed;
};
enum class buttons
{
none, forward, backward, scroll, first, second
};
struct metrics_type
{
typedef std::size_t size_type;
size_type peak;
size_type range;
size_type step;
size_type value;
buttons what;
bool pressed;
size_type scroll_length;
int scroll_pos;
int scroll_mouse_offset;
metrics_type();
};
class drawer
{
public:
struct states
{
enum{none, highlight, actived, selected};
};
typedef nana::paint::graphics& graph_reference;
const static unsigned fixedsize = 16;
drawer(metrics_type& m);
void set_vertical(bool);
buttons what(graph_reference, const point&);
void scroll_delta_pos(graph_reference, int);
void auto_scroll();
void draw(graph_reference, buttons);
private:
bool _m_check() const;
void _m_adjust_scroll(graph_reference);
void _m_background(graph_reference);
void _m_button_frame(graph_reference, int x, int y, unsigned width, unsigned height, int state);
void _m_draw_scroll(graph_reference, int state);
void _m_draw_button(graph_reference, int x, int y, unsigned width, unsigned height, buttons what, int state);
private:
metrics_type &metrics_;
bool vertical_;
};
template<bool Vertical>
class trigger
: public drawer_trigger
{
public:
typedef metrics_type::size_type size_type;
trigger()
: graph_(nullptr), drawer_(metrics_)
{
drawer_.set_vertical(Vertical);
}
const metrics_type& metrics() const
{
return metrics_;
}
void peak(size_type s)
{
if(graph_ && (metrics_.peak != s))
{
metrics_.peak = s;
API::refresh_window(widget_->handle());
}
}
void value(size_type s)
{
if(s + metrics_.range > metrics_.peak)
s = metrics_.peak - metrics_.range;
if(graph_ && (metrics_.value != s))
{
metrics_.value = s;
_m_emit_value_changed();
API::refresh_window(*widget_);
}
}
void range(size_type s)
{
if(graph_ && (metrics_.range != s))
{
metrics_.range = s;
API::refresh_window(widget_->handle());
}
}
void step(size_type s)
{
metrics_.step = s;
}
bool make_step(bool forward, unsigned multiple)
{
if(graph_)
{
size_type step = (multiple > 1 ? metrics_.step * multiple : metrics_.step);
size_type value = metrics_.value;
if(forward)
{
size_type maxv = metrics_.peak - metrics_.range;
if(metrics_.peak > metrics_.range && value < maxv)
{
if(maxv - value >= step)
value += step;
else
value = maxv;
}
}
else if(value)
{
if(value > step)
value -= step;
else
value = 0;
}
size_type cmpvalue = metrics_.value;
metrics_.value = value;
if(value != cmpvalue)
{
_m_emit_value_changed();
return true;
}
return false;
}
return false;
}
private:
void attached(widget_reference widget, graph_reference graph)
{
graph_ = &graph;
widget_ = static_cast< ::nana::scroll<Vertical>*>(&widget);
widget.caption(STR("Nana Scroll"));
timer_.stop();
timer_.elapse(std::bind(&trigger::_m_tick, this));
}
void detached()
{
graph_ = nullptr;
}
void refresh(graph_reference graph)
{
drawer_.draw(graph, metrics_.what);
}
void resized(graph_reference graph, const ::nana::arg_resized&) override
{
drawer_.draw(graph, metrics_.what);
API::lazy_refresh();
}
void mouse_enter(graph_reference graph, const ::nana::arg_mouse& arg) override
{
metrics_.what = drawer_.what(graph, arg.pos);
drawer_.draw(graph, metrics_.what);
API::lazy_refresh();
}
void mouse_move(graph_reference graph, const ::nana::arg_mouse& arg)
{
bool redraw = false;
if(metrics_.pressed && (metrics_.what == buttons::scroll))
{
size_type cmpvalue = metrics_.value;
drawer_.scroll_delta_pos(graph, (Vertical ? arg.pos.y : arg.pos.x));
if(cmpvalue != metrics_.value)
_m_emit_value_changed();
redraw = true;
}
else
{
buttons what = drawer_.what(graph, arg.pos);
if(metrics_.what != what)
{
redraw = true;
metrics_.what = what;
}
}
if(redraw)
{
drawer_.draw(graph, metrics_.what);
API::lazy_refresh();
}
}
void mouse_down(graph_reference graph, const arg_mouse& arg)
{
if(arg.left_button)
{
metrics_.pressed = true;
metrics_.what = drawer_.what(graph, arg.pos);
switch(metrics_.what)
{
case buttons::first:
case buttons::second:
make_step(metrics_.what == buttons::second, 1);
timer_.interval(1000);
timer_.start();
break;
case buttons::scroll:
API::capture_window(widget_->handle(), true);
metrics_.scroll_mouse_offset = (Vertical ? arg.pos.y : arg.pos.x) - metrics_.scroll_pos;
break;
case buttons::forward:
case buttons::backward:
{
size_type cmpvalue = metrics_.value;
drawer_.auto_scroll();
if(cmpvalue != metrics_.value)
_m_emit_value_changed();
}
break;
default: //Ignore buttons::none
break;
}
drawer_.draw(graph, metrics_.what);
API::lazy_refresh();
}
}
void mouse_up(graph_reference graph, const arg_mouse& arg)
{
timer_.stop();
API::capture_window(widget_->handle(), false);
metrics_.pressed = false;
metrics_.what = drawer_.what(graph, arg.pos);
drawer_.draw(graph, metrics_.what);
API::lazy_refresh();
}
void mouse_leave(graph_reference graph, const arg_mouse&)
{
if(metrics_.pressed) return;
metrics_.what = buttons::none;
drawer_.draw(graph, buttons::none);
API::lazy_refresh();
}
void mouse_wheel(graph_reference graph, const arg_wheel& arg)
{
if(make_step(arg.upwards == false, 3))
{
drawer_.draw(graph, metrics_.what);
API::lazy_refresh();
}
}
private:
void _m_emit_value_changed()
{
widget_->events().value_changed.emit(::nana::arg_scroll<Vertical>({*widget_}));
}
void _m_tick()
{
make_step(metrics_.what == buttons::second, 1);
API::refresh_window(widget_->handle());
timer_.interval(100);
}
private:
::nana::scroll<Vertical> * widget_;
nana::paint::graphics * graph_;
metrics_type metrics_;
drawer drawer_;
timer timer_;
};
}//end namespace scroll
}//end namespace drawerbase
/// Provides a way to display an object which is larger than the window's client area.
template<bool Vertical>
class scroll
: public widget_object<category::widget_tag, drawerbase::scroll::trigger<Vertical>, drawerbase::scroll::scroll_events<Vertical>>
{
typedef widget_object<category::widget_tag, drawerbase::scroll::trigger<Vertical> > base_type;
public:
typedef std::size_t size_type;
/// \brief The default constructor without creating the widget.
scroll(){}
/// \brief The construct that creates a widget.
/// @param wd A handle to the parent window of the widget being created.
/// @param visible specifying the visible after creating.
scroll(window wd, bool visible)
{
this->create(wd, rectangle(), visible);
}
/// \brief The construct that creates a widget.
/// @param wd A handle to the parent window of the widget being created.
/// @param r the size and position of the widget in its parent window coordinate.
/// @param visible specifying the visible after creating.
scroll(window wd, const rectangle& r, bool visible = true)
{
this->create(wd, r, visible);
}
/// \brief Determines whether it is scrollable.
/// @param for_less whether it can be scrolled for a less value.
bool scrollable(bool for_less) const
{
auto & m = this->get_drawer_trigger().metrics();
return (for_less ? (0 != m.value) : (m.value < m.peak - m.range));
}
size_type amount() const
{
return this->get_drawer_trigger().metrics().peak;
}
void amount(size_type Max)
{
return this->get_drawer_trigger().peak(Max);
}
/// Get the range of the widget.
size_type range() const
{
return this->get_drawer_trigger().metrics().range;
}
/// Set the range of the widget.
void range(size_type r)
{
return this->get_drawer_trigger().range(r);
}
/// \brief Get the value.
/// @return the value.
size_type value() const
{
return this->get_drawer_trigger().metrics().value;
}
/// \brief Set the value.
/// @param s a new value.
void value(size_type s)
{
return this->get_drawer_trigger().value(s);
}
/// \brief Get the step of the sroll widget. The step indicates a variation of the value.
/// @return the step.
size_type step() const
{
return this->get_drawer_trigger().metrics().step;
}
/// \brief Set the step.
/// @param s a value for step.
void step(size_type s)
{
return this->get_drawer_trigger().step(s);
}
/// \brief Increase/decrease values by a step.
/// @param forward it determines whether increase or decrease.
/// @return true if the value is changed.
bool make_step(bool forward)
{
if(this->get_drawer_trigger().make_step(forward, 1))
{
API::refresh_window(this->handle());
return true;
}
return false;
}
/// \brief Increase/decrease values by steps as if it is scrolled through mouse wheel.
/// @param forward it determines whether increase or decrease.
/// @return true if the vlaue is changed.
bool make_scroll(bool forward)
{
if(this->get_drawer_trigger().make_step(forward, 3))
{
API::refresh_window(this->handle());
return true;
}
return false;
}
};//end class scroll
}//end namespace nana
#endif

View File

@@ -0,0 +1,335 @@
/*
* A text editor implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/skeletons/text_editor.hpp
* @description:
*/
#ifndef NANA_GUI_SKELETONS_TEXT_EDITOR_HPP
#define NANA_GUI_SKELETONS_TEXT_EDITOR_HPP
#include "textbase.hpp"
#include <nana/gui/widgets/scroll.hpp>
#include <nana/unicode_bidi.hpp>
#include <memory>
namespace nana{ namespace widgets
{
namespace skeletons
{
template<typename EnumCommand>
class undoable_command_interface
{
public:
virtual ~undoable_command_interface() = default;
virtual EnumCommand get() const = 0;
virtual bool merge(const undoable_command_interface&) = 0;
virtual void execute(bool redo) = 0;
};
template<typename EnumCommand>
class undoable
{
public:
using command = EnumCommand;
using container = std::deque < std::unique_ptr<undoable_command_interface<command>> >;
void max_steps(std::size_t maxs)
{
max_steps_ = maxs;
if (maxs && (commands_.size() >= maxs))
commands_.erase(commands_.begin(), commands_.begin() + (commands_.size() - maxs + 1));
}
std::size_t max_steps() const
{
return max_steps_;
}
void enable(bool enb)
{
enabled_ = enb;
if (!enb)
commands_.clear();
}
bool enabled() const
{
return enabled_;
}
void push(std::unique_ptr<undoable_command_interface<command>> && ptr)
{
if (!ptr || !enabled_)
return;
if (pos_ < commands_.size())
commands_.erase(commands_.begin() + pos_, commands_.end());
else if (max_steps_ && (commands_.size() >= max_steps_))
commands_.erase(commands_.begin(), commands_.begin() + (commands_.size() - max_steps_ + 1));
pos_ = commands_.size();
if (!commands_.empty())
{
if (commands_.back().get()->merge(*ptr))
return;
}
commands_.emplace_back(std::move(ptr));
++pos_;
}
std::size_t count(bool is_undo) const
{
return (is_undo ? pos_ : commands_.size() - pos_);
}
void undo()
{
if (pos_ > 0)
{
--pos_;
commands_[pos_].get()->execute(false);
}
}
void redo()
{
if (pos_ != commands_.size())
commands_[pos_++].get()->execute(true);
}
private:
container commands_;
bool enabled_{ true };
std::size_t max_steps_{ 30 };
std::size_t pos_{ 0 };
};
class text_editor
{
struct attributes;
class editor_behavior_interface;
class behavior_normal;
class behavior_linewrapped;
enum class command{
backspace, input_text, move_text,
};
//Commands for undoable
template<typename EnumCommand> class basic_undoable;
class undo_backspace;
class undo_input_text;
class undo_move_text;
public:
typedef nana::char_t char_type;
typedef textbase<char_type>::size_type size_type;
typedef textbase<char_type>::string_type string_type;
typedef nana::paint::graphics & graph_reference;
struct ext_renderer_tag
{
std::function<void(graph_reference, const nana::rectangle& text_area, nana::color_t)> background;
};
text_editor(window, graph_reference);
~text_editor();
bool respone_keyboard(nana::char_t, bool enterable);
void typeface_changed();
/// Determine whether the text_editor is line wrapped.
bool line_wrapped() const;
/// Set the text_editor whether it is line wrapped, it returns false if the state is not changed.
bool line_wrapped(bool);
void border_renderer(std::function<void(graph_reference, nana::color_t bgcolor)>);
bool load(const nana::char_t*);
//text_area
//@return: Returns true if the area of text is changed.
bool text_area(const nana::rectangle&);
bool tip_string(nana::string&&);
const attributes & attr() const;
bool multi_lines(bool);
void editable(bool);
void enable_background(bool);
void enable_background_counterpart(bool);
void undo_enabled(bool);
bool undo_enabled() const;
void undo_max_steps(std::size_t);
std::size_t undo_max_steps() const;
ext_renderer_tag& ext_renderer() const;
unsigned line_height() const;
unsigned screen_lines() const;
bool getline(std::size_t pos, nana::string&) const;
void text(nana::string);
nana::string text() const;
//move_caret
//@brief: Set caret position through text coordinate
void move_caret(const upoint&);
void move_caret_end();
void reset_caret_height() const;
void reset_caret();
void show_caret(bool isshow);
bool selected() const;
bool select(bool);
//Set the end position of a selected string
void set_end_caret();
bool hit_text_area(const point&) const;
bool hit_select_area(nana::upoint pos) const;
bool move_select();
bool mask(char_t);
/// Returns width of text area excluding the vscroll size.
unsigned width_pixels() const;
public:
void draw_scroll_rectangle();
void render(bool focused);
public:
void put(nana::string);
void put(nana::char_t);
void copy() const;
void cut();
void paste();
void enter(bool record_undo = true);
void del();
void backspace(bool record_undo = true);
void undo(bool reverse);
bool move(nana::char_t);
void move_ns(bool to_north); //Moves up and down
void move_left();
void move_right();
nana::upoint mouse_caret(const point& screen_pos);
nana::upoint caret() const;
bool scroll(bool upwards, bool vertical);
bool mouse_enter(bool);
bool mouse_down(bool left_button, const point& screen_pos);
bool mouse_move(bool left_button, const point& screen_pos);
bool mouse_up(bool left_button, const point& screen_pos);
skeletons::textbase<nana::char_t>& textbase();
const skeletons::textbase<nana::char_t>& textbase() const;
private:
nana::color_t _m_bgcolor() const;
bool _m_scroll_text(bool vertical);
void _m_on_scroll(const arg_mouse&);
void _m_scrollbar();
nana::size _m_text_area() const;
void _m_get_scrollbar_size();
void _m_reset();
nana::upoint _m_put(nana::string);
nana::upoint _m_erase_select();
bool _m_make_select_string(nana::string&) const;
static bool _m_resolve_text(const nana::string&, std::vector<std::pair<std::size_t, std::size_t>> & lines);
bool _m_cancel_select(int align);
unsigned _m_tabs_pixels(size_type tabs) const;
nana::size _m_text_extent_size(const char_type*) const;
nana::size _m_text_extent_size(const char_type*, size_type n) const;
//_m_move_offset_x_while_over_border
//@brief: Moves the view window
bool _m_move_offset_x_while_over_border(int many);
bool _m_move_select(bool record_undo);
int _m_text_top_base() const;
//_m_endx
//@brief: Gets the right point of text area
int _m_endx() const;
//_m_endy
//@brief: Get the bottom point of text area
int _m_endy() const;
void _m_draw_tip_string() const;
//_m_draw_string
//@brief: Draw a line of string
void _m_draw_string(int top, nana::color_t color, const nana::upoint& str_pos, const nana::string&, bool if_mask) const;
//_m_draw
//@brief: Draw a character at a position specified by caret pos.
//@return: true if beyond the border
bool _m_draw(nana::char_t, std::size_t secondary_before);
bool _m_get_sort_select_points(nana::upoint&, nana::upoint&) const;
void _m_offset_y(int y);
unsigned _m_char_by_pixels(const nana::char_t*, std::size_t len, unsigned* pxbuf, int str_px, int pixels, bool is_rtl);
unsigned _m_pixels_by_char(const nana::string&, std::size_t pos) const;
static bool _m_is_right_text(const unicode_bidi::entity&);
private:
std::unique_ptr<editor_behavior_interface> behavior_;
undoable<command> undo_;
nana::window window_;
graph_reference graph_;
skeletons::textbase<nana::char_t> textbase_;
nana::char_t mask_char_{0};
mutable ext_renderer_tag ext_renderer_;
struct attributes
{
nana::string tip_string;
bool line_wrapped{false};
bool multi_lines{true};
bool editable{true};
bool enable_background{true};
bool enable_counterpart{false};
nana::paint::graphics counterpart; //this is used to keep the background that painted by external part.
std::unique_ptr<nana::scroll<true>> vscroll;
std::unique_ptr<nana::scroll<false>> hscroll;
}attributes_;
struct text_area_type
{
nana::rectangle area;
bool captured;
unsigned tab_space;
unsigned scroll_pixels;
unsigned vscroll;
unsigned hscroll;
std::function<void(nana::paint::graphics&, nana::color_t)> border_renderer;
}text_area_;
struct selection
{
enum mode_selection_t{mode_no_selected, mode_mouse_selected, mode_method_selected};
mode_selection_t mode_selection;
bool dragged;
nana::upoint a, b;
}select_;
struct coordinate
{
nana::point offset; //x stands for pixels, y for lines
nana::upoint caret; //position of caret by text, it specifies the position of a new character
unsigned xpos{0}; //This data is used for move up/down
}points_;
};
}//end namespace skeletons
}//end namespace widgets
}//end namespace nana
#endif

View File

@@ -0,0 +1,952 @@
/*
* Text Token Stream
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2013 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: nana/gui/widgets/skeletons/text_token_stream.hpp
*/
#ifndef NANA_GUI_WIDGETS_SKELETONS_TEXT_TOKEN_STREAM
#define NANA_GUI_WIDGETS_SKELETONS_TEXT_TOKEN_STREAM
#include <nana/gui/layout_utility.hpp>
#include <sstream>
#include <deque>
#include <vector>
#include <list>
#include <stack>
#include <stdexcept>
namespace nana{ namespace widgets{ namespace skeletons
{
//The tokens are defined for representing a text, the tokens are divided
//into two parts.
//Formatted tokens: The tokens present in a format block, they form the format-syntax.
//Data tokens: The tokens present a text displaying on the screen.
enum class token
{
tag_begin, tag_end, format_end,
font, bold, size, color, url, target, image, top, center, bottom, baseline,
number, string, _true, _false, red, green, blue, white, black, binary, min_limited, max_limited,
equal, comma, backslash,
data, endl,
eof
};
class tokenizer
{
public:
tokenizer(const nana::string& s, bool format_enabled)
: iptr_(s.data()),
endptr_(s.data() + s.size()),
format_enabled_(format_enabled),
format_state_(false),
revert_token_(token::eof)
{
}
void push(token tk)
{
revert_token_ = tk;
}
//Read the token.
token read()
{
if(revert_token_ != token::eof)
{
token tk = revert_token_;
revert_token_ = token::eof;
return tk;
}
if(iptr_ == endptr_)
return token::eof;
//Check whether it is a format token.
if(format_enabled_ && format_state_)
return _m_format_token();
return _m_token();
}
const nana::string& idstr() const
{
return idstr_;
}
const std::pair<nana::string, nana::string>& binary() const
{
return binary_;
}
std::pair<unsigned, unsigned> binary_number() const
{
std::stringstream ss;
ss<<static_cast<std::string>(nana::charset(binary_.first))<<' '<<static_cast<std::string>(nana::charset(binary_.second));
std::pair<unsigned, unsigned> r;
ss>>r.first>>r.second;
return r;
}
int number() const
{
std::stringstream ss;
ss<<static_cast<std::string>(nana::charset(idstr_));
//It's a hex number.
if(idstr_.size() > 2 && idstr_[0] == '0' && (idstr_[1] == 'x' || idstr_[1] == 'X'))
ss>>std::hex;
int n;
ss>>n;
return n;
}
private:
static bool _m_unicode_word_breakable(nana::char_t ch)
{
return ((0x4E00 <= ch) && (ch <= 0x9FFF));
}
//Read the data token
token _m_token()
{
nana::char_t ch = *iptr_;
if(ch > 0xFF)
{
//This is the Unicode.
idstr_.clear();
idstr_.append(1, ch);
if(_m_unicode_word_breakable(ch))
{
++iptr_;
return token::data;
}
ch = *++iptr_;
while((iptr_ != endptr_) && (ch > 0xFF) && (false == _m_unicode_word_breakable(ch)))
{
idstr_.append(1, ch);
ch = *++iptr_;
}
return token::data;
}
if('\n' == ch)
{
++iptr_;
return token::endl;
}
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
{
const nana::char_t * idstr = iptr_;
do
{
ch = *(++iptr_);
}
while(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'));
idstr_.assign(idstr, iptr_);
return token::data;
}
if('0' <= ch && ch <= '9')
{
_m_read_number();
return token::data;
}
if(('<' == ch) && format_enabled_)
{
//pos keeps the current position, and it used for restring
//iptr_ when the search is failed.
const nana::char_t * pos = ++iptr_;
_m_eat_whitespace();
if(*iptr_ == '/')
{
++iptr_;
_m_eat_whitespace();
if(*iptr_ == '>')
{
++iptr_;
return token::format_end;
}
}
//Restore the iptr_;
iptr_ = pos;
format_state_ = true;
return token::tag_begin;
}
//Escape
if(ch == '\\')
{
if(iptr_ + 1 < endptr_)
{
ch = *(iptr_ + 1);
iptr_ += 2;
}
else
{
iptr_ = endptr_;
return token::eof;
}
}
++iptr_;
idstr_.clear();
idstr_.append(1, ch);
return token::data;
}
//Read the format token
token _m_format_token()
{
_m_eat_whitespace();
nana::char_t ch = *iptr_++;
switch(ch)
{
case ',': return token::comma;
case '/': return token::backslash;
case '=': return token::equal;
case '>':
format_state_ = false;
return token::tag_end;
case '"':
//Here is a string and all the meta characters will be ignored except "
{
const nana::char_t * str = iptr_;
while((iptr_ != endptr_) && (*iptr_ != '"'))
++iptr_;
idstr_.assign(str, iptr_++);
}
return token::string;
case '(':
_m_eat_whitespace();
if((iptr_ < endptr_) && _m_is_idstr_element(*iptr_))
{
const nana::char_t * pbegin = iptr_;
while((iptr_ < endptr_) && _m_is_idstr_element(*iptr_))
++iptr_;
binary_.first.assign(pbegin, iptr_);
_m_eat_whitespace();
if((iptr_ < endptr_) && (',' == *iptr_))
{
++iptr_;
_m_eat_whitespace();
if((iptr_ < endptr_) && _m_is_idstr_element(*iptr_))
{
pbegin = iptr_;
while((iptr_ < endptr_) && _m_is_idstr_element(*iptr_))
++iptr_;
binary_.second.assign(pbegin, iptr_);
_m_eat_whitespace();
if((iptr_ < endptr_) && (')' == *iptr_))
{
++iptr_;
return token::binary;
}
}
}
}
return token::eof;
}
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || '_' == ch)
{
--iptr_;
//Here is a identifier
_m_read_idstr();
if(STR("font") == idstr_)
return token::font;
else if(STR("bold") == idstr_)
return token::bold;
else if(STR("size") == idstr_)
return token::size;
else if(STR("baseline") == idstr_)
return token::baseline;
else if(STR("top") == idstr_)
return token::top;
else if(STR("center") == idstr_)
return token::center;
else if(STR("bottom") == idstr_)
return token::bottom;
else if(STR("color") == idstr_)
return token::color;
else if(STR("image") == idstr_)
return token::image;
else if(STR("true") == idstr_)
return token::_true;
else if(STR("url") == idstr_)
return token::url;
else if(STR("target") == idstr_)
return token::target;
else if(STR("false") == idstr_)
return token::_false;
else if(STR("red") == idstr_)
return token::red;
else if(STR("green") == idstr_)
return token::green;
else if(STR("blue") == idstr_)
return token::blue;
else if(STR("white") == idstr_)
return token::white;
else if(STR("black") == idstr_)
return token::black;
else if(STR("min_limited") == idstr_)
return token::min_limited;
else if(STR("max_limited") == idstr_)
return token::max_limited;
return token::string;
}
if('0' <= ch && ch <= '9')
{
--iptr_;
_m_read_number();
return token::number;
}
return token::eof;
}
static bool _m_is_idstr_element(nana::char_t ch)
{
return (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('_' == ch) || ('0' <= ch && ch <= '9'));
}
//Read the identifier.
void _m_read_idstr()
{
const nana::char_t * idstr = iptr_;
nana::char_t ch;
do
{
ch = *(++iptr_);
}
while(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('_' == ch) || ('0' <= ch && ch <= '9'));
idstr_.assign(idstr, iptr_);
}
//Read the number
void _m_read_number()
{
idstr_.clear();
nana::char_t ch = *iptr_;
idstr_ += ch;
//First check the number whether will be a hex number.
if('0' == ch)
{
ch = *++iptr_;
if((!('0' <= ch && ch <= '9')) && (ch != 'x' && ch != 'X'))
return;
if(ch == 'x' || ch == 'X')
{
//Here is a hex number
idstr_ += 'x';
ch = *++iptr_;
while(('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F'))
{
idstr_ += ch;
ch = *++iptr_;
}
return;
}
//Here is not a hex number
idstr_ += ch;
}
ch = *++iptr_;
while('0' <= ch && ch <= '9')
{
idstr_ += ch;
ch = *++iptr_;
}
}
void _m_eat_whitespace()
{
while(true)
{
switch(*iptr_)
{
case ' ':
case '\t':
++iptr_;
break;
default:
return;
}
}
}
private:
const nana::char_t * iptr_;
const nana::char_t * endptr_;
const bool format_enabled_;
bool format_state_;
nana::string idstr_;
std::pair<nana::string, nana::string> binary_;
std::size_t whspace_size_;
token revert_token_;
};
//The fblock states a format, and a format from which it is inherted
struct fblock
{
struct aligns
{
enum t
{
top, center, bottom,
baseline
};
};
nana::string font;
std::size_t font_size;
bool bold;
bool bold_empty; //bold should be ignored if bold_empty is true
aligns::t text_align;
nana::color_t bgcolor; //If the color is not specified, it will be ignored, and the system will search for its parent.
nana::color_t fgcolor; //ditto
nana::string target;
nana::string url;
fblock * parent;
};
//The abstruct data class states a data.
class data
{
public:
typedef nana::paint::graphics& graph_reference;
virtual ~data(){}
virtual bool is_text() const = 0;
virtual bool is_whitespace() const = 0;
virtual const nana::string& text() const = 0;
virtual void measure(graph_reference) = 0;
virtual void nontext_render(graph_reference, int x, int y) = 0;
virtual const nana::size & size() const = 0;
virtual std::size_t ascent() const = 0;
};
class data_text
: public data
{
public:
data_text(const nana::string& s)
: str_(s)
{}
private:
virtual bool is_text() const override
{
return true;
}
virtual bool is_whitespace() const override
{
return false;
}
virtual const nana::string& text() const override
{
return str_;
}
virtual void measure(graph_reference graph) override
{
size_ = graph.text_extent_size(str_);
unsigned ascent;
unsigned descent;
unsigned internal_leading;
graph.text_metrics(ascent, descent, internal_leading);
ascent_ = ascent;
}
virtual void nontext_render(graph_reference, int, int) override
{
}
virtual const nana::size & size() const override
{
return size_;
}
virtual std::size_t ascent() const override
{
return ascent_;
}
private:
nana::string str_;
nana::size size_;
std::size_t ascent_;
};
class data_image
: public data
{
public:
data_image(const nana::string& imgpath, const nana::size & sz, std::size_t limited)
: image_(imgpath), limited_(limited)
{
size_ = image_.size();
if(sz.width != 0 && sz.height != 0)
{
bool make_fit = false;
switch(limited)
{
case 1:
make_fit = (size_.width < sz.width || size_.height < sz.height);
break;
case 2:
make_fit = (size_.width > sz.width || size_.height > sz.height);
break;
}
if(make_fit)
{
nana::size res;
nana::fit_zoom(size_, sz, res);
size_ = res;
}
else
size_ = sz;
}
}
private:
//implement data interface
virtual bool is_text() const override
{
return false;
}
virtual bool is_whitespace() const override
{
return false;
}
virtual const nana::string& text() const override
{
return str_;
}
virtual void measure(graph_reference) override
{
}
virtual void nontext_render(graph_reference graph, int x, int y) override
{
if(size_ != image_.size())
image_.stretch(image_.size(), graph, nana::rectangle(x, y, size_.width, size_.height));
else
image_.paste(graph, x, y);
}
virtual const nana::size & size() const override
{
return size_;
}
virtual std::size_t ascent() const override
{
return size_.height;
}
private:
nana::string str_;
nana::paint::image image_;
nana::size size_;
std::size_t limited_;
};
class dstream
{
struct value
{
fblock * fblock_ptr;
data * data_ptr;
};
public:
typedef std::list<std::deque<value> >::iterator iterator;
typedef std::deque<value> linecontainer;
~dstream()
{
close();
}
void close()
{
for(auto & values: lines_)
{
for(std::deque<value>::iterator u = values.begin(); u != values.end(); ++u)
delete u->data_ptr;
}
lines_.clear();
for(auto p : fblocks_)
delete p;
fblocks_.clear();
}
void parse(const nana::string& s, bool format_enabled)
{
close();
tokenizer tknizer(s, format_enabled);
std::stack<fblock*> fstack;
fstack.push(_m_create_default_fblock());
while(true)
{
token tk = tknizer.read();
switch(tk)
{
case token::data:
_m_data_factory(tk, tknizer.idstr(), fstack.top(), lines_.back());
break;
case token::endl:
lines_.emplace_back();
break;
case token::tag_begin:
_m_parse_format(tknizer, fstack);
if(attr_image_.path.size())
{
_m_data_image(fstack.top(), lines_.back());
//This fblock just serves the image. So we should restore the pervious fblock
fstack.pop();
}
break;
case token::format_end:
if(fstack.size() > 1)
fstack.pop();
break;
case token::eof:
return;
default:
int * debug = 0; //for debug.
*debug = 0;
}
}
}
iterator begin()
{
return lines_.begin();
}
iterator end()
{
return lines_.end();
}
private:
void _m_parse_format(tokenizer & tknizer, std::stack<fblock*> & fbstack)
{
fblock * fp = _m_inhert_from(fbstack.top());
attr_image_.reset();
while(true)
{
switch(tknizer.read())
{
case token::comma: //Eat the comma, now the comma can be omitted.
break;
case token::eof:
case token::tag_end:
fblocks_.push_back(fp);
fbstack.push(fp);
return;
case token::font:
if(token::equal != tknizer.read())
throw std::runtime_error("");
if(token::string != tknizer.read())
throw std::runtime_error("");
fp->font = tknizer.idstr();
break;
case token::size:
if(token::equal != tknizer.read())
throw std::runtime_error("");
switch(tknizer.read())
{
case token::number:
fp->font_size = tknizer.number();
break;
case token::binary:
{
auto value = tknizer.binary_number();
attr_image_.size.width = value.first;
attr_image_.size.height = value.second;
}
break;
default:
throw std::runtime_error("");
}
break;
case token::color:
if(token::equal != tknizer.read())
throw std::runtime_error("");
switch(tknizer.read())
{
case token::number:
fp->fgcolor = tknizer.number();
break;
case token::red:
fp->fgcolor = 0xFF0000;
break;
case token::green:
fp->fgcolor = 0xFF00;
break;
case token::blue:
fp->fgcolor = 0xFF;
break;
case token::white:
fp->fgcolor = 0xFFFFFF;
break;
case token::black:
fp->fgcolor = 0x0;
break;
default:
throw std::runtime_error("");
}
break;
case token::red: //support the omitting of color.
fp->fgcolor = 0xFF0000;
break;
case token::green: //support the omitting of color.
fp->fgcolor = 0xFF00;
break;
case token::blue: //support the omitting of color.
fp->fgcolor = 0xFF;
break;
case token::white: //support the omitting of color.
fp->fgcolor = 0xFFFFFF;
break;
case token::black: //support the omitting of color.
fp->fgcolor = 0x0;
break;
case token::baseline:
fp->text_align = fblock::aligns::baseline;
break;
case token::top:
fp->text_align = fblock::aligns::top;
break;
case token::center:
fp->text_align = fblock::aligns::center;
break;
case token::bottom:
fp->text_align = fblock::aligns::bottom;
break;
case token::image:
if(token::equal != tknizer.read())
throw std::runtime_error("");
if(token::string != tknizer.read())
throw std::runtime_error("");
attr_image_.path = tknizer.idstr();
break;
case token::min_limited:
attr_image_.limited = 1;
break;
case token::max_limited:
attr_image_.limited = 2;
break;
case token::target:
if(token::equal != tknizer.read())
throw std::runtime_error("error: a '=' is required behind 'target'");
if(token::string != tknizer.read())
throw std::runtime_error("error: the value of 'target' should be a string");
fp->target = tknizer.idstr();
break;
case token::url:
if(token::equal != tknizer.read())
throw std::runtime_error("error: a '=' is required behind 'url'");
if(token::string != tknizer.read())
throw std::runtime_error("error: the value of 'url' should be a string");
fp->url = tknizer.idstr();
break;
case token::bold:
{
token tk = tknizer.read();
if(token::equal == tk)
{
switch(tknizer.read())
{
case token::_true:
fp->bold = true;
break;
case token::_false:
fp->bold = false;
break;
default:
throw std::runtime_error("");
}
}
else
{
tknizer.push(tk);
fp->bold = true;
}
fp->bold_empty = false;
}
break;
default:
throw std::runtime_error("");
}
}
}
fblock* _m_create_default_fblock()
{
//Make sure that there is not a fblock is created.
if(fblocks_.size())
return fblocks_.front();
//Create a default fblock.
fblock * fbp = new fblock;
fbp->font_size = 0xFFFFFFFF;
fbp->bold = false;
fbp->bold_empty = true;
fbp->text_align = fblock::aligns::baseline;
//Refer to the definition for the color specification.
fbp->bgcolor = 0xFFFFFFFF;
fbp->fgcolor = 0xFFFFFFFF;
fbp->parent = nullptr;
fblocks_.push_back(fbp);
lines_.emplace_back();
return fbp;
}
fblock * _m_inhert_from(fblock* fp)
{
fblock * fbp = new fblock;
fbp->font = fp->font;
fbp->font_size = fp->font_size;
fbp->bold = fp->bold;
fbp->bold_empty = fp->bold_empty;
fbp->text_align = fp->text_align;
fbp->bgcolor = fp->bgcolor;
fbp->fgcolor = fp->fgcolor;
fbp->target = fp->target;
fbp->parent = fp;
return fbp;
}
void _m_data_factory(token tk, const nana::string& idstr, fblock* fp, std::deque<value>& line)
{
value v;
v.fblock_ptr = fp;
switch(tk)
{
case token::data:
v.data_ptr = new data_text(idstr);
break;
default:
int * debug = 0; //for debug
*debug = 0;
}
line.push_back(v);
}
void _m_data_image(fblock* fp, std::deque<value>& line)
{
value v;
v.fblock_ptr = fp;
v.data_ptr = new data_image(attr_image_.path, attr_image_.size, attr_image_.limited);
line.push_back(v);
}
private:
bool format_enabled_;
std::vector<fblock*> fblocks_;
std::list<std::deque<value> > lines_;
struct attr_image_tag
{
nana::string path;
nana::size size;
std::size_t limited;
void reset()
{
path.clear();
size.width = size.height = 0;
limited = 0;
}
}attr_image_;
};
}//end namespace skeletons
}//end namespace widgets
}//end namepsace nana
#endif //NANA_GUI_WIDGETS_SKELETONS_TEXT_TOKEN_STREAM

View File

@@ -0,0 +1,539 @@
/*
* A textbase class implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/skeletons/textbase.hpp
* @description: This class manages the multi-line text and provides some operation on text
*/
#ifndef NANA_GUI_WIDGET_DETAIL_TEXTBASE_HPP
#define NANA_GUI_WIDGET_DETAIL_TEXTBASE_HPP
#include <nana/charset.hpp>
#include <nana/basic_types.hpp>
#include <nana/traits.hpp>
#include "textbase_export_interface.hpp"
#include <deque>
#include <memory>
#include <fstream>
#include <stdexcept>
namespace nana
{
namespace widgets
{
namespace skeletons
{
template<typename CharT>
class textbase
: public ::nana::noncopyable
{
public:
typedef CharT char_type;
typedef std::basic_string<CharT> string_type;
typedef typename string_type::size_type size_type;
textbase()
{
attr_max_.reset();
//Insert an empty string for the first line of empty text.
text_cont_.emplace_back();
}
void set_event_agent(textbase_event_agent_interface * evt)
{
evt_agent_ = evt;
}
bool empty() const
{
return (text_cont_.empty() ||
((text_cont_.size() == 1) && (text_cont_[0].empty())));
}
bool load(const nana::char_t* fs)
{
if (nullptr == fs)
return false;
std::string fs_mbs = nana::charset(fs);
std::ifstream ifs(fs_mbs.data());
if (!ifs)
return false;
ifs.seekg(0, std::ios::end);
std::size_t bytes = static_cast<std::size_t>(ifs.tellg());
ifs.seekg(0, std::ios::beg);
if(bytes >= 2)
{
int ch = ifs.get();
if(0xEF == ch && bytes >= 3)
{
//UTF8
ch = ifs.get();
if(0xBB == ch && 0xBF == ifs.get())
{
ifs.close();
return load(fs, nana::unicode::utf8);
}
}
else if(0xFF == ch)
{
if(0xFE == ifs.get())
{
//UTF16,UTF32
if(bytes >= 4)
{
if(ifs.get() == 0 && ifs.get() == 0)
{
ifs.close();
return load(fs, nana::unicode::utf32);
}
}
ifs.close();
return load(fs, nana::unicode::utf16);
}
}
else if(0xFE == ch)
{
if(ifs.get() == 0xFF)
{
//UTF16(big-endian)
ifs.close();
return load(fs, nana::unicode::utf16);
}
}
else if(0 == ch)
{
if(bytes >= 4 && ifs.get() == 0)
{
ch = ifs.get();
if(0xFE == ch && ifs.get() == 0xFF)
{
//UTF32(big_endian)
ifs.close();
return load(fs, nana::unicode::utf32);
}
}
}
}
ifs.clear();
ifs.seekg(0, std::ios::beg);
text_cont_.clear(); //Clear only if the file can be opened.
attr_max_.reset();
std::string str_mbs;
while(ifs.good())
{
std::getline(ifs, str_mbs);
text_cont_.emplace_back(nana::charset(str_mbs));
if(text_cont_.back().size() > attr_max_.size)
{
attr_max_.size = text_cont_.back().size();
attr_max_.line = text_cont_.size() - 1;
}
}
_m_saved(fs);
return true;
}
static void byte_order_translate_2bytes(std::string& str)
{
char * s = const_cast<char*>(str.c_str());
char * end = s + str.size();
for(; s < end; s += 2)
{
char c = *s;
*s = *(s + 1);
*(s + 1) = c;
}
}
static void byte_order_translate_4bytes(std::string& str)
{
char * s = const_cast<char*>(str.c_str());
char * end = s + str.size();
for(; s < end; s += 4)
{
char c = *s;
*s = *(s + 3);
*(s + 3) = c;
c = *(s + 1);
*(s + 1) = *(s + 2);
*(s + 2) = c;
}
}
bool load(const nana::char_t * fs, nana::unicode encoding)
{
if (nullptr == fs)
return false;
std::string fs_mbs = nana::charset(fs);
std::ifstream ifs(fs_mbs.data());
if (!ifs)
return false;
std::string str;
bool big_endian = true;
if(ifs.good())
{
text_cont_.clear(); //Clear only if the file can be opened.
attr_max_.reset();
std::getline(ifs, str);
std::size_t len_of_BOM = 0;
switch(encoding)
{
case nana::unicode::utf8:
len_of_BOM = 3; break;
case nana::unicode::utf16:
len_of_BOM = 2; break;
case nana::unicode::utf32:
len_of_BOM = 4; break;
default:
throw std::runtime_error("Specified a wrong UTF");
}
big_endian = (str[0] == 0x00 || str[0] == char(0xFE));
str.erase(0, len_of_BOM);
if(big_endian)
{
if(nana::unicode::utf16 == encoding)
byte_order_translate_2bytes(str);
else
byte_order_translate_4bytes(str);
}
text_cont_.emplace_back(nana::charset(str, encoding));
attr_max_.size = text_cont_.back().size();
attr_max_.line = 0;
}
while(ifs.good())
{
std::getline(ifs, str);
if(big_endian)
{
if(nana::unicode::utf16 == encoding)
byte_order_translate_2bytes(str);
else
byte_order_translate_4bytes(str);
}
text_cont_.emplace_back(nana::charset(str, encoding));
if(text_cont_.back().size() > attr_max_.size)
{
attr_max_.size = text_cont_.back().size();
attr_max_.line = text_cont_.size() - 1;
}
}
_m_saved(fs);
return true;
}
void store(nana::string fs) const
{
std::string fs_mbs = nana::charset(fs);
std::ofstream ofs(fs_mbs.data(), std::ios::binary);
if(ofs && text_cont_.size())
{
if(text_cont_.size() > 1)
{
for(auto i = text_cont_.cbegin(), end = text_cont_.cend() - 1; i != end; ++i)
{
std::string mbs = nana::charset(*i);
ofs.write(mbs.c_str(), mbs.size());
ofs.write("\r\n", 2);
}
}
std::string mbs = nana::charset(text_cont_.back());
ofs.write(mbs.c_str(), mbs.size());
_m_saved(std::move(fs));
}
}
void store(nana::string fs, nana::unicode encoding) const
{
std::string fs_mbs = nana::charset(fs);
std::ofstream ofs(fs_mbs.data(), std::ios::binary);
if(ofs && text_cont_.size())
{
const char * le_boms[] = {"\xEF\xBB\xBF", "\xFF\xFE", "\xFF\xFE\x0\x0"}; //BOM for little-endian
int bytes = 0;
switch(encoding)
{
case nana::unicode::utf8:
bytes = 3; break;
case nana::unicode::utf16:
bytes = 2; break;
case nana::unicode::utf32:
bytes = 4; break;
}
if(bytes)
ofs.write(le_boms[static_cast<int>(encoding)], bytes);
if(text_cont_.size() > 1)
{
std::string mbs;
for(auto i = text_cont_.cbegin(), end = text_cont_.cend() - 1; i != end; ++i)
{
mbs = nana::charset(*i).to_bytes(encoding);
mbs += "\r\n";
ofs.write(mbs.c_str(), static_cast<std::streamsize>(mbs.size()));
}
}
std::string mbs = nana::charset(text_cont_.back()).to_bytes(encoding);
ofs.write(mbs.c_str(), static_cast<std::streamsize>(mbs.size()));
_m_saved(std::move(fs));
}
}
size_type lines() const
{
return text_cont_.size();
}
const string_type& getline(size_type pos) const
{
if(pos < text_cont_.size())
return text_cont_[pos];
return nullstr_;
}
std::pair<size_t, size_t> max_line() const
{
return std::make_pair(attr_max_.line, attr_max_.size);
}
public:
void replace(size_type pos, string_type && text)
{
if(text_cont_.size() <= pos)
{
text_cont_.emplace_back(std::move(text));
pos = text_cont_.size() - 1;
}
else
text_cont_[pos].swap(text);
_m_make_max(pos);
_m_edited();
}
void insert(upoint pos, string_type && str)
{
if(pos.y < text_cont_.size())
{
string_type& lnstr = text_cont_[pos.y];
if(pos.x < lnstr.size())
lnstr.insert(pos.x, str);
else
lnstr += str;
}
else
{
text_cont_.emplace_back(std::move(str));
pos.y = static_cast<unsigned>(text_cont_.size() - 1);
}
_m_make_max(pos.y);
_m_edited();
}
void insertln(size_type pos, string_type&& str)
{
if(pos < text_cont_.size())
text_cont_.emplace(text_cont_.begin() + pos, std::move(str));
else
text_cont_.emplace_back(std::move(str));
_m_make_max(pos);
_m_edited();
}
void erase(size_type line, size_type pos, size_type count)
{
if (line < text_cont_.size())
{
string_type& lnstr = text_cont_[line];
if ((pos == 0) && (count >= lnstr.size()))
lnstr.clear();
else
lnstr.erase(pos, count);
if (attr_max_.line == line)
_m_scan_for_max();
_m_edited();
}
}
bool erase(size_type pos, std::size_t n)
{
//Bounds checking
if ((pos >= text_cont_.size()) || (0 == n))
return false;
if (pos + n > text_cont_.size())
n = text_cont_.size() - pos;
text_cont_.erase(text_cont_.begin() + pos, text_cont_.begin() + (pos + n));
if (pos <= attr_max_.line && attr_max_.line < pos + n)
_m_scan_for_max();
else if (pos < attr_max_.line)
attr_max_.line -= n;
_m_edited();
return true;
}
void erase_all()
{
std::deque<string_type>().swap(text_cont_);
attr_max_.reset();
_m_saved(nana::string());
}
void merge(size_type pos)
{
if(pos + 1 < text_cont_.size())
{
text_cont_[pos] += text_cont_[pos + 1];
text_cont_.erase(text_cont_.begin() + (pos + 1));
_m_make_max(pos);
if(pos < attr_max_.line)
--attr_max_.line;
_m_edited();
}
}
const nana::string& filename() const
{
return filename_;
}
bool edited() const
{
return changed_;
}
void edited_reset()
{
changed_ = false;
}
void reset()
{
filename_.clear();
changed_ = false;
}
bool saved() const
{
return ! not_saved();
}
bool not_saved() const
{
return edited() || filename_.empty();
}
private:
void _m_make_max(std::size_t pos)
{
const string_type& str = text_cont_[pos];
if(str.size() > attr_max_.size)
{
attr_max_.size = str.size();
attr_max_.line = pos;
}
}
void _m_scan_for_max()
{
attr_max_.size = 0;
std::size_t n = 0;
for(auto & s : text_cont_)
{
if(s.size() > attr_max_.size)
{
attr_max_.size = s.size();
attr_max_.line = n;
}
++n;
}
}
void _m_first_change() const
{
if (evt_agent_)
evt_agent_->first_change();
}
void _m_saved(nana::string && filename) const
{
if(filename_ != filename)
{
filename_ = std::move(filename);
_m_first_change();
}
else if(changed_)
_m_first_change();
changed_ = false;
}
void _m_edited()
{
if(!changed_)
{
_m_first_change();
changed_ = true;
}
}
private:
std::deque<string_type> text_cont_;
textbase_event_agent_interface* evt_agent_{ nullptr };
mutable bool changed_{ false };
mutable nana::string filename_; //A string for the saved filename.
const string_type nullstr_;
struct attr_max
{
std::size_t line;
std::size_t size;
void reset()
{
line = 0;
size = 0;
}
}attr_max_;
};
}//end namespace detail
}//end namespace widgets
}//end namespace nana
#endif

View File

@@ -0,0 +1,32 @@
/*
* Definitions of textbase export interfaces
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/skeletons/textbase_export_interface.hpp
* @description: It is defined outside, some headers like textbox should not include a whole textbase for its ext_evtbase
*
*/
#ifndef NANA_GUI_WIDGET_TEXTBASE_EXPORT_INTERFACE_HPP
#define NANA_GUI_WIDGET_TEXTBASE_EXPORT_INTERFACE_HPP
namespace nana{ namespace widgets
{
namespace skeletons
{
class textbase_event_agent_interface
{
public:
virtual ~textbase_event_agent_interface() = default;
virtual void first_change() = 0; ///< An event for the text first change after text has been opened or stored.
};
}//end namespace skeletons
}//end namespace widgets
}//end namespace nana
#endif //NANA_GUI_WIDGET_TEXTBASE_EXPORT_INTERFACE_HPP

View File

@@ -0,0 +1,142 @@
/*
* A Slider Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/slider.hpp
*/
#ifndef NANA_GUI_WIDGETS_SLIDER_HPP
#define NANA_GUI_WIDGETS_SLIDER_HPP
#include "widget.hpp"
#include <nana/pat/cloneable.hpp>
namespace nana
{
class slider;
struct arg_slider
{
slider & widget;
};
namespace drawerbase
{
namespace slider
{
struct slider_events
: public general_events
{
basic_event<arg_slider> value_changed;
};
enum class seekdir
{
bilateral, forward, backward
};
class provider
{
public:
virtual ~provider() = 0;
virtual nana::string adorn_trace(unsigned vmax, unsigned vadorn) const = 0;
};
class renderer
{
public:
typedef ::nana::paint::graphics & graph_reference;
struct bar_t
{
bool horizontal;
nana::rectangle r; //the rectangle of bar.
unsigned border_size; //border_size of bar.
};
struct slider_t
{
bool horizontal;
int pos;
unsigned border;
unsigned scale;
};
struct adorn_t
{
bool horizontal;
nana::point bound;
int fixedpos;
unsigned block;
unsigned vcur_scale; //pixels of vcur scale.
};
virtual ~renderer() = 0;
virtual void background(window, graph_reference, bool isglass) = 0;
virtual void adorn(window, graph_reference, const adorn_t&) = 0;
virtual void adorn_textbox(window, graph_reference, const nana::string&, const nana::rectangle&) = 0;
virtual void bar(window, graph_reference, const bar_t&) = 0;
virtual void slider(window, graph_reference, const slider_t&) = 0;
};
class controller;
class trigger
: public drawer_trigger
{
public:
typedef controller controller_t;
trigger();
~trigger();
controller_t* ctrl() const;
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void refresh(graph_reference) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void resized(graph_reference, const arg_resized&) override;
private:
controller_t * impl_;
};
}//end namespace slider
}//end namespace drawerbase
/// A slider widget wich the user can drag for tracking
class slider
: public widget_object<category::widget_tag, drawerbase::slider::trigger, drawerbase::slider::slider_events>
{
public:
typedef drawerbase::slider::renderer renderer; ///< The interface for user-defined renderer.
typedef drawerbase::slider::provider provider; ///< The interface for user-defined provider.
typedef drawerbase::slider::seekdir seekdir; ///< Defines the slider seek direction.
slider();
slider(window, bool visible);
slider(window, const rectangle& = rectangle(), bool visible = true);
void seek(seekdir); ///< Define the direction that user can seek by using mouse.
void vertical(bool);
bool vertical() const;
void vmax(unsigned);
unsigned vmax() const;
void value(unsigned);
unsigned value() const;
unsigned move_step(bool forward); ///< Increase or decrease the value of slider.
unsigned adorn() const;
pat::cloneable<renderer>& ext_renderer(); ///< Refers to the current renderer that slider is using.
void ext_renderer(const pat::cloneable<renderer>&); ///< Set the current renderer.
void ext_provider(const pat::cloneable<provider>&);
void transparent(bool);
bool transparent() const;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,332 @@
/*
* A Tabbar implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/tabbar.hpp
* @brief: A tabbar contains tab items and toolbox for scrolling, closing, selecting items.
*
*/
#ifndef NANA_GUI_WIDGET_TABBAR_HPP
#define NANA_GUI_WIDGET_TABBAR_HPP
#include "widget.hpp"
#include "../../paint/gadget.hpp"
#include <nana/pat/cloneable.hpp>
#include <nana/any.hpp>
namespace nana
{
template<typename T> class tabbar;
template<typename T>
struct arg_tabbar
{
tabbar<T> & widget;
T & value;
};
template<typename T>
struct arg_tabbar_removed : public arg_tabbar<T>
{
arg_tabbar_removed(tabbar<T>& wdg, T& v)
: arg_tabbar<T>({wdg, v})
{}
bool remove = true;
};
namespace drawerbase
{
namespace tabbar
{
template<typename T>
struct tabbar_events
: public general_events
{
typedef T value_type;
basic_event<arg_tabbar<value_type>> added;
basic_event<arg_tabbar<value_type>> activated;
basic_event<arg_tabbar<value_type>> removed;
};
class event_agent_interface
{
public:
virtual ~event_agent_interface() = 0;
virtual void added(std::size_t) = 0;
virtual void activated(std::size_t) = 0;
virtual bool removed(std::size_t) = 0;
};
class item_renderer
{
public:
typedef item_renderer item_renderer_type;
typedef nana::paint::graphics & graph_reference;
enum state_t{disable, normal, highlight, press};
struct item_t
{
nana::rectangle r;
nana::color_t bgcolor;
nana::color_t fgcolor;
};
virtual ~item_renderer() = 0;
virtual void background(graph_reference, const nana::rectangle& r, nana::color_t bgcolor) = 0;
virtual void item(graph_reference, const item_t&, bool active, state_t) = 0;
virtual void close_fly(graph_reference, const nana::rectangle&, bool active, state_t) = 0;
virtual void add(graph_reference, const nana::rectangle&, state_t) = 0;
virtual void close(graph_reference, const nana::rectangle&, state_t) = 0;
virtual void back(graph_reference, const nana::rectangle&, state_t) = 0;
virtual void next(graph_reference, const nana::rectangle&, state_t) = 0;
virtual void list(graph_reference, const nana::rectangle&, state_t) = 0;
};
template<typename T, typename DrawerTrigger>
class event_agent
: public event_agent_interface
{
public:
typedef ::nana::arg_tabbar<T> arg_tabbar;
event_agent(::nana::tabbar<T>& tb, DrawerTrigger & dtr)
: tabbar_(tb), drawer_trigger_(dtr)
{}
void added(std::size_t pos) override
{
if(pos != npos)
{
drawer_trigger_.at_no_bound_check(pos) = T();
tabbar_.events().added.emit(arg_tabbar({ tabbar_, tabbar_[pos] }));
}
}
void activated(std::size_t pos) override
{
if(pos != npos)
tabbar_.events().activated.emit(arg_tabbar({ tabbar_, tabbar_[pos]}));
}
bool removed(std::size_t pos) override
{
if (pos != npos)
{
::nana::arg_tabbar_removed<T> arg(tabbar_, tabbar_[pos]);
tabbar_.events().removed.emit(arg);
return arg.remove;
}
return true;
}
private:
::nana::tabbar<T> & tabbar_;
DrawerTrigger& drawer_trigger_;
};
class layouter;
class trigger
: public drawer_trigger
{
public:
enum toolbox_button_t{ButtonAdd, ButtonScroll, ButtonList, ButtonClose};
trigger();
~trigger();
void activate(std::size_t);
std::size_t activated() const;
nana::any& at(std::size_t) const;
nana::any& at_no_bound_check(std::size_t) const;
const pat::cloneable<item_renderer> & ext_renderer() const;
void ext_renderer(const pat::cloneable<item_renderer>&);
void set_event_agent(event_agent_interface*);
void push_back(const nana::string&, const nana::any&);
std::size_t length() const;
bool close_fly(bool);
void relate(size_t, window);
void tab_color(std::size_t, bool is_bgcolor, nana::color_t);
void tab_image(size_t, const nana::paint::image&);
void text(std::size_t, const nana::string&);
nana::string text(std::size_t) const;
bool toolbox_button(toolbox_button_t, bool);
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void refresh(graph_reference) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
private:
layouter * layouter_;
};
}
}//end namespace drawerbase
/// Analogous to dividers in a notebook or the labels in a file cabinet
template<typename Type>
class tabbar
: public widget_object<category::widget_tag, drawerbase::tabbar::trigger, drawerbase::tabbar::tabbar_events<Type>>
{
typedef drawerbase::tabbar::trigger drawer_trigger_t;
public:
typedef Type value_type; ///< The type of element data which is stored in the tabbar.
typedef drawerbase::tabbar::item_renderer item_renderer; ///< A user-defined item renderer should be derived from this interface.
struct button_add{}; ///< The type identifies the add button of the tabbar's toolbox.
struct button_scroll{}; ///< The type identifies the scroll button of the tabbar's toolbox.
struct button_list{}; ///< The type identifies the list button of the tabbar's toolbox.
struct button_close{}; ///< The type identifies the close button of the tabbar's toolbox.
/// A template class identifies the buttons of the tabbar<61>s toolbox. Refer to notes for more details.
template<typename ButtonAdd = nana::null_type, typename ButtonScroll = nana::null_type, typename ButtonList = nana::null_type, typename ButtonClose = nana::null_type>
struct button_container
{
typedef meta::fixed_type_set<ButtonAdd, ButtonScroll, ButtonList, ButtonClose> type_set;
};
tabbar()
{
evt_agent_.reset(new drawerbase::tabbar::event_agent<value_type, drawer_trigger_t>(*this, this->get_drawer_trigger()));
this->get_drawer_trigger().set_event_agent(evt_agent_.get());
}
tabbar(window wd, bool visible)
: tabbar()
{
this->create(wd, rectangle(), visible);
}
tabbar(window wd, const nana::char_t* text, bool visible)
: tabbar(wd, ::nana::string(text), visible)
{
}
tabbar(window wd, const nana::string& text, bool visible)
: tabbar()
{
this->create(wd, rectangle(), visible);
this->caption(text);
}
tabbar(window wd, const rectangle& r = rectangle(), bool visible = true)
: tabbar()
{
this->create(wd, r, visible);
}
~tabbar()
{
this->get_drawer_trigger().set_event_agent(nullptr);
}
value_type & operator[](std::size_t pos) const
{
return static_cast<value_type&>(this->get_drawer_trigger().at_no_bound_check(pos));
}
void activate(std::size_t pos) /// Activates a tab specified by i.
{
this->get_drawer_trigger().activate(pos);
}
std::size_t activated() const
{
return this->get_drawer_trigger().activated();
}
value_type & at(std::size_t i) const /// Returns i'th element
{
return static_cast<value_type&>(this->get_drawer_trigger().at(i));
}
void close_fly(bool fly) /// Draw or not a close button in each tab.
{
if(this->get_drawer_trigger().close_fly(fly))
API::refresh_window(this->handle());
}
pat::cloneable<item_renderer>& ext_renderer() const
{
return this->get_drawer_trigger().ext_renderer();
}
void ext_renderer(const pat::cloneable<item_renderer>& ir)
{
this->get_drawer_trigger().ext_renderer(ir);
}
std::size_t length() const /// Returns the number of items.
{
return this->get_drawer_trigger().length();
}
void push_back(const nana::string& text) /// Append a new item.
{
auto & t = this->get_drawer_trigger();
t.push_back(text, value_type());
API::update_window(*this);
}
void relate(std::size_t pos, window wd) /// Binds a window to an item specified by pos, if the item is selected, shows the window, otherwise, hides it.
{
this->get_drawer_trigger().relate(pos, wd);
}
void tab_bgcolor(std::size_t i, nana::color_t color)
{
this->get_drawer_trigger().tab_color(i, true, color);
}
void tab_fgcolor(std::size_t i, nana::color_t color)
{
this->get_drawer_trigger().tab_color(i, false, color);
}
void tab_image(std::size_t i, const nana::paint::image& img)
{
this->get_drawer_trigger().tab_image(i, img);
}
/// Sets buttons of the tabbar's toolbox, refer to notes for more details.
template<typename Add, typename Scroll, typename List, typename Close>
void toolbox(const button_container<Add, Scroll, List, Close>&, bool enable)
{
typedef typename button_container<Add, Scroll, List, Close>::type_set type_set;
auto & tg = this->get_drawer_trigger();
bool redraw = false;
if(type_set::template count<button_add>::value)
redraw |= tg.toolbox_button(tg.ButtonAdd, enable);
if(type_set::template count<button_scroll>::value)
redraw |= tg.toolbox_button(tg.ButtonScroll, enable);
if(type_set::template count<button_list>::value)
redraw |= tg.toolbox_button(tg.ButtonList, enable);
if(type_set::template count<button_close>::value)
redraw |= tg.toolbox_button(tg.ButtonClose, enable);
if(redraw)
API::refresh_window(this->handle());
}
void text(std::size_t pos, const nana::string& str) /// Sets the title of the specified item, If pos is invalid, the method throws an std::out_of_range object.
{
this->get_drawer_trigger().text(pos, str);
}
nana::string text(std::size_t pos) const /// Returns a title of a specified item, If pos is invalid, the method trhows a std::out_of_range object.
{
return this->get_drawer_trigger().text(pos);
}
private:
std::unique_ptr<drawerbase::tabbar::event_agent<value_type, drawerbase::tabbar::trigger> > evt_agent_;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,189 @@
/*
* A Textbox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/textbox.hpp
*/
#ifndef NANA_GUI_WIDGET_TEXTBOX_HPP
#define NANA_GUI_WIDGET_TEXTBOX_HPP
#include <nana/gui/widgets/widget.hpp>
#include "skeletons/textbase_export_interface.hpp"
namespace nana
{
class textbox;
struct arg_textbox
{
textbox& widget;
};
namespace widgets
{
namespace skeletons
{
class text_editor;
}
}
namespace drawerbase
{
namespace textbox
{
struct textbox_events
: public general_events
{
basic_event<arg_textbox> first_change;
};
class event_agent
: public widgets::skeletons::textbase_event_agent_interface
{
public:
event_agent(::nana::textbox& wdg);
void first_change() override;
private:
::nana::textbox & widget_;
};
//class drawer
class drawer
: public drawer_trigger
{
public:
typedef widgets::skeletons::text_editor text_editor;
drawer();
text_editor * editor();
const text_editor * editor() const;
void set_accept(std::function<bool(nana::char_t)> &&);
private:
void attached(widget_reference, graph_reference) override;
void detached() override;
void refresh(graph_reference) override;
void focus(graph_reference, const arg_focus&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_enter(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void key_press(graph_reference, const arg_keyboard&)override;
void key_char(graph_reference, const arg_keyboard&) override;
void mouse_wheel(graph_reference, const arg_wheel&) override;
void resized(graph_reference, const arg_resized&) override;
void typeface_changed(graph_reference) override;
private:
void _m_text_area(unsigned width, unsigned height);
void _m_draw_border(graph_reference, nana::color_t bgcolor);
private:
widget* widget_;
struct status_type
{
bool has_focus; //Indicates whether it has the keyboard focus
}status_;
std::function<bool(nana::char_t)> pred_acceptive_;
widgets::skeletons::text_editor * editor_;
std::unique_ptr<event_agent> evt_agent_;
};
}//end namespace textbox
}//end namespace drawerbase
/// Allow users to enter and edit text by typing on the keyboard.
class textbox
:public widget_object<category::widget_tag, drawerbase::textbox::drawer, drawerbase::textbox::textbox_events>
{
public:
/// The default constructor without creating the widget.
textbox();
/// \brief The construct that creates a widget.
/// @param wd A handle to the parent window of the widget being created.
/// @param visible specifying the visible after creating.
textbox(window, bool visible);
/// \brief The construct that creates a widget with a specified text.
/// @param window A handle to the parent window of the widget being created.
/// @param text the text that will be displayed.
/// @param visible specifying the visible after creating.
textbox(window, const nana::string& text, bool visible = true);
/// \brief The construct that creates a widget with a specified text.
/// @param window A handle to the parent window of the widget being created.
/// @param text the text that will be displayed.
/// @param visible specifying the visible after creating.
textbox(window, const nana::char_t* text, bool visible = true);
/// \brief The construct that creates a widget.
/// @param window A handle to the parent window of the widget being created.
/// @param rectangle the size and position of the widget in its parent window coordinate.
/// @param visible specifying the visible after creating.
textbox(window, const rectangle& = rectangle(), bool visible = true);
/// \brief Loads a text file. When attempt to load a unicode encoded text file, be sure the file have a BOM header.
void load(nana::string file);
void store(nana::string file);
void store(nana::string file, nana::unicode encoding);
textbox& reset(nana::string = {}); ///< discard the old text and set a newtext
/// The file of last store operation.
nana::string filename() const;
/// Determine whether the text was edited.
bool edited() const;
/// Reset the edited flag to false manually
textbox& edited_reset();
/// Determine whether the changed text has been saved into the file.
bool saved() const;
/// Read the text from a specified line. It returns true for success.
bool getline(std::size_t line_index, nana::string&) const;
/// Appends an string. If `at_caret` is `true`, the string is inserted at the position of caret, otherwise, it is appended at end of the textbox.
textbox& append(const nana::string& text, bool at_caret);
/// Determine wheter the text is line wrapped.
bool line_wrapped() const;
textbox& line_wrapped(bool);
/// Determine whether the text is multi-line enabled.
bool multi_lines() const;
textbox& multi_lines(bool);
bool editable() const;
textbox& editable(bool);
void set_accept(std::function<bool(nana::char_t)>);
textbox& tip_string(nana::string);
/// Set a mask character. Text is displayed as mask character if a mask character is set. This is used for hiding some special text, such as password.
textbox& mask(nana::char_t);
/// Returns true if some text is selected.
bool selected() const;
/// Selects/unselects all text.
void select(bool);
void copy() const; ///< Copies the selected text into shared memory, such as clipboard under Windows.
void paste(); ///< Pastes the text from shared memory.
void del();
int to_int() const;
double to_double() const;
textbox& from(int);
textbox& from(double);
protected:
//Overrides widget's virtual functions
::nana::string _m_caption() const override;
void _m_caption(::nana::string&&) override;
void _m_typeface(const paint::font&) override;
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,102 @@
/*
* A Toolbar Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/toolbar.hpp
*/
#ifndef NANA_GUI_WIDGET_TOOLBAR_HPP
#define NANA_GUI_WIDGET_TOOLBAR_HPP
#include "widget.hpp"
#include <vector>
namespace nana
{
class toolbar;
struct arg_toolbar
{
toolbar& widget;
std::size_t button;
};
namespace drawerbase
{
namespace toolbar
{
struct toolbar_events
: public general_events
{
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 drawer
: public drawer_trigger
{
struct drawer_impl_type;
public:
typedef std::size_t size_type;
drawer();
~drawer();
void append(const nana::string&, const nana::paint::image&);
void append();
bool enable(size_type) const;
bool enable(size_type, bool);
void scale(unsigned);
private:
void refresh(graph_reference) override;
void attached(widget_reference, graph_reference) override;
void detached() override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
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(nana::color_t);
void _m_draw();
void _m_owner_sized(const arg_resized&);
private:
void _m_fill_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.
toolbar();
toolbar(window, bool visible);
toolbar(window, const rectangle& = rectangle(), bool visible = true);
void append(); ///< 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;
void enable(size_type index, bool enable_state);
void scale(unsigned s); ///< Sets the scale of control button.
};
}//end namespace nana
#endif

View File

@@ -0,0 +1,440 @@
/*
* A Tree Box Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/treebox.hpp
* @brief:
* The treebox organizes the nodes by a key string.
* The treebox would have a vertical scrollbar if the node
* is too many to display. And it does not have a horizontal scrollbar,
* the widget will adjust the node's displaying position for fitting.
*/
#ifndef NANA_GUI_WIDGETS_TREEBOX_HPP
#define NANA_GUI_WIDGETS_TREEBOX_HPP
#include "widget.hpp"
#include "detail/compset.hpp"
#include <nana/paint/gadget.hpp>
#include "detail/tree_cont.hpp"
#include <nana/gui/timer.hpp>
#include <nana/any.hpp>
#include <nana/pat/cloneable.hpp>
#include <stdexcept>
namespace nana
{
class treebox;
namespace drawerbase
{
namespace treebox
{
enum class component
{
begin, expender = begin, crook, icon, text, bground, end
};
struct node_image_tag
{
nana::paint::image normal;
nana::paint::image hovered;
nana::paint::image expanded;
};
struct node_attribute
{
bool has_children;
bool expended;
checkstate checked;
bool selected;
bool mouse_pointed;
nana::paint::image icon_normal;
nana::paint::image icon_hover;
nana::paint::image icon_expanded;
nana::string text;
};
typedef widgets::detail::compset<component, node_attribute> compset_interface;
typedef widgets::detail::compset_placer<component, node_attribute> compset_placer_interface;
class renderer_interface
{
public:
typedef drawerbase::treebox::component component;
typedef ::nana::paint::graphics& graph_reference;
typedef drawerbase::treebox::compset_interface compset_interface;
typedef compset_interface::item_attribute_t item_attribute_t;
typedef compset_interface::comp_attribute_t comp_attribute_t;
virtual ~renderer_interface()
{}
virtual void bground(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const compset_interface *) const = 0;
virtual void expander(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const compset_interface *) const = 0;
virtual void crook(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const compset_interface *) const = 0;
virtual void icon(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const compset_interface *) const = 0;
virtual void text(graph_reference, nana::color_t bgcolor, nana::color_t fgcolor, const compset_interface *) const = 0;
};
class item_proxy;
class trigger
:public drawer_trigger
{
template<typename Renderer>
struct basic_implement;
class item_renderer;
class item_locator;
typedef basic_implement<item_renderer> implement;
public:
struct treebox_node_type
{
treebox_node_type();
treebox_node_type(nana::string);
treebox_node_type& operator=(const treebox_node_type&);
nana::string text;
nana::any value;
bool expanded;
checkstate checked;
nana::string img_idstr;
};
struct pseudo_node_type{};
typedef widgets::detail::tree_cont<treebox_node_type> tree_cont_type;
typedef tree_cont_type::node_type node_type;
trigger();
~trigger();
implement * impl() const;
void auto_draw(bool);
void checkable(bool);
bool checkable() const;
void check(node_type*, checkstate);
bool draw();
const tree_cont_type & tree() const;
tree_cont_type & tree();
void renderer(::nana::pat::cloneable<renderer_interface>&&);
const ::nana::pat::cloneable<renderer_interface>& renderer() const;
void placer(::nana::pat::cloneable<compset_placer_interface>&&);
const ::nana::pat::cloneable<compset_placer_interface>& placer() const;
nana::any & value(node_type*) const;
node_type* insert(node_type*, const nana::string& key, nana::string&&);
node_type* insert(const nana::string& path, nana::string&&);
bool verify(const void*) const;
bool verify_kinship(node_type* parent, node_type* child) const;
void remove(node_type*);
node_type * selected() const;
void selected(node_type*);
void set_expand(node_type*, bool);
void set_expand(const nana::string& path, bool);
//void image(const nana::string& id, const node_image_tag&);
node_image_tag& icon(const nana::string&) const;
void icon_erase(const nana::string&);
void node_icon(node_type*, const nana::string& id);
unsigned node_width(const node_type*) const;
bool rename(node_type*, const nana::char_t* key, const nana::char_t* name);
private:
//Overrides drawer_trigger methods
void attached(widget_reference, graph_reference) override;
void refresh(graph_reference) override;
void dbl_click(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_wheel(graph_reference, const arg_wheel&) override;
void mouse_leave(graph_reference, const arg_mouse&) override;
void resized(graph_reference, const arg_resized&) override;
void key_press(graph_reference, const arg_keyboard&) override;
void key_char(graph_reference, const arg_keyboard&) override;
private:
void _m_deal_adjust();
private:
implement * const impl_;
}; //end class trigger
/// \brief A proxy for accessing the node. The key string is case sensitive.
class item_proxy
: public std::iterator<std::input_iterator_tag, item_proxy>
{
public:
item_proxy() = default; ///< The default constructor creates an end iterator.
//Undocumented constructor.
item_proxy(trigger*, trigger::node_type*);
/// Append a child.
item_proxy append(const nana::string& key, nana::string name);
/// Append a child with a specified value (user object.).
template<typename T>
item_proxy append(const nana::string& key, nana::string name, const T&t)
{
item_proxy ip = append(key, std::move(name));
if(false == ip.empty())
ip.value(t);
return ip;
}
/// Return true if the proxy does not refer to a node, as an end iterator.
bool empty() const;
/// \brief Return the distance between the ROOT node and this node.
/// @return only available when emtpy() is false.
std::size_t level() const;
/// Return the check state
bool checked() const;
/// Set the check state, and it returns itself.
item_proxy& check(bool);
/// Return true when the node is expanded \todo change to expanded ??
bool expanded() const;
/// Expand/Shrink children of the node, and returns itself. \todo change to expand ??
item_proxy& expand(bool);
/// Return true when the node is selected.
bool selected() const;
/// Select the node, and returns itself..
item_proxy& select(bool);
/// Return the icon.
const nana::string& icon() const;
/// Set the icon, and returns itself..
item_proxy& icon(const nana::string& id);
/// Return the text.
const nana::string& text() const;
/// Set a new key, and returns itself..
item_proxy& key(const nana::string& s);
/// Return the key.
const nana::string& key() const;
/// Set the text, and returns itself.
item_proxy& text(const nana::string&);
std::size_t size() const; ///< Returns the number of child nodes.
/// Return the first child of the node.
item_proxy child() const;
/// Return the owner of the node.
item_proxy owner() const;
/// Return the sibling of the node.
item_proxy sibling() const;
/// Return the first child of the node
item_proxy begin() const;
/// An end node.
item_proxy end() const;
/// Makes an action for each sub item recursively, returns the item that stops the action where action returns false.
item_proxy visit_recursively(std::function<bool(item_proxy)> action);
bool operator==(const nana::string& s) const; ///< Compare the text of node with s.
bool operator==(const char* s ) const; ///< Compare the text of node with s.
bool operator==(const wchar_t* s ) const; ///< Compare the text of node with s.
/// Behavior of Iterator
item_proxy& operator=(const item_proxy&);
/// Behavior of Iterator
item_proxy & operator++();
/// Behavior of Iterator
item_proxy operator++(int);
/// Behavior of Iterator
item_proxy& operator*();
/// Behavior of Iterator
const item_proxy& operator*() const;
/// Behavior of Iterator
item_proxy* operator->();
/// Behavior of Iterator
const item_proxy* operator->() const;
/// Behavior of Iterator
bool operator==(const item_proxy&) const;
/// Behavior of Iterator
bool operator!=(const item_proxy&) const;
template<typename T>
T * value_ptr() const
{
return _m_value().get<T>();
}
template<typename T>
T& value() const
{
T* p = _m_value().get<T>();
if(nullptr == p)
throw std::runtime_error("treebox::value<T>() Invalid type of value.");
return *p;
}
template<typename T>
item_proxy & value(const T& t)
{
_m_value() = t;
return *this;
};
template<typename T>
item_proxy & value(T&& t)
{
_m_value() = std::move(t);
return *this;
};
// Undocumentated methods for internal use
trigger::node_type * _m_node() const;
private:
nana::any& _m_value();
const nana::any& _m_value() const;
private:
trigger * trigger_{nullptr};
trigger::node_type * node_{nullptr};
};//end class item_proxy
}//end namespace treebox
}//end namespace drawerbase
struct arg_treebox
{
treebox& widget;
drawerbase::treebox::item_proxy & item;
bool operated;
};
namespace drawerbase
{
namespace treebox
{
struct treebox_events
: public general_events
{
basic_event<arg_treebox> expanded;
basic_event<arg_treebox> checked;
basic_event<arg_treebox> selected;
basic_event<arg_treebox> hovered;
};
}//end namespace treebox
}//end namespace drawerbase
/// Displays a hierarchical list of items, such as the files and directories on a disk.
class treebox
:public widget_object < category::widget_tag, drawerbase::treebox::trigger, drawerbase::treebox::treebox_events>
{
public:
/// A type refers to the item and also used to iterate through the node.
typedef drawerbase::treebox::item_proxy item_proxy;
typedef drawerbase::treebox::node_image_tag node_image_type;
/// The interface of treebox item renderer
typedef drawerbase::treebox::renderer_interface renderer_interface;
/// The interface of treebox compset_placer
typedef drawerbase::treebox::compset_placer_interface compset_placer_interface;
/// The default constructor without creating the widget.
treebox();
/// \brief The construct that creates a widget.
/// @param wd A handle to the parent window of the widget being created.
/// @param visible specifying the visible after creating.
treebox(window wd, bool visible);
/// \brief The construct that creates a widget.
/// @param wd A handle to the parent window of the widget being created.
/// @param r the size and position of the widget in its parent window coordinate.
/// @param visible specifying the visible after creating.
treebox(window, const nana::rectangle& = rectangle(), bool visible = true);
template<typename ItemRenderer>
treebox & renderer(const ItemRenderer & rd)
{
get_drawer_trigger().renderer(::nana::pat::cloneable<renderer_interface>(rd));
return *this;
}
const nana::pat::cloneable<renderer_interface> & renderer() const;
template<typename Placer>
treebox & placer(const Placer & r)
{
get_drawer_trigger().placer(::nana::pat::cloneable<compset_placer_interface>(r));
return *this;
}
const nana::pat::cloneable<compset_placer_interface> & placer() const;
/// \brief Eanble the widget to be draws automatically when it is operated.
/// @param bool whether to enable.
void auto_draw(bool);
/// \brief Enable the checkbox for each item of the widget.
/// @param bool wheter to enable.
treebox & checkable(bool enable);
/// Determinte whether the checkbox is enabled.
bool checkable() const;
treebox& icon(const nana::string& id, const node_image_type& node_img);
node_image_type& icon(const nana::string& id) const;
void icon_erase(const nana::string& id);
item_proxy find(const nana::string& keypath); ///< Find an item though a specified keypath.
/// Inserts a new node to treebox, but if the keypath exists returns the existing node.
item_proxy insert(const nana::string& path_key, ///< specifies the node hierarchical
nana::string title ///< used for displaying
);
/// Inserts a new node to treebox, but if the keypath exists returns the existing node.
item_proxy insert( item_proxy pos, ///< the parent item node
const nana::string& key, ///< specifies the new node
nana::string title ///< used for displaying.
);
item_proxy erase(item_proxy i);
void erase(const nana::string& keypath);
nana::string make_key_path(item_proxy i, const nana::string& splitter) const;///<returns the key path
item_proxy selected() const;
};//end class treebox
}//end namespace nana
#endif

View File

@@ -0,0 +1,499 @@
/*
* The fundamental widget class implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/gui/widgets/widget.hpp
*/
#ifndef NANA_GUI_WIDGET_HPP
#define NANA_GUI_WIDGET_HPP
#include <nana/traits.hpp>
#include "../basis.hpp"
#include "../programming_interface.hpp"
#include <nana/internationalization.hpp>
#include <nana/gui/detail/drawer.hpp>
#include <nana/gui/layout_utility.hpp>
#include <functional>
namespace nana
{
class drawer_trigger;
/// Abstract class for defining the capacity interface.
class widget
: nana::noncopyable, nana::nonmovable
{
typedef void(*dummy_bool_type)(widget* (*)(const widget&));
public:
virtual ~widget();
virtual window handle() const = 0; ///< Returns the handle of window, returns 0 if window is not created.
bool empty() const; ///< Determines whether the manipulator is handling a window.
void close();
window parent() const;
nana::string caption() const;
void caption(nana::string);
template<typename ...Args>
void i18n(std::string msgid, Args&&... args)
{
_m_caption(nana::internationalization().get(msgid, std::forward<Args>(args)...));
}
void i18n(i18n_eval);
void cursor(nana::cursor);
nana::cursor cursor() const; ///< Retrieves the shape of cursor
void typeface(const paint::font& font);
paint::font typeface() const;
bool enabled() const; ///< Determines whether the window is enabled for mouse and keyboard input.
void enabled(bool);
void enable_dropfiles(bool); ///< Enables/Disables a window to accept dropped files.
void focus();
bool focused() const;
void show(); ///< Sets the window visible.
void hide(); ///< Sets the window invisible.
bool visible() const;
nana::size size() const;
void size(const nana::size&);
point pos() const;
void move(int x, int y);
void move(const rectangle&);
void foreground(nana::color_t);
nana::color_t foreground() const;
void background(nana::color_t);
nana::color_t background() const;
general_events& events() const;
void umake_event(event_handle eh) const; ///< Deletes an event callback by a handle.
widget& tooltip(const nana::string&);
operator dummy_bool_type() const;
operator window() const;
protected:
//protected members, a derived class must call this implementation if it overrides an implementation
virtual void _m_complete_creation();
virtual general_events& _m_get_general_events() const = 0;
virtual nana::string _m_caption() const;
virtual void _m_caption(nana::string&&);
virtual nana::cursor _m_cursor() const;
virtual void _m_cursor(nana::cursor);
virtual void _m_close();
virtual bool _m_enabled() const;
virtual void _m_enabled(bool);
virtual bool _m_show(bool);
virtual bool _m_visible() const;
virtual void _m_size(const nana::size&);
virtual void _m_move(int x, int y);
virtual void _m_move(const rectangle&);
virtual void _m_typeface(const nana::paint::font& font);
virtual nana::paint::font _m_typeface() const;
virtual void _m_foreground(nana::color_t);
virtual nana::color_t _m_foreground() const;
virtual void _m_background(nana::color_t);
virtual nana::color_t _m_background() const;
};
/// Base class of all the classes defined as a widget window. Defaultly a widget_tag
template<typename Category, typename DrawerTrigger, typename Events = nana::general_events>
class widget_object: public widget
{
protected:
typedef DrawerTrigger drawer_trigger_t;
public:
widget_object()
: events_(std::make_shared<Events>())
{}
~widget_object()
{
if(handle_)
API::close_window(handle_);
}
Events& events() const
{
return *events_;
}
bool create(window parent_wd, bool visible) ///< Creates a no-size (zero-size) widget. in a widget/root window specified by parent_wd.
{
return create(parent_wd, rectangle(), visible);
}
bool create(window parent_wd, const rectangle & r = rectangle(), bool visible = true) ///< in a widget/root window specified by parent_wd.
{
if(parent_wd && this->empty())
{
handle_ = API::dev::create_widget(parent_wd, r, this);
API::dev::set_events(handle_, events_);
API::dev::attach_signal(handle_, *this, &widget_object::signal);
API::dev::attach_drawer(*this, trigger_);
if(visible)
API::show_window(handle_, true);
this->_m_complete_creation();
}
return (this->empty() == false);
}
window handle() const override
{
return handle_;
}
widget_object& borderless(bool enable)
{
API::widget_borderless(handle_, enable);
return *this;
}
bool borderless() const
{
return API::widget_borderless(handle_);
}
protected:
DrawerTrigger& get_drawer_trigger()
{
return trigger_;
}
const DrawerTrigger& get_drawer_trigger() const
{
return trigger_;
}
private:
void signal(detail::signals::code code, const detail::signals& sig)
{
typedef detail::signals::code codes;
switch(code)
{
case codes::caption:
this->_m_caption(sig.info.caption);
break;
case codes::read_caption:
*sig.info.str = this->_m_caption();
break;
case codes::destroy:
handle_ = nullptr;
break;
default:
break;
}
}
general_events& _m_get_general_events() const
{
return *events_;
}
private:
window handle_{nullptr};
DrawerTrigger trigger_;
std::shared_ptr<Events> events_;
};//end class widget_object
/// Base class of all the classes defined as a non-graphics-buffer widget window. The second template parameter DrawerTrigger is always ignored.\see nana::panel
template<typename DrawerTrigger, typename Events>
class widget_object<category::lite_widget_tag, DrawerTrigger, Events>: public widget
{
protected:
typedef DrawerTrigger drawer_trigger_t;
public:
widget_object()
: events_(std::make_shared<Events>())
{}
~widget_object()
{
if(handle_)
API::close_window(handle_);
}
Events& events() const
{
return *events_;
}
bool create(window parent_wd, bool visible) ///< Creates a no-size (zero-size) widget. in a widget/root window specified by parent_wd.
{
return create(parent_wd, rectangle(), visible);
}
bool create(window parent_wd, const rectangle& r = rectangle(), bool visible = true) ///< in a widget/root window specified by parent_wd.
{
if(parent_wd && this->empty())
{
handle_ = API::dev::create_lite_widget(parent_wd, r, this);
API::dev::set_events(handle_, events_);
if(visible)
API::show_window(handle_, true);
this->_m_complete_creation();
}
return (this->empty() == false);
}
window handle() const
{
return handle_;
}
private:
void signal(detail::signals::code code, const detail::signals& sig)
{
typedef detail::signals::code codes;
switch(code)
{
case codes::caption:
this->_m_caption(sig.info.caption);
break;
case codes::read_caption:
*sig.info.str = this->_m_caption();
break;
case codes::destroy:
handle_ = nullptr;
break;
default:
break;
}
}
general_events& _m_get_general_events() const
{
return *events_;
}
private:
window handle_{nullptr};
std::shared_ptr<Events> events_;
};//end class widget_object
/// Base class of all the classes defined as a root window. \see nana::form
template<typename DrawerTrigger, typename Events>
class widget_object<category::root_tag, DrawerTrigger, Events>: public widget
{
protected:
typedef DrawerTrigger drawer_trigger_t;
public:
widget_object()
{
handle_ = API::dev::create_window(nullptr, false, API::make_center(300, 150), appearance(), this);
_m_bind_and_attach();
}
widget_object(const rectangle& r, const appearance& apr = appearance())
{
handle_ = API::dev::create_window(nullptr, false, r, apr, this);
_m_bind_and_attach();
}
widget_object(window owner, bool nested, const rectangle& r = rectangle(), const appearance& apr = appearance())
{
handle_ = API::dev::create_window(owner, nested, r, apr, this);
_m_bind_and_attach();
}
~widget_object()
{
if(handle_)
API::close_window(handle_);
}
Events& events() const
{
return *events_;
}
void activate()
{
API::activate_window(handle_);
}
void bring_to_top()
{
API::bring_to_top(handle_);
}
window handle() const
{
return handle_;
}
native_window_type native_handle() const
{
return API::root(handle_);
}
window owner() const
{
return API::get_owner_window(handle_);
}
void icon(const nana::paint::image& ico)
{
API::window_icon(handle_, ico);
}
void restore()
{
API::restore_window(handle_);
}
void zoom(bool ask_for_max)
{
API::zoom_window(handle_, ask_for_max);
}
bool is_zoomed(bool ask_for_max) const
{
return API::is_window_zoomed(handle_, ask_for_max);
}
protected:
DrawerTrigger& get_drawer_trigger()
{
return trigger_;
}
const DrawerTrigger& get_drawer_trigger() const
{
return trigger_;
}
private:
void signal(detail::signals::code code, const detail::signals& sig)
{
typedef detail::signals::code codes;
switch(code)
{
case codes::caption:
this->_m_caption(sig.info.caption);
break;
case codes::read_caption:
*sig.info.str = this->_m_caption();
break;
case codes::destroy:
handle_ = nullptr;
break;
default:
break;
}
}
void _m_bind_and_attach()
{
events_ = std::make_shared<Events>();
API::dev::set_events(handle_, events_);
API::dev::attach_signal(handle_, *this, &widget_object::signal);
API::dev::attach_drawer(*this, trigger_);
}
general_events& _m_get_general_events() const
{
return *events_;
}
private:
window handle_;
DrawerTrigger trigger_;
std::shared_ptr<Events> events_;
};//end class widget_object<root_tag>
/// Base class of all the classes defined as a frame window. \see nana::frame
template<typename Drawer, typename Events>
class widget_object<category::frame_tag, Drawer, Events>: public widget{};
/// Especialization. Base class of all the classes defined as a frame window. \see nana::frame
template<typename Events>
class widget_object<category::frame_tag, int, Events>: public widget
{
protected:
typedef int drawer_trigger_t;
public:
widget_object()
: events_(std::make_shared<Events>())
{}
~widget_object()
{
if(handle_)
API::close_window(handle_);
}
Events& events() const
{
return *events_;
}
bool create(window parent_wd, bool visible) ///< Creates a no-size (zero-size) widget. in a widget/root window specified by parent_wd.
{
return create(parent_wd, rectangle(), visible);
}
/// Creates in a widget/root window specified by parent_wd.
bool create(window parent_wd, const rectangle& r = rectangle(), bool visible = true)
{
if(parent_wd && this->empty())
{
handle_ = API::dev::create_frame(parent_wd, r, this);
API::dev::set_events(handle_, events_);
API::dev::attach_signal(handle_, *this, &widget_object::signal);
API::show_window(handle_, visible);
this->_m_complete_creation();
}
return (this->empty() == false);
}
window handle() const
{
return handle_;
}
private:
virtual drawer_trigger* get_drawer_trigger()
{
return nullptr;
}
void signal(detail::signals::code code, const detail::signals& sig)
{
typedef detail::signals::code codes;
switch(code)
{
case codes::caption:
this->_m_caption(sig.info.caption);
break;
case codes::read_caption:
*sig.info.str = this->_m_caption();
break;
case codes::destroy:
handle_ = nullptr;
break;
default:
break;
}
}
general_events& _m_get_general_events() const
{
return *events_;
}
private:
window handle_{nullptr};
std::shared_ptr<Events> events_;
};//end class widget_object<category::frame_tag>
}//end namespace nana
#endif

45
include/nana/gui/wvl.hpp Normal file
View File

@@ -0,0 +1,45 @@
/*
* Nana GUI Library Definition
* Copyright(C) 2003-2013 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: nana/gui/wvl.hpp
* @description:
* the header file contains the files required for running of Nana.GUI
*/
#ifndef NANA_GUI_WVL_HPP
#define NANA_GUI_WVL_HPP
#include "programming_interface.hpp"
#include "widgets/form.hpp"
#include "drawing.hpp"
#include "msgbox.hpp"
#include "../exceptions.hpp"
namespace nana
{
template<typename Form, bool IsMakeVisible = true>
class form_loader
{
public:
template<typename... Args>
Form & operator()(Args &&... args) const
{
Form* res = detail::bedrock::instance().rt_manager.create_form<Form>(std::forward<Args>(args)...);
if (nullptr == res)
throw nana::bad_window("form_loader.operator(): failed to create a window");
if (IsMakeVisible) res->show();
return *res;
}
};
void exec();
}//end namespace nana
#endif

View File

@@ -0,0 +1,211 @@
/*
* An Implementation of i18n
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/internationalization.hpp
*/
#ifndef NANA_INTERNATIONALIZATION_HPP
#define NANA_INTERNATIONALIZATION_HPP
#include "basic_types.hpp"
#include <vector>
#include <sstream>
#include <functional>
#include <memory>
namespace nana
{
class internationalization
{
friend class i18n_eval;
public:
void load(const std::string& file);
void load_utf8(const std::string& file);
template<typename ...Args>
nana::string get(std::string msgid_utf8, Args&&... args) const
{
std::vector<nana::string> arg_strs;
_m_fetch_args(arg_strs, std::forward<Args>(args)...);
nana::string msgstr;
if (_m_get(msgid_utf8, msgstr))
_m_replace_args(msgstr, &arg_strs);
return msgstr;
}
nana::string get(std::string msgid_utf8) const;
void set(std::string msgid_utf8, nana::string msgstr);
template<typename ...Args>
nana::string operator()(std::string msgid_utf8, Args&&... args) const
{
return get(msgid_utf8, std::forward<Args>(args)...);
}
private:
bool _m_get(std::string& msgid, nana::string& msgstr) const;
void _m_replace_args(nana::string& str, std::vector<nana::string> * arg_strs) const;
void _m_fetch_args(std::vector<nana::string>&) const //Termination of _m_fetch_args
{}
template<typename Arg>
void _m_fetch_args(std::vector<nana::string>& v, Arg&& arg) const
{
std::wstringstream ss;
ss << arg;
v.emplace_back(ss.str());
}
template<typename ...Args>
void _m_fetch_args(std::vector<nana::string>& v, const char* arg, Args&&... args) const
{
std::wstringstream ss;
ss << nana::string(nana::charset(arg));
v.emplace_back(ss.str());
_m_fetch_args(v, std::forward<Args>(args)...);
}
template<typename ...Args>
void _m_fetch_args(std::vector<nana::string>& v, const std::string& arg, Args&&... args) const
{
std::wstringstream ss;
ss << nana::string(nana::charset(arg));
v.emplace_back(ss.str());
_m_fetch_args(v, std::forward<Args>(args)...);
}
template<typename ...Args>
void _m_fetch_args(std::vector<nana::string>& v, std::string& arg, Args&&... args) const
{
std::wstringstream ss;
ss << nana::string(nana::charset(arg));
v.emplace_back(ss.str());
_m_fetch_args(v, std::forward<Args>(args)...);
}
template<typename ...Args>
void _m_fetch_args(std::vector<nana::string>& v, std::string&& arg, Args&&... args) const
{
std::wstringstream ss;
ss << nana::string(nana::charset(arg));
v.emplace_back(ss.str());
_m_fetch_args(v, std::forward<Args>(args)...);
}
template<typename Arg, typename ...Args>
void _m_fetch_args(std::vector<nana::string>& v, Arg&& arg, Args&&... args) const
{
std::wstringstream ss;
ss << arg;
v.emplace_back(ss.str());
_m_fetch_args(v, std::forward<Args>(args)...);
}
};//end class internationalization
class i18n_eval
{
class eval_arg
{
public:
virtual ~eval_arg() = default;
virtual nana::string eval() const = 0;
virtual std::unique_ptr<eval_arg> clone() const = 0;
};
class arg_string;
class arg_eval;
template<typename Return>
class arg_function
{
public:
arg_function(std::function<Return()> fn)
: fn_(fn)
{}
nana::string eval() const override
{
std::wstringstream ss;
ss << fn_();
return ss.str();
}
std::unique_ptr<eval_arg> clone() const override
{
return std::unique_ptr<eval_arg>(new arg_function(*this));
}
private:
std::function<Return()> fn_;
};
public:
i18n_eval() = default;
template<typename ...Args>
i18n_eval(std::string msgid_utf8, Args&&... args)
: msgid_(std::move(msgid_utf8))
{
_m_fetch_args(std::forward<Args>(args)...);
}
i18n_eval(const i18n_eval&);
//Workaround for VC2013, becuase it can't specified a default explicit move-constructor
i18n_eval(i18n_eval&&); //= default
i18n_eval& operator=(const i18n_eval&);
i18n_eval& operator=(i18n_eval&& rhs);
nana::string operator()() const;
private:
void _m_fetch_args(){} //Termination of _m_fetch_args
template<typename Arg, typename ...Args>
void _m_fetch_args(Arg&& arg, Args&&... args)
{
_m_add_args(std::forward<Arg>(arg));
_m_fetch_args(std::forward<Args>(args)...);
}
template<typename Arg>
void _m_add_args(Arg&& arg)
{
std::wstringstream ss;
ss << arg;
_m_add_args(ss.str());
}
template<typename Return>
void _m_add_args(std::function<Return()> fn)
{
args_.emplace_back(new arg_function<Return>(fn));
}
void _m_add_args(i18n_eval&);
void _m_add_args(const i18n_eval&);
void _m_add_args(i18n_eval&&);
void _m_add_args(std::string&);
void _m_add_args(const std::string&);
void _m_add_args(std::string&&);
void _m_add_args(std::wstring&);
void _m_add_args(const std::wstring&);
void _m_add_args(std::wstring&&);
private:
std::string msgid_;
std::vector<std::unique_ptr<eval_arg>> args_;
};//end class i18n_eval;
}
#endif//NANA_I18N_HPP

123
include/nana/key_type.hpp Normal file
View File

@@ -0,0 +1,123 @@
/*
* A Key Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/key_type.hpp
*/
#ifndef NANA_KEY_TYPE_HPP
#define NANA_KEY_TYPE_HPP
namespace nana
{
namespace detail
{
class key_interface
{
public:
virtual ~key_interface(){}
virtual bool same_type(const key_interface*) const = 0;
virtual bool compare(const key_interface*) const = 0;
}; //end class key_interface
//Use less compare for equal compare
inline bool pred_equal_by_less(const key_interface * left, const key_interface* right)
{
return (left->compare(right) == false) && (right->compare(left) == false);
}
template<typename T>
struct type_escape
{
typedef T type;
};
template<>
struct type_escape<char*>
{
typedef std::string type;
};
template<>
struct type_escape<const char*>
{
typedef std::string type;
};
template<int Size>
struct type_escape<char[Size]>
{
typedef std::string type;
};
template<int Size>
struct type_escape<const char[Size]>
{
typedef std::string type;
};
template<>
struct type_escape<wchar_t*>
{
typedef std::wstring type;
};
template<>
struct type_escape<const wchar_t*>
{
typedef std::wstring type;
};
template<int Size>
struct type_escape<wchar_t[Size]>
{
typedef std::wstring type;
};
template<int Size>
struct type_escape<const wchar_t[Size]>
{
typedef std::wstring type;
};
}
template<typename T, typename Compare>
class key
: public detail::key_interface
{
public:
typedef detail::key_interface key_interface;
typedef T key_type;
key(const key_type& k)
: key_object_(k)
{}
key(key_type&& k)
: key_object_(std::move(k))
{
}
public:
//implement key_interface methods
bool same_type(const key_interface * p) const override
{
return (nullptr != dynamic_cast<const key*>(p));
}
bool compare(const key_interface* p) const override
{
auto rhs = dynamic_cast<const key*>(p);
return rhs && compare_(key_object_, rhs->key_object_);
}
private:
Compare compare_;
key_type key_object_;
};
}
#endif

View File

@@ -0,0 +1,359 @@
#ifndef NANA_PAINT_DETAIL_IMAGE_BMP_HPP
#define NANA_PAINT_DETAIL_IMAGE_BMP_HPP
#include "image_impl_interface.hpp"
#include <memory>
namespace nana{ namespace paint
{
namespace detail
{
#ifndef NANA_WINDOWS
struct bitmap_file_header
{
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} __attribute__((packed));
struct bitmap_info_header {
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
}__attribute__((packed));
struct rgb_quad
{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
};
struct bitmap_info
{
bitmap_info_header bmiHeader;
rgb_quad bmiColors[1];
}__attribute__((packed));
#else
typedef BITMAPFILEHEADER bitmap_file_header;
typedef BITMAPINFO bitmap_info;
typedef RGBQUAD rgb_quad;
#endif
class image_bmp
:public image::image_impl_interface
{
public:
image_bmp(){}
~image_bmp()
{
this->close();
}
bool open(const nana::char_t* filename)
{
if(nullptr == filename) return false;
std::ifstream ifs;
#if defined(NANA_UNICODE)
ifs.open(static_cast<std::string>(nana::charset(filename)).c_str(), std::ios::binary);
#else
ifs.open(filename, std::ios::binary);
#endif
if(ifs)
{
ifs.seekg(0, std::ios::end);
auto size = ifs.tellg();
ifs.seekg(0, std::ios::beg);
if(size <= static_cast<int>(sizeof(bitmap_file_header)))
return false;
std::unique_ptr<char[]> buffer(new char[static_cast<int>(size)]);
ifs.read(buffer.get(), size);
if(size == ifs.gcount())
{
bitmap_file_header * header = reinterpret_cast<bitmap_file_header*>(buffer.get());
if((header->bfType == 0x4D42) && (static_cast<std::streamsize>(header->bfSize) == size))
{
unsigned char* bits = reinterpret_cast<unsigned char*>(buffer.get() + header->bfOffBits);
bitmap_info * info = reinterpret_cast<bitmap_info *>(header + 1);
//Bitmap file is 4byte-aligned for each line.
std::size_t bytes_per_line;
const std::size_t height_pixels = abs(info->bmiHeader.biHeight);
if(0 == info->bmiHeader.biSizeImage)
bytes_per_line = (((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) & ~31) >> 3);
else
bytes_per_line = info->bmiHeader.biSizeImage / height_pixels;
pixbuf_.open(info->bmiHeader.biWidth, height_pixels);
pixel_rgb_t * d = pixbuf_.raw_ptr(0);
if(16 <= info->bmiHeader.biBitCount)
{
pixbuf_.put(bits, info->bmiHeader.biWidth, height_pixels, info->bmiHeader.biBitCount, bytes_per_line, (info->bmiHeader.biHeight < 0));
}
else if(8 == info->bmiHeader.biBitCount)
{
const pixel_rgb_t * const lend = d + info->bmiHeader.biWidth * height_pixels;
if(info->bmiHeader.biHeight < 0)
{
const unsigned char* s = bits;
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
const unsigned char * s_p = s;
while(d_p != dpend)
{
rgb_quad & rgb = info->bmiColors[*s_p++];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
}
d = dpend;
s += bytes_per_line;
}
}
else
{
const unsigned char* s = bits + bytes_per_line * (height_pixels - 1);
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
const unsigned char * s_p = s;
while(d_p != dpend)
{
rgb_quad & rgb = info->bmiColors[*s_p++];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
}
d = dpend;
s -= bytes_per_line;
}
}
}
else if(4 == info->bmiHeader.biBitCount)
{
const pixel_rgb_t * const lend = d + info->bmiHeader.biWidth * height_pixels;
if(info->bmiHeader.biHeight < 0)
{
const unsigned char* s = bits;
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
unsigned index = 0;
while(d_p != dpend)
{
rgb_quad & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
++index;
}
d = dpend;
s += bytes_per_line;
}
}
else
{
const unsigned char* s = bits + bytes_per_line * (height_pixels - 1);
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
unsigned index = 0;
while(d_p != dpend)
{
rgb_quad & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
++index;
}
d = dpend;
s -= bytes_per_line;
}
}
}
else if(2 == info->bmiHeader.biBitCount)
{
const pixel_rgb_t * const lend = d + info->bmiHeader.biWidth * height_pixels;
if(info->bmiHeader.biHeight < 0)
{
const unsigned char* s = bits;
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
unsigned index = 0;
while(d_p != dpend)
{
unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2
rgb_quad& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift))>>shift];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
++index;
}
d = dpend;
s += bytes_per_line;
}
}
else
{
const unsigned char* s = bits + bytes_per_line * (height_pixels - 1);
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
unsigned index = 0;
while(d_p != dpend)
{
unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2
rgb_quad& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift))>>shift];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
++index;
}
d = dpend;
s -= bytes_per_line;
}
}
}
else if(1 == info->bmiHeader.biBitCount)
{
const pixel_rgb_t * const lend = d + info->bmiHeader.biWidth * height_pixels;
if(info->bmiHeader.biHeight < 0)
{
const unsigned char* s = bits;
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
unsigned index = 0;
while(d_p != dpend)
{
unsigned bi = (7 - (index & 7)); //(index % 8)
rgb_quad & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
++index;
}
d = dpend;
s += bytes_per_line;
}
}
else
{
const unsigned char* s = bits + bytes_per_line * (height_pixels - 1);
while(d < lend)
{
pixel_rgb_t * d_p = d;
pixel_rgb_t * const dpend = d_p + info->bmiHeader.biWidth;
unsigned index = 0;
while(d_p != dpend)
{
unsigned bi = (7 - (index & 7));
rgb_quad & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi];
d_p->u.element.red = rgb.rgbRed;
d_p->u.element.green = rgb.rgbGreen;
d_p->u.element.blue = rgb.rgbBlue;
d_p->u.element.alpha_channel = rgb.rgbReserved;
++d_p;
++index;
}
d = dpend;
s -= bytes_per_line;
}
}
}
}
}
}
return (false == pixbuf_.empty());
}
bool alpha_channel() const
{
return false;
}
bool empty() const
{
return pixbuf_.empty();
}
void close()
{
pixbuf_.close();
}
nana::size size() const
{
return pixbuf_.size();
}
void paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const
{
if(graph && pixbuf_)
pixbuf_.paste(src_r, graph.handle(), x, y);
}
void stretch(const nana::rectangle& src_r, graph_reference graph, const nana::rectangle& r) const
{
if(graph && pixbuf_)
pixbuf_.stretch(src_r, graph.handle(), r);
}
private:
nana::paint::pixel_buffer pixbuf_;
};//end class bmpfile
}//end namespace detail
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,43 @@
#ifndef NANA_PAINT_DETAIL_IMAGE_ICO_HPP
#define NANA_PAINT_DETAIL_IMAGE_ICO_HPP
#include "image_impl_interface.hpp"
namespace nana{ namespace paint
{
namespace detail
{
class image_ico
:public image::image_impl_interface
{
#if defined(NANA_WINDOWS)
struct handle_deleter
{
void operator()(HICON* handle) const;
};//end struct handle_deleter
typedef std::shared_ptr<HICON> ptr_t;
#else
typedef std::shared_ptr<int*> ptr_t;
#endif
public:
image_ico(bool is_ico);
bool open(const nana::char_t* filename);
bool alpha_channel() const;
bool empty() const;
void close();
nana::size size() const;
virtual void paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const;
virtual void stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const;
const ptr_t & ptr() const;
private:
const bool is_ico_;
nana::size size_;
ptr_t ptr_;
};//end class image_ico
}
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,29 @@
#ifndef NANA_PAINT_DETAIL_IMAGE_IMPL_INTERFACE_HPP
#define NANA_PAINT_DETAIL_IMAGE_IMPL_INTERFACE_HPP
#include "../image.hpp"
namespace nana{ namespace paint{
// class image::image_impl_interface
// the nana::image refers to an object of image::image_impl_interface by nana::refer. Employing nana::refer to refer the image::implement_t object indirectly is used
// for saving the memory that sharing the same image resource with many nana::image objects.
class image::image_impl_interface
: private nana::noncopyable
{
image_impl_interface& operator=(const image_impl_interface& rhs);
public:
typedef nana::paint::graphics& graph_reference;
virtual ~image_impl_interface() = 0; //The destructor is defined in ../image.cpp
virtual bool open(const nana::char_t* filename) = 0;
virtual bool alpha_channel() const = 0;
virtual bool empty() const = 0;
virtual void close() = 0;
virtual nana::size size() const = 0;
virtual void paste(const nana::rectangle& src_r, graph_reference dst, int x, int y) const = 0;
virtual void stretch(const nana::rectangle& src_r, graph_reference dst, const nana::rectangle& r) const = 0;
};//end class image::image_impl_interface
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,188 @@
#ifndef NANA_PAINT_DETAIL_IMAGE_PNG_HPP
#define NANA_PAINT_DETAIL_IMAGE_PNG_HPP
#include "image_impl_interface.hpp"
//Separate the libpng from the package that system provides.
#if defined(NANA_LIBPNG)
#include <nana/extrlib/png.h>
#else
#include <png.h>
#endif
#include <stdio.h>
#include "../pixel_buffer.hpp"
namespace nana
{
namespace paint{ namespace detail{
class image_png
: public image::image_impl_interface
{
public:
image_png()
{
}
bool open(const nana::char_t* png_file)
{
#ifdef NANA_UNICODE
FILE * fp = ::fopen(static_cast<std::string>(nana::charset(png_file)).c_str(), "rb");
#else
FILE* fp = ::fopen(png_file, "rb");
#endif
if(nullptr == fp) return false;
bool is_opened = false;
png_byte png_sig[8];
::fread(png_sig, 1, 8, fp);
//Test whether the file is a png.
if(0 == png_sig_cmp(png_sig, 0, 8))
{
png_structp png_ptr = ::png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if(png_ptr)
{
png_infop info_ptr = ::png_create_info_struct(png_ptr);
if(info_ptr)
{
if(!setjmp(png_jmpbuf(png_ptr)))
{
//The following codes may longjmp while init_io error.
::png_init_io(png_ptr, fp);
::png_set_sig_bytes(png_ptr, 8);
::png_read_info(png_ptr, info_ptr);
const int png_width = ::png_get_image_width(png_ptr, info_ptr);
const int png_height = ::png_get_image_height(png_ptr, info_ptr);
png_byte color_type = ::png_get_color_type(png_ptr, info_ptr);
::png_set_interlace_handling(png_ptr);
::png_read_update_info(png_ptr, info_ptr);
//The following codes may longjmp while image_read error.
png_bytep * row_ptrs = new png_bytep[png_height];
const std::size_t png_rowbytes = ::png_get_rowbytes(png_ptr, info_ptr);
pixbuf_.open(png_width, png_height);
const bool is_alpha_enabled = ((PNG_COLOR_MASK_ALPHA & color_type) != 0);
pixbuf_.alpha_channel(is_alpha_enabled);
if(is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_rgb_t)))
{
for(int i = 0; i < png_height; ++i)
row_ptrs[i] = reinterpret_cast<png_bytep>(pixbuf_.raw_ptr(i));
::png_read_image(png_ptr, row_ptrs);
::png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
for (int i = 0; i < png_height; ++i)
{
auto p = pixbuf_.raw_ptr(i);
for (int u = 0; u < png_width; ++u)
{
auto t = p[u].u.element.red;
p[u].u.element.red = p[u].u.element.blue;
p[u].u.element.blue = t;
}
}
}
else
{
png_byte * png_pixbuf = new png_byte[png_height * png_rowbytes];
for(int i = 0; i < png_height; ++i)
row_ptrs[i] = reinterpret_cast<png_bytep>(png_pixbuf + png_rowbytes * i);
::png_read_image(png_ptr, row_ptrs);
::png_destroy_read_struct(&png_ptr, &info_ptr, 0);
std::size_t png_pixel_bytes = png_rowbytes / png_width;
pixel_rgb_t * rgb_row_ptr = pixbuf_.raw_ptr(0);
for(int y = 0; y < png_height; ++y)
{
png_bytep png_ptr = row_ptrs[y];
pixel_rgb_t * rgb_end = rgb_row_ptr + png_width;
if(is_alpha_enabled)
{
for(pixel_rgb_t * i = rgb_row_ptr; i < rgb_end; ++i)
{
i->u.element.red = png_ptr[0];
i->u.element.green = png_ptr[1];
i->u.element.blue = png_ptr[2];
i->u.element.alpha_channel = png_ptr[3];
png_ptr += png_pixel_bytes;
}
}
else
{
for(pixel_rgb_t * i = rgb_row_ptr; i < rgb_end; ++i)
{
i->u.element.red = png_ptr[0];
i->u.element.green = png_ptr[1];
i->u.element.blue = png_ptr[2];
i->u.element.alpha_channel = 255;
png_ptr += png_pixel_bytes;
}
}
rgb_row_ptr = rgb_end;
}
delete [] png_pixbuf;
}
delete [] row_ptrs;
is_opened = true;
}
}
}
}
::fclose(fp);
return is_opened;
}
bool alpha_channel() const
{
return pixbuf_.alpha_channel();
}
virtual bool empty() const
{
return pixbuf_.empty();
}
virtual void close()
{
pixbuf_.close();
}
virtual nana::size size() const
{
return pixbuf_.size();
}
void paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const
{
pixbuf_.paste(src_r, graph.handle(), x, y);
}
void stretch(const nana::rectangle& src_r, graph_reference dst, const nana::rectangle& r) const
{
pixbuf_.stretch(src_r, dst.handle(), r);
}
private:
nana::paint::pixel_buffer pixbuf_;
};
}//end namespace detail
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,127 @@
#ifndef NANA_PAINT_IMAGE_PROCESS_PROVIDER_HPP
#define NANA_PAINT_IMAGE_PROCESS_PROVIDER_HPP
#include <nana/pat/cloneable.hpp>
#include <nana/paint/image_process_interface.hpp>
#include <string>
#include <map>
namespace nana
{
namespace paint
{
namespace detail
{
class image_process_provider
: nana::noncopyable
{
image_process_provider();
struct stretch_tag
{
typedef paint::image_process::stretch_interface interface_t;
typedef pat::mutable_cloneable<interface_t> cloneable_t;
typedef std::map<std::string, cloneable_t> table_t;
table_t table;
interface_t* employee;
}stretch_;
struct alpha_blend_tag
{
typedef paint::image_process::alpha_blend_interface interface_t;
typedef pat::mutable_cloneable<interface_t> cloneable_t;
typedef std::map<std::string, cloneable_t> table_t;
table_t table;
interface_t * employee;
}alpha_blend_;
struct blend_tag
{
typedef paint::image_process::blend_interface interface_t;
typedef pat::mutable_cloneable<interface_t> cloneable_t;
typedef std::map<std::string, cloneable_t> table_t;
table_t table;
interface_t * employee;
}blend_;
struct line_tag
{
typedef paint::image_process::line_interface interface_t;
typedef pat::mutable_cloneable<interface_t> cloneable_t;
typedef std::map<std::string, cloneable_t> table_t;
table_t table;
interface_t * employee;
}line_;
struct blur_tag
{
typedef paint::image_process::blur_interface interface_t;
typedef pat::mutable_cloneable<interface_t> cloneable_t;
typedef std::map<std::string, cloneable_t> table_t;
table_t table;
interface_t * employee;
}blur_;
public:
static image_process_provider & instance();
stretch_tag & ref_stretch_tag();
paint::image_process::stretch_interface * const * stretch() const;
paint::image_process::stretch_interface * ref_stretch(const std::string& name) const;
alpha_blend_tag & ref_alpha_blend_tag();
paint::image_process::alpha_blend_interface * const * alpha_blend() const;
paint::image_process::alpha_blend_interface * ref_alpha_blend(const std::string& name) const;
blend_tag & ref_blend_tag();
paint::image_process::blend_interface * const * blend() const;
paint::image_process::blend_interface * ref_blend(const std::string& name) const;
line_tag & ref_line_tag();
paint::image_process::line_interface * const * line() const;
paint::image_process::line_interface * ref_line(const std::string& name) const;
blur_tag & ref_blur_tag();
paint::image_process::blur_interface * const * blur() const;
paint::image_process::blur_interface * ref_blur(const std::string& name) const;
public:
template<typename Tag>
void set(Tag & tag, const std::string& name)
{
auto i = tag.table.find(name);
if(i != tag.table.end())
tag.employee = &(*(i->second));
}
//add
//@brief: The add operation is successful if the name does not exist.
// it does not replace the existing object by new object, becuase this
// feature is thread safe and efficiency.
template<typename ImageProcessor, typename Tag>
void add(Tag & tag, const std::string& name)
{
if(tag.table.count(name) == 0)
{
typedef typename Tag::cloneable_t cloneable_t;
auto & obj = tag.table[name];
obj = cloneable_t(ImageProcessor());
if(nullptr == tag.employee)
tag.employee = &(*obj);
}
}
private:
template<typename Tag>
typename Tag::interface_t* _m_read(const Tag& tag, const std::string& name) const
{
auto i = tag.table.find(name);
return (i != tag.table.end() ? &(*i->second) : tag.employee);
}
};
}
}
}//end namespace nana
#endif

View File

@@ -0,0 +1,676 @@
/*
* Image Processor Algorithm Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 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: nana/paint/detail/image_processor.hpp
* @brief: This header file implements the algorithms of image processor
*
* DON'T INCLUDE THIS HEADER FILE DIRECTLY TO YOUR SOURCE FILE.
*/
#ifndef NANA_PAINT_DETAIL_IMAGE_PROCESSOR_HPP
#define NANA_PAINT_DETAIL_IMAGE_PROCESSOR_HPP
#include "../image_process_interface.hpp"
#include <nana/paint/pixel_buffer.hpp>
#include <nana/paint/detail/native_paint_interface.hpp>
#include <algorithm>
namespace nana
{
namespace paint
{
namespace detail
{
namespace algorithms
{
class proximal_interoplation
: public image_process::stretch_interface
{
void process(const paint::pixel_buffer& s_pixbuf, const nana::rectangle& r_src, paint::pixel_buffer & pixbuf, const nana::rectangle& r_dst) const
{
const auto bytes_per_line = s_pixbuf.bytes_per_line();
double rate_x = double(r_src.width) / r_dst.width;
double rate_y = double(r_src.height) / r_dst.height;
pixel_rgb_t * s_raw_pixbuf = s_pixbuf.raw_ptr(0);
if(s_pixbuf.alpha_channel())
{
for(std::size_t row = 0; row < r_dst.height; ++row)
{
const pixel_rgb_t * s_line = pixel_at(s_raw_pixbuf, (static_cast<int>(row * rate_y) + r_src.y) * bytes_per_line);
pixel_rgb_t * i = pixbuf.raw_ptr(r_dst.y + row);
for(std::size_t x = 0; x < r_dst.width; ++x, ++i)
{
const pixel_rgb_t * s = s_line + static_cast<int>(x * rate_x) + r_src.x;
if(0 == s->u.element.alpha_channel)
continue;
if(s->u.element.alpha_channel != 255)
{
i->u.element.red = unsigned(i->u.element.red * (255 - s->u.element.alpha_channel) + s->u.element.red * s->u.element.alpha_channel) / 255;
i->u.element.green = unsigned(i->u.element.green * (255 - s->u.element.alpha_channel) + s->u.element.green * s->u.element.alpha_channel) / 255;
i->u.element.blue = unsigned(i->u.element.blue * (255 - s->u.element.alpha_channel) + s->u.element.blue * s->u.element.alpha_channel) / 255;
}
else
{
unsigned alpha_chn = i->u.element.alpha_channel;
*i = *s;
i->u.element.alpha_channel = alpha_chn;
}
}
}
}
else
{
for(std::size_t row = 0; row < r_dst.height; ++row)
{
const pixel_rgb_t * s_line = pixel_at(s_raw_pixbuf, (static_cast<int>(row * rate_y) + r_src.y) * bytes_per_line);
pixel_rgb_t * i = pixbuf.raw_ptr(r_dst.y + row);
for(std::size_t x = 0; x < r_dst.width; ++x, ++i)
*i = s_line[static_cast<int>(x * rate_x) + r_src.x];
}
}
}
};
class bilinear_interoplation
: public image_process::stretch_interface
{
struct x_u_table_tag
{
int x;
int iu;
int iu_minus_coef;
};
void process(const paint::pixel_buffer & s_pixbuf, const nana::rectangle& r_src, paint::pixel_buffer & pixbuf, const nana::rectangle& r_dst) const
{
const auto s_bytes_per_line = s_pixbuf.bytes_per_line();
const int shift_size = 8;
const std::size_t coef = 1 << shift_size;
const int double_shift_size = shift_size << 1;
double rate_x = double(r_src.width) / r_dst.width;
double rate_y = double(r_src.height) / r_dst.height;
const int right_bound = static_cast<int>(r_src.width) - 1 + r_src.x;
const nana::pixel_rgb_t * s_raw_pixel_buffer = s_pixbuf.raw_ptr(0);
const int bottom = r_src.y + static_cast<int>(r_src.height - 1);
x_u_table_tag * x_u_table = new x_u_table_tag[r_dst.width];
for(std::size_t x = 0; x < r_dst.width; ++x)
{
double u = (int(x) + 0.5) * rate_x - 0.5;
x_u_table_tag el;
el.x = r_src.x;
if(u < 0)
{
u = 0;
}
else
{
int ipart = static_cast<int>(u);
el.x += ipart;
u -= ipart;
}
el.iu = static_cast<int>(u * coef);
el.iu_minus_coef = coef - el.iu;
x_u_table[x] = el;
}
const bool is_alpha_channel = s_pixbuf.alpha_channel();
for(std::size_t row = 0; row < r_dst.height; ++row)
{
double v = (int(row) + 0.5) * rate_y - 0.5;
int sy = r_src.y;
if(v < 0)
{
v = 0;
}
else
{
int ipart = static_cast<int>(v);
sy += ipart;
v -= ipart;
}
std::size_t iv = static_cast<size_t>(v * coef);
const std::size_t iv_minus_coef = coef - iv;
const nana::pixel_rgb_t * s_line = pixel_at(s_raw_pixel_buffer, sy * s_bytes_per_line);
const nana::pixel_rgb_t * next_s_line = pixel_at(s_line, (sy < bottom ? s_bytes_per_line : 0));
nana::pixel_rgb_t col0;
nana::pixel_rgb_t col1;
nana::pixel_rgb_t col2;
nana::pixel_rgb_t col3;
pixel_rgb_t * i = pixbuf.raw_ptr(row + r_dst.y) + r_dst.x;
if(is_alpha_channel)
{
for(std::size_t x = 0; x < r_dst.width; ++x, ++i)
{
x_u_table_tag el = x_u_table[x];
col0 = s_line[el.x];
col1 = next_s_line[el.x];
if(el.x < right_bound)
{
col2 = s_line[el.x + 1];
col3 = next_s_line[el.x + 1];
}
else
{
col2 = col0;
col3 = col1;
}
std::size_t coef0 = el.iu_minus_coef * iv_minus_coef;
std::size_t coef1 = el.iu_minus_coef * iv;
std::size_t coef2 = el.iu * iv_minus_coef;
std::size_t coef3 = el.iu * iv;
unsigned alpha_chn = static_cast<unsigned>((coef0 * col0.u.element.alpha_channel + coef1 * col1.u.element.alpha_channel + (coef2 * col2.u.element.alpha_channel + coef3 * col3.u.element.alpha_channel)) >> double_shift_size);
unsigned s_red = static_cast<unsigned>((coef0 * col0.u.element.red + coef1 * col1.u.element.red + (coef2 * col2.u.element.red + coef3 * col3.u.element.red)) >> double_shift_size);
unsigned s_green = static_cast<unsigned>((coef0 * col0.u.element.green + coef1 * col1.u.element.green + (coef2 * col2.u.element.green + coef3 * col3.u.element.green)) >> double_shift_size);
unsigned s_blue = static_cast<unsigned>((coef0 * col0.u.element.blue + coef1 * col1.u.element.blue + (coef2 * col2.u.element.blue + coef3 * col3.u.element.blue)) >> double_shift_size);
if(alpha_chn)
{
if(alpha_chn != 255)
{
i->u.element.red = unsigned(i->u.element.red * (255 - alpha_chn) + s_red * alpha_chn) / 255;
i->u.element.green = unsigned(i->u.element.green * (255 - alpha_chn) + s_green * alpha_chn) / 255;
i->u.element.blue = unsigned(i->u.element.blue * (255 - alpha_chn) + s_blue * alpha_chn) / 255;
}
else
{
i->u.element.red = s_red;
i->u.element.green = s_green;
i->u.element.blue = s_blue;
}
}
}
}
else
{
for(std::size_t x = 0; x < r_dst.width; ++x, ++i)
{
x_u_table_tag el = x_u_table[x];
col0 = s_line[el.x];
col1 = next_s_line[el.x];
if(el.x < right_bound)
{
col2 = s_line[el.x + 1];
col3 = next_s_line[el.x + 1];
}
else
{
col2 = col0;
col3 = col1;
}
std::size_t coef0 = el.iu_minus_coef * iv_minus_coef;
std::size_t coef1 = el.iu_minus_coef * iv;
std::size_t coef2 = el.iu * iv_minus_coef;
std::size_t coef3 = el.iu * iv;
i->u.element.red = static_cast<unsigned>((coef0 * col0.u.element.red + coef1 * col1.u.element.red + (coef2 * col2.u.element.red + coef3 * col3.u.element.red)) >> double_shift_size);
i->u.element.green = static_cast<unsigned>((coef0 * col0.u.element.green + coef1 * col1.u.element.green + (coef2 * col2.u.element.green + coef3 * col3.u.element.green)) >> double_shift_size);
i->u.element.blue = static_cast<unsigned>((coef0 * col0.u.element.blue + coef1 * col1.u.element.blue + (coef2 * col2.u.element.blue + coef3 * col3.u.element.blue)) >> double_shift_size);
}
}
}
delete [] x_u_table;
}
};
//alpha_blend
class alpha_blend
: public image_process::alpha_blend_interface
{
//process
virtual void process(const paint::pixel_buffer& s_pixbuf, const nana::rectangle& s_r, paint::pixel_buffer& d_pixbuf, const nana::point& d_pos) const
{
nana::pixel_rgb_t * d_rgb = d_pixbuf.at(d_pos);
nana::pixel_rgb_t * s_rgb = s_pixbuf.raw_ptr(s_r.y) + s_r.x;
if(d_rgb && s_rgb)
{
const unsigned rest = s_r.width & 0x3;
const unsigned length_align4 = s_r.width - rest;
std::size_t d_step_bytes = d_pixbuf.bytes_per_line() - (s_r.width - rest) * sizeof(pixel_rgb_t);
std::size_t s_step_bytes = s_pixbuf.bytes_per_line() - (s_r.width - rest) * sizeof(pixel_rgb_t);
for(unsigned line = 0; line < s_r.height; ++line)
{
pixel_rgb_t* end = d_rgb + length_align4;
for(; d_rgb < end; d_rgb += 4, s_rgb += 4)
{
//0
if(s_rgb->u.element.alpha_channel)
{
if(s_rgb->u.element.alpha_channel != 255)
{
d_rgb->u.element.red = unsigned(d_rgb->u.element.red * (255 - s_rgb[0].u.element.alpha_channel) + s_rgb[0].u.element.red * s_rgb[0].u.element.alpha_channel) / 255;
d_rgb->u.element.green = unsigned(d_rgb->u.element.green * (255 - s_rgb[0].u.element.alpha_channel) + s_rgb[0].u.element.green * s_rgb[0].u.element.alpha_channel) / 255;
d_rgb->u.element.blue = unsigned(d_rgb->u.element.blue * (255 - s_rgb[0].u.element.alpha_channel) + s_rgb[0].u.element.blue * s_rgb[0].u.element.alpha_channel) / 255;
}
else
*d_rgb = *s_rgb;
}
//1
if(s_rgb[1].u.element.alpha_channel)
{
if(s_rgb[1].u.element.alpha_channel != 255)
{
d_rgb[1].u.element.red = unsigned(d_rgb[1].u.element.red * (255 - s_rgb[1].u.element.alpha_channel) + s_rgb[1].u.element.red * s_rgb[1].u.element.alpha_channel) / 255;
d_rgb[1].u.element.green = unsigned(d_rgb[1].u.element.green * (255 - s_rgb[1].u.element.alpha_channel) + s_rgb[1].u.element.green * s_rgb[1].u.element.alpha_channel) / 255;
d_rgb[1].u.element.blue = unsigned(d_rgb[1].u.element.blue * (255 - s_rgb[1].u.element.alpha_channel) + s_rgb[1].u.element.blue * s_rgb[1].u.element.alpha_channel) / 255;
}
else
d_rgb[1] = s_rgb[1];
}
//2
if(s_rgb[2].u.element.alpha_channel)
{
if(s_rgb[2].u.element.alpha_channel != 255)
{
d_rgb[2].u.element.red = unsigned(d_rgb[2].u.element.red * (255 - s_rgb[2].u.element.alpha_channel) + s_rgb[2].u.element.red * s_rgb[2].u.element.alpha_channel) / 255;
d_rgb[2].u.element.green = unsigned(d_rgb[2].u.element.green * (255 - s_rgb[2].u.element.alpha_channel) + s_rgb[2].u.element.green * s_rgb[2].u.element.alpha_channel) / 255;
d_rgb[2].u.element.blue = unsigned(d_rgb[2].u.element.blue * (255 - s_rgb[2].u.element.alpha_channel) + s_rgb[2].u.element.blue * s_rgb[2].u.element.alpha_channel) / 255;
}
else
d_rgb[2] = s_rgb[2];
}
//3
if(s_rgb[3].u.element.alpha_channel)
{
if(s_rgb[3].u.element.alpha_channel != 255)
{
d_rgb[3].u.element.red = unsigned(d_rgb[3].u.element.red * (255 - s_rgb[3].u.element.alpha_channel) + s_rgb[3].u.element.red * s_rgb[3].u.element.alpha_channel) / 255;
d_rgb[3].u.element.green = unsigned(d_rgb[3].u.element.green * (255 - s_rgb[3].u.element.alpha_channel) + s_rgb[3].u.element.green * s_rgb[3].u.element.alpha_channel) / 255;
d_rgb[3].u.element.blue = unsigned(d_rgb[3].u.element.blue * (255 - s_rgb[3].u.element.alpha_channel) + s_rgb[3].u.element.blue * s_rgb[3].u.element.alpha_channel) / 255;
}
else
d_rgb[3] = s_rgb[3];
}
}
const pixel_rgb_t * s_end = s_rgb + rest;
for(auto i = s_rgb; i != s_end; ++i)
{
if(i->u.element.alpha_channel)
{
if(i->u.element.alpha_channel != 255)
{
d_rgb[3].u.element.red = unsigned(d_rgb[3].u.element.red * (255 - i->u.element.alpha_channel) + i->u.element.red * i->u.element.alpha_channel) / 255;
d_rgb[3].u.element.green = unsigned(d_rgb[3].u.element.green * (255 - i->u.element.alpha_channel) + i->u.element.green * i->u.element.alpha_channel) / 255;
d_rgb[3].u.element.blue = unsigned(d_rgb[3].u.element.blue * (255 - i->u.element.alpha_channel) + i->u.element.blue * i->u.element.alpha_channel) / 255;
}
else
d_rgb[3] = *i;
}
}
d_rgb = pixel_at(d_rgb, d_step_bytes);
s_rgb = pixel_at(s_rgb, s_step_bytes);
}
}
}
};
//blend
class blend
: public image_process::blend_interface
{
//process
virtual void process(const paint::pixel_buffer& s_pixbuf, const nana::rectangle& s_r, paint::pixel_buffer& d_pixbuf, const nana::point& d_pos, double fade_rate) const
{
nana::pixel_rgb_t * d_rgb = d_pixbuf.raw_ptr(d_pos.y) + d_pos.x;
nana::pixel_rgb_t * s_rgb = s_pixbuf.raw_ptr(s_r.y) + s_r.x;
if(d_rgb && s_rgb)
{
unsigned char* tablebuf = detail::alloc_fade_table(fade_rate);//new unsigned char[0x100 * 2];
unsigned char* d_table = tablebuf;
unsigned char* s_table = d_table + 0x100;
const unsigned rest = s_r.width & 0x3;
const unsigned length_align4 = s_r.width - rest;
std::size_t d_step_bytes = d_pixbuf.bytes_per_line() - (s_r.width - rest) * sizeof(pixel_rgb_t);
std::size_t s_step_bytes = s_pixbuf.bytes_per_line() - (s_r.width - rest) * sizeof(pixel_rgb_t);
for(unsigned line = 0; line < s_r.height; ++line)
{
pixel_rgb_t* end = d_rgb + length_align4;
for(; d_rgb < end; d_rgb += 4, s_rgb += 4)
{
//0
d_rgb[0].u.element.red = unsigned(d_table[d_rgb[0].u.element.red] + s_table[s_rgb[0].u.element.red]);
d_rgb[0].u.element.green = unsigned(d_table[d_rgb[0].u.element.green] + s_table[s_rgb[0].u.element.green]);
d_rgb[0].u.element.blue = unsigned(d_table[d_rgb[0].u.element.blue] + s_table[s_rgb[0].u.element.blue]);
//1
d_rgb[1].u.element.red = unsigned(d_table[d_rgb[1].u.element.red] + s_table[s_rgb[1].u.element.red]);
d_rgb[1].u.element.green = unsigned(d_table[d_rgb[1].u.element.green] + s_table[s_rgb[1].u.element.green]);
d_rgb[1].u.element.blue = unsigned(d_table[d_rgb[1].u.element.blue] + s_table[s_rgb[1].u.element.blue]);
//2
d_rgb[2].u.element.red = unsigned(d_table[d_rgb[2].u.element.red] + s_table[s_rgb[2].u.element.red]);
d_rgb[2].u.element.green = unsigned(d_table[d_rgb[2].u.element.green] + s_table[s_rgb[2].u.element.green]);
d_rgb[2].u.element.blue = unsigned(d_table[d_rgb[2].u.element.blue] + s_table[s_rgb[2].u.element.blue]);
//3
d_rgb[3].u.element.red = unsigned(d_table[d_rgb[3].u.element.red] + s_table[s_rgb[3].u.element.red]);
d_rgb[3].u.element.green = unsigned(d_table[d_rgb[3].u.element.green] + s_table[s_rgb[3].u.element.green]);
d_rgb[3].u.element.blue = unsigned(d_table[d_rgb[3].u.element.blue] + s_table[s_rgb[3].u.element.blue]);
}
for(unsigned i = 0; i < rest; ++i)
{
d_rgb[i].u.element.red = unsigned(d_table[d_rgb[i].u.element.red] + s_table[s_rgb[i].u.element.red]);
d_rgb[i].u.element.green = unsigned(d_table[d_rgb[i].u.element.green] + s_table[s_rgb[i].u.element.green]);
d_rgb[i].u.element.blue = unsigned(d_table[d_rgb[i].u.element.blue] + s_table[s_rgb[i].u.element.blue]);
}
d_rgb = pixel_at(d_rgb, d_step_bytes);
s_rgb = pixel_at(s_rgb, s_step_bytes);
}
detail::free_fade_table(tablebuf);
}
}
};
//class line
class bresenham_line
: public image_process::line_interface
{
virtual void process(paint::pixel_buffer & pixbuf, const nana::point& pos_beg, const nana::point& pos_end, nana::color_t color, double fade_rate) const
{
const std::size_t bytes_pl = pixbuf.bytes_per_line();
unsigned char * fade_table = nullptr;
nana::pixel_rgb_t rgb_imd;
if(fade_rate != 0.0)
{
fade_table = detail::alloc_fade_table(1 - fade_rate);
rgb_imd.u.color = color;
rgb_imd = detail::fade_color_intermedia(rgb_imd, fade_table);
}
nana::pixel_rgb_t * i = pixel_at(pixbuf.raw_ptr(0), pos_beg.y * bytes_pl) + pos_beg.x;
auto delta = pos_end - pos_beg;
int step_bytes;
if(delta.y < 0)
{
delta.y = -delta.y;
step_bytes = -static_cast<int>(bytes_pl);
}
else
step_bytes = static_cast<int>(bytes_pl);
if(delta.x == delta.y)
{
step_bytes += sizeof(pixel_rgb_t);
++delta.x;
if(fade_table)
{
for(int x = 0; x < delta.x; ++x)
{
*i = detail::fade_color_by_intermedia(*i, rgb_imd, fade_table);
i = pixel_at(i, step_bytes);
}
}
else
{
for(int x = 0; x < delta.x; ++x)
{
i->u.color = color;
i = pixel_at(i, step_bytes);
}
}
}
else
{
int dx_2 = delta.x << 1;
int dy_2 = delta.y << 1;
if(delta.x > delta.y)
{
int error = dy_2 - delta.x;
++delta.x; //Include the end poing
if(fade_table)
{
for(int x = 0; x < delta.x; ++x)
{
*i = detail::fade_color_by_intermedia(*i, rgb_imd, fade_table);
if(error >= 0)
{
error -= dx_2;
i = pixel_at(i, step_bytes);
}
error += dy_2;
++i;
}
}
else
{
for(int x = 0; x < delta.x; ++x)
{
i->u.color = color;
if(error >= 0)
{
error -= dx_2;
i = pixel_at(i, step_bytes);
}
error += dy_2;
++i;
}
}
}
else
{
int error = dx_2 - delta.y;
++delta.y; //Include the end point
if(fade_table)
{
for (int y = 0; y < delta.y; ++y)
{
*i = detail::fade_color_by_intermedia(*i, rgb_imd, fade_table);
if(error >= 0)
{
error -= dy_2;
++i;
}
error += dx_2;
i = pixel_at(i, step_bytes);
}
}
else
{
for (int y = 0; y < delta.y; ++y)
{
i->u.color = color;
if(error >= 0)
{
error -= dy_2;
++i;
}
error += dx_2;
i = pixel_at(i, step_bytes);
}
}
}
}
detail::free_fade_table(fade_table);
}
};
class superfast_blur
: public image_process::blur_interface
{
void process(pixel_buffer& pixbuf, const nana::rectangle& area, std::size_t u_radius) const
{
int radius = static_cast<int>(u_radius);
int w = area.width;
int h = area.height;
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = (radius << 1) + 1;
int large_edge = (w > h ? w : h);
const int div_256 = div * 256;
std::unique_ptr<int[]> all_table(new int[(wh << 1) + wh + (large_edge << 1) + div_256]);
int * r = all_table.get();
int * g = r + wh;
int * b = g + wh;
int * vmin = b + wh;
int * vmax = vmin + large_edge;
int * dv = vmax + large_edge;
int end_div = div - 1;
for(int i = 0, *dv_block = dv; i < 256; ++i)
{
for(int u = 0; u < end_div; u += 2)
{
dv_block[u] = i;
dv_block[u + 1] = i;
}
dv_block[div - 1] = i;
dv_block += div;
}
auto linepix = pixbuf.raw_ptr(area.y) + area.x;
int yi = 0;
for(int y = 0; y < h; ++y)
{
int sum_r = 0, sum_g = 0, sum_b = 0;
if(radius <= wm)
{
for(int i = - radius; i <= radius; ++i)
{
nana::pixel_rgb_t px = linepix[(i > 0 ? i : 0)];
sum_r += px.u.element.red;
sum_g += px.u.element.green;
sum_b += px.u.element.blue;
}
}
else
{
for(int i = - radius; i <= radius; ++i)
{
nana::pixel_rgb_t px = linepix[std::min(wm, (i > 0 ? i : 0))];
sum_r += px.u.element.red;
sum_g += px.u.element.green;
sum_b += px.u.element.blue;
}
}
for(int x = 0; x < w; ++x)
{
r[yi] = dv[sum_r];
g[yi] = dv[sum_g];
b[yi] = dv[sum_b];
if(0 == y)
{
vmin[x] = std::min(x + radius + 1, wm);
vmax[x] = std::max(x - radius, 0);
}
nana::pixel_rgb_t p1 = linepix[vmin[x]];
nana::pixel_rgb_t p2 = linepix[vmax[x]];
sum_r += p1.u.element.red - p2.u.element.red;
sum_g += p1.u.element.green - p2.u.element.green;
sum_b += p1.u.element.blue - p2.u.element.blue;
++yi;
}
linepix = pixbuf.raw_ptr(area.y + y) + area.x;
}
const int yp_init = -radius * w;
const std::size_t bytes_pl = pixbuf.bytes_per_line();
for(int x = 0; x < w; ++x)
{
int sum_r = 0, sum_g = 0, sum_b = 0;
int yp = yp_init;
for(int i = -radius; i <= radius; ++i)
{
if(yp < 1)
{
sum_r += r[x];
sum_g += g[x];
sum_b += b[x];
}
else
{
int yi = yp + x;
sum_r += r[yi];
sum_g += g[yi];
sum_b += b[yi];
}
yp += w;
}
linepix = pixbuf.raw_ptr(area.y) + x;
for(int y = 0; y < h; ++y)
{
linepix->u.color = 0xFF000000 | (dv[sum_r] << 16) | (dv[sum_g] << 8) | dv[sum_b];
if(x == 0)
{
vmin[y] = std::min(y + radius + 1, hm) * w;
vmax[y] = std::max(y - radius, 0) * w;
}
int pt1 = x + vmin[y];
int pt2 = x + vmax[y];
sum_r += r[pt1] - r[pt2];
sum_g += g[pt1] - g[pt2];
sum_b += b[pt1] - b[pt2];
linepix = pixel_at(linepix, bytes_pl);
}
}
}
};//end class superfast_blur
}
}
}
}
#endif

View File

@@ -0,0 +1,42 @@
/*
* Platform Implementation
* Copyright(C) 2003-2013 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: nana/paint/detail/native_paint_interface.hpp
*/
#ifndef NANA_PAINT_DETAIL_PLATFORM_HPP
#define NANA_PAINT_DETAIL_PLATFORM_HPP
#include <nana/basic_types.hpp>
namespace nana
{
namespace paint
{
namespace detail
{
nana::size drawable_size(drawable_type);
unsigned char * alloc_fade_table(double fade_rate);
void free_fade_table(const unsigned char*);
//color = bgcolor * fade_rate + fgcolor * (1 - fade_rate);
nana::pixel_rgb_t fade_color(nana::pixel_rgb_t bgcolor, nana::pixel_rgb_t fgcolor, double fade_rate);
nana::pixel_rgb_t fade_color(nana::pixel_rgb_t bgcolor, nana::pixel_rgb_t fgcolor, const unsigned char* const fade_table);
nana::pixel_rgb_t fade_color_intermedia(nana::pixel_rgb_t fgcolor, const unsigned char* fade_table);
nana::pixel_rgb_t fade_color_by_intermedia(nana::pixel_rgb_t bgcolor, nana::pixel_rgb_t fgcolor_intermedia, const unsigned char* const fade_table);
void blend(drawable_type dw, const nana::rectangle& r, nana::color_t, double fade_rate);
nana::size raw_text_extent_size(drawable_type, const nana::char_t*, std::size_t len);
nana::size text_extent_size(drawable_type, const nana::char_t*, std::size_t len);
void draw_string(drawable_type, int x, int y, const nana::char_t *, std::size_t len);
}//end namespace detail
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,38 @@
/*
* Graphics Gadget Implementation
* Copyright(C) 2003-2013 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: nana/paint/gadget.hpp
*/
#ifndef NANA_PAINT_GADGET_HPP
#define NANA_PAINT_GADGET_HPP
#include "graphics.hpp"
#include "image.hpp"
#include <nana/basic_types.hpp>
namespace nana
{
namespace paint
{
namespace gadget
{
struct directions
{
enum t{to_east, to_southeast, to_south, to_southwest, to_west, to_northwest, to_north, to_northeast};
};
void arrow_16_pixels(nana::paint::graphics&, int x, int y, unsigned color, uint32_t style, directions::t direction);
void close_16_pixels(nana::paint::graphics&, int x, int y, uint32_t style, uint32_t color);
void cross(nana::paint::graphics&, int x, int y, uint32_t size, uint32_t thickness, nana::color_t color);
}//end namespace gadget
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,166 @@
/*
* Paint Graphics Implementation
* Copyright(C) 2003-2013 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: nana/paint/graphics.hpp
*/
#ifndef NANA_PAINT_GRAPHICS_HPP
#define NANA_PAINT_GRAPHICS_HPP
#include "../basic_types.hpp"
#include "../gui/basis.hpp"
#include "pixel_buffer.hpp"
#include <memory>
namespace nana
{
namespace paint
{
namespace detail
{
struct native_font_signature;
}// end namespace detail
typedef detail::native_font_signature* native_font_type;
class font
{
friend class graphics;
public:
font();
font(drawable_type);
font(const font&);
font(const char_t* name, unsigned size, bool bold = false, bool italic = false, bool underline = false, bool strike_out = false);
~font();
bool empty() const;
void make(const char_t* name, unsigned size, bool bold = false, bool italic = false, bool underline = false, bool strike_out = false);
void make_raw(const char_t*, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out);
void set_default() const;
::nana::string name() const;
unsigned size() const;
bool bold() const;
unsigned height() const;
unsigned weight() const;
bool italic() const;
native_font_type handle() const;
void release();
font& operator=(const font&);
bool operator==(const font&) const;
bool operator!=(const font&) const;
private:
struct impl_type;
impl_type * impl_;
};
/// \brief off-screen resource defined as ref-counting, can refer one resource
///
/// Load a bitmap into a graphics:
/// \code
/// nana::paint::graphics graph;
/// nana::paint::image img("C:\\ABitmap.bmp");
/// img.paste(graph, 0, 0); //graph may create if it is empty
/// \endcode
class graphics
{
public:
typedef ::nana::native_window_type native_window_type;
graphics();
graphics(unsigned width, unsigned height); ///< size in pixel
graphics(const ::nana::size&); ///< size in pixel
graphics(const graphics&); ///< the resource is not copyed, the two graphics objects refer to the *SAME* resource
graphics& operator=(const graphics&);
bool changed() const; ///< Returns true if the graphics object is operated
bool empty() const; ///< Returns true if the graphics object does not refer to any resource.
operator const void*() const;
drawable_type handle() const;
const void* pixmap() const;
const void* context() const;
void make(unsigned width, unsigned height); ///< Creates a bitmap resource that size is width by height in pixel
void resize(unsigned width, unsigned height);
void typeface(const font&); ///< Selects a specified font type into the graphics object.
font typeface() const;
::nana::size text_extent_size(const char_t*) const; ///< Computes the width and height of the specified string of text.
::nana::size text_extent_size(const string&) const; ///< Computes the width and height of the specified string of text.
::nana::size text_extent_size(const char_t*, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length.
::nana::size text_extent_size(const string&, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length.
::nana::size glyph_extent_size(const char_t*, std::size_t length, std::size_t begin, std::size_t end) const;
::nana::size glyph_extent_size(const string&, std::size_t length, std::size_t begin, std::size_t end) const;
bool glyph_pixels(const char_t *, std::size_t length, unsigned* pxbuf) const;
::nana::size bidi_extent_size(const string&) const;
bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const;
unsigned bidi_string(int x, int y, color_t, const char_t *, std::size_t len);
void string(int x, int y, color_t, const ::nana::string&, std::size_t len);
void string(int x, int y, color_t, const ::nana::string&);
void string(int x, int y, color_t, const char_t*, std::size_t len);
void string(int x, int y, color_t, const char_t*);
void set_pixel(int x, int y, color_t);
void rectangle(int x, int y, unsigned width, unsigned height, color_t, bool solid);
void rectangle(color_t, bool solid);
void rectangle(const ::nana::rectangle&, color_t, bool solid);
void rectangle_line(const ::nana::rectangle&, color_t left, color_t top, color_t right, color_t bottom);
void round_rectangle(int x, int y, unsigned width, unsigned height, unsigned radius_x, unsigned radius_y, color_t, bool solid, color_t color_if_solid);
void round_rectangle(const ::nana::rectangle&, unsigned radius_x, unsigned radius_y, color_t, bool solid, color_t color_if_solid);
void shadow_rectangle(const ::nana::rectangle&, color_t beg_color, color_t end_color, bool vertical);
void shadow_rectangle(int x, int y, unsigned width, unsigned height, color_t beg_color, color_t end_color, bool vertical); ///< Draws a width and height rectangle at (x, y) and the color in range of [begin, end]
void line(int x1, int y1, int x2, int y2, color_t); ///< Draws a line from point (x1, y1) to point (x2, y2) in the specified color.
void line(const point& beg, const point& end, color_t);
void lines(const point* points, std::size_t n_of_points, color_t);
void line_begin(int x, int y);
void line_to(int x, int y, color_t);
void bitblt(int x, int y, const graphics& source); ///< Transfers the source to the specified point.
void bitblt(const ::nana::rectangle& r_dst, native_window_type src); ///< Transfers the color data corresponding to r_dst from the src window to this graphics.
void bitblt(const ::nana::rectangle& r_dst, native_window_type src, const point& p_src); ///< Transfers the color data corresponding to r_dst from the src window at point p_src to this graphics.
void bitblt(const ::nana::rectangle& r_dst, const graphics& src); ///< Transfers the color data corresponding to r_dst from the src graphics to this graphics.
void bitblt(const ::nana::rectangle& r_dst, const graphics& src, const point& p_src);///< Transfers the color data corresponding to r_dst from the src graphics at point p_src to this graphics.
void blend(const ::nana::rectangle& s_r, graphics& dst, const point& d_pos, double fade_rate) const;///< blends with the dst object.
void blend(const ::nana::rectangle& r, color_t, double fade_rate); ///< blends the specifed block width the specified color.
void blur(const ::nana::rectangle& r, std::size_t radius); ///< Blur process.
void paste(graphics& dst, int x, int y) const; ///< Paste the graphics object into the dest at (x, y)
void paste(native_window_type dst, const ::nana::rectangle&, int sx, int sy) const; ///< Paste the graphics object into a platform-dependent window at (x, y)
void paste(native_window_type dst, int dx, int dy, unsigned width, unsigned height, int sx, int sy) const;
void paste(drawable_type dst, int x, int y) const;
void paste(const ::nana::rectangle& r_src, graphics& dst, int x, int y) const;
void rgb_to_wb(); ///< Transform a color graphics into black&white.
void stretch(const ::nana::rectangle& src_r, graphics& dst, const ::nana::rectangle& r) const;
void stretch(graphics& dst, const ::nana::rectangle& r) const;
void flush();
unsigned width() const;
unsigned height() const; ///< Returns the height of the off-screen buffer.
::nana::size size() const;
void setsta(); ///< Clears the status if the graphics object had been changed
void release();
void save_as_file(const char*);
static color_t mix(color_t colorX, color_t colorY, double persent);
private:
std::shared_ptr< ::nana::detail::drawable_impl_type> dwptr_;
font font_shadow_;
drawable_type handle_;
::nana::size size_;
pixel_buffer pxbuf_;
bool changed_;
};
}//end namespace paint
} //end namespace nana
#endif

View File

@@ -0,0 +1,54 @@
/*
* Paint Image Implementation
* Copyright(C) 2003-2013 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: nana/paint/image.hpp
* @description: class image is used for load an image file into memory.
*/
#ifndef NANA_PAINT_IMAGE_HPP
#define NANA_PAINT_IMAGE_HPP
#include "graphics.hpp"
namespace nana
{
namespace paint
{
/// load a picture file
class image
{
friend class image_accessor;
typedef bool (image::* unspecified_bool_t)() const;
public:
class image_impl_interface;
image();
image(const image&);
image(image&&);
image(const nana::char_t* file);
image(const nana::string& filename);
~image();
image& operator=(const image& rhs);
image& operator=(image&&);
bool open(const nana::string& filename);
bool empty() const;
operator unspecified_bool_t() const;
void close();
nana::size size() const;
void paste(graphics& dst, int x, int y) const;
void paste(const nana::rectangle& r_src, graphics& dst, const point& p_dst) const;///< Paste the area of picture specified by r_src into the destination graphics specified by dst at position p_dst.
void stretch(const nana::rectangle& r_src, graphics& dst, const nana::rectangle& r_dst) const;///<Paste the picture into the dst, stretching or compressing the picture to fit the given area.
private:
std::shared_ptr<image_impl_interface> image_ptr_;
};//end class image
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,85 @@
/*
* Image Processing Interfaces
* Copyright(C) 2003-2013 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: nana/paint/image_process_interface.hpp
*/
#ifndef NANA_PAINT_IMAGE_PROCESS_INTERFACE_HPP
#define NANA_PAINT_IMAGE_PROCESS_INTERFACE_HPP
#include <nana/basic_types.hpp>
#include <nana/paint/pixel_buffer.hpp>
namespace nana
{
namespace paint
{ /// Image Processing Algorithm Interfaces
namespace image_process
{ /// The interface of stretch algorithm.
class stretch_interface
{
public:
virtual ~stretch_interface() = 0;
/// Copies the image from a source rectangle into a destination rectangle, stretching or compressing the image to fit the dimensions of the destination rectangle in destination(d_pixbuf).
virtual void process(const paint::pixel_buffer & s_pixbuf,
const nana::rectangle& source_rectangle,
paint::pixel_buffer & d_pixbuf,
const nana::rectangle& destination_rectangle
) const = 0;
};
class alpha_blend_interface
{
public:
virtual ~alpha_blend_interface() = 0;
virtual void process(const paint::pixel_buffer& s_pixbuf, const nana::rectangle& s_r, paint::pixel_buffer& d_pixbuf, const point& d_pos) const = 0;
};
/// The interface of a blend algorithm.
class blend_interface
{
public:
virtual ~blend_interface() = 0;
/// \brief Blends two images with specified area and blend rate.
///
/// Semantics: \code dest_pixbuf = dest_pixbuf * fade_rate + scr_pixbuf * (1 - fade_rate); \endcode
/// The area is always valid, it is calculated by Nana before passing to the algorithm. So the area could be applied without a check.
virtual void process( const paint::pixel_buffer& src_pixbuf,
const nana::rectangle& src_area,
paint::pixel_buffer& dest_pixbuf,
const nana::point& dest_pos,
double fade_rate ///< blend rate in the range of [0, 1]
) const = 0;
};
/// The interface of line algorithm.
class line_interface
{
public:
virtual ~line_interface() = 0;
/// \brief Draws a line
///
/// Semantics: \code pixbuf = pixbuf * (1 - fade_rate) + color * fade_rate \endcode
/// The two points are calculated by Nana, they are always valid, and pos_beg.x <= pos_end.x
virtual void process(paint::pixel_buffer & pixbuf,
const nana::point& pos_beg, ///< left point
const nana::point& pos_end, ///< right point
nana::color_t color,
double fade_rate ///< blend rate in the range of [0, 1] If not 0, the line is blended to the pixbuf
) const = 0;
};
class blur_interface
{
public:
virtual ~blur_interface() = 0;
virtual void process(paint::pixel_buffer&, const nana::rectangle& r, std::size_t radius) const = 0;
};
}
}//end namespace paint
}//end namespace nana
#endif

View File

@@ -0,0 +1,71 @@
#ifndef NANA_PAINT_IMAGE_PROCESS_SELECTOR_HPP
#define NANA_PAINT_IMAGE_PROCESS_SELECTOR_HPP
#include "detail/image_process_provider.hpp"
namespace nana
{
namespace paint
{
namespace image_process
{ /// Configure the image processing algorithms.
class selector
{
public:
/// Selects an image processor through a specified name.
/*! if users give a non-existing name for choosing an image processor,
the call succeed, but no image processor would be replaced.
*/
void stretch(const std::string& name);
/// Inserts a new user-defined image processor for stretch.
template<typename ImageProcessor>
void add_stretch(const std::string& name)
{
detail::image_process_provider & p = detail::image_process_provider::instance();
p.add<ImageProcessor>(p.ref_stretch_tag(), name);
}
/// Selects an image process through a specified name.
void alpha_blend(const std::string& name);
/// Inserts a new user defined image process for alpha blend.
template<typename ImageProcessor>
void add_alpha_blend(const std::string& name)
{
detail::image_process_provider& p = detail::image_process_provider::instance();
p.add<ImageProcessor>(p.ref_alpha_blend_tag(), name);
}
/// Selects an image processor blend through a specified name.
void blend(const std::string& name);
/// Inserts a new user-defined image processor for blend.
template<typename ImageProcessor>
void add_blend(const std::string& name)
{
detail::image_process_provider& p = detail::image_process_provider::instance();
p.add<ImageProcessor>(p.ref_blend_tag(), name);
}
/// Selects an image processor through a specified name.
void line(const std::string& name);
/// Inserts a new user-defined image processor for line.
template<typename ImageProcessor>
void add_line(const std::string& name)
{
detail::image_process_provider & p = detail::image_process_provider::instance();
p.add<ImageProcessor>(p.ref_line_tag(), name);
}
/// blur - Selects an image procssor through a specified name.
void blur(const std::string& name);
/// Inserts a new user-defined image process for blur.
template<typename ImageProcessor>
void add_blur(const std::string& name)
{
detail::image_process_provider & p = detail::image_process_provider::instance();
p.add<ImageProcessor>(p.ref_blur_tag(), name);
}
};
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More