Merge branch 'hotfixes-1.0.1' into develop
Conflicts: .gitignore include/nana/deploy.hpp source/deploy.cpp source/gui/widgets/listbox.cpp
This commit is contained in:
commit
08e860a7e7
4
.gitignore
vendored
4
.gitignore
vendored
@ -24,6 +24,7 @@ bii/deps/*
|
||||
[Bb]in
|
||||
[Dd]ebug*/
|
||||
*.lib
|
||||
*.a
|
||||
*.sbr
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
@ -31,5 +32,4 @@ _ReSharper*/
|
||||
[Tt]est[Rr]esult*
|
||||
*.suo
|
||||
*.sdf
|
||||
|
||||
bii/.hive.db
|
||||
lib/
|
||||
|
||||
@ -1,20 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2013 for Windows Desktop
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{25B21068-491B-4A9F-B99F-6C27BF31BAAD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x64.Build.0 = Debug|x64
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|Win32.Build.0 = Release|Win32
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x64.ActiveCfg = Release|x64
|
||||
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@ -5,10 +5,18 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{25B21068-491B-4A9F-B99F-6C27BF31BAAD}</ProjectGuid>
|
||||
@ -22,6 +30,12 @@
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
@ -29,21 +43,48 @@
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>../bin/vc2013/</OutDir>
|
||||
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
|
||||
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
|
||||
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
|
||||
<OutDir>../bin/vc2013/</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>../bin/vc2013/</OutDir>
|
||||
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
|
||||
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
|
||||
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
|
||||
<OutDir>../bin/vc2013/</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
@ -52,13 +93,33 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\nana_debug.lib</OutputFile>
|
||||
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@ -70,6 +131,8 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -78,7 +141,28 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\nana_release.lib</OutputFile>
|
||||
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
1
extrlib/readme (2).txt
Normal file
1
extrlib/readme (2).txt
Normal file
@ -0,0 +1 @@
|
||||
The libpng.a is for MinGW(Not linux), and other .lib files are for VS2013
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
namespace nana
|
||||
{
|
||||
//A constant value for the invalid position.
|
||||
/// A constant value for the invalid position.
|
||||
const std::size_t npos = static_cast<std::size_t>(-1);
|
||||
|
||||
|
||||
@ -127,8 +127,7 @@ namespace nana
|
||||
|
||||
using pixel_color_t = pixel_argb_t;
|
||||
|
||||
//http://www.w3.org/TR/2011/REC-css3-color-20110607/
|
||||
//4.3. Extended color keywords
|
||||
/// See extended CSS color keywords (4.3) in http://www.w3.org/TR/2011/REC-css3-color-20110607/
|
||||
enum class colors
|
||||
{
|
||||
alice_blue = 0xf0f8ff,
|
||||
@ -283,7 +282,7 @@ namespace nana
|
||||
//temporary defintions, these will be replaced by color schema
|
||||
button_face_shadow_start = 0xF5F4F2,
|
||||
button_face_shadow_end = 0xD5D2CA,
|
||||
button_face = 0xD4D0C8,
|
||||
button_face = 0xD4D0C8 , //,light_cyan
|
||||
dark_border = 0x404040,
|
||||
gray_border = 0x808080,
|
||||
highlight = 0x1CC4F7
|
||||
@ -320,10 +319,10 @@ namespace nana
|
||||
|
||||
color blend(const color& bgcolor, bool ignore_bgcolor_alpha) const;
|
||||
|
||||
///< Blends two colors with the specified alpha, and the alpha values that come with these two colors are both ignored.
|
||||
/// Blends two colors with the specified alpha, and the alpha values that come with these two colors are both ignored.
|
||||
color blend(const color& bgcolor, double alpha) const;
|
||||
|
||||
///< Determines whether the color is completely transparent.
|
||||
/// Determines whether the color is completely transparent.
|
||||
bool invisible() const;
|
||||
pixel_color_t px_color() const;
|
||||
pixel_argb_t argb() const;
|
||||
@ -435,10 +434,10 @@ namespace nana
|
||||
unsigned height;
|
||||
};
|
||||
|
||||
class area_rotator
|
||||
class rectangle_rotator
|
||||
{
|
||||
public:
|
||||
area_rotator(bool rotated, const ::nana::rectangle& area);
|
||||
rectangle_rotator(bool rotated, const ::nana::rectangle& area);
|
||||
|
||||
int x() const;
|
||||
int & x_ref();
|
||||
@ -455,7 +454,7 @@ namespace nana
|
||||
private:
|
||||
bool rotated_;
|
||||
::nana::rectangle area_;
|
||||
};//end class area_rotator
|
||||
};//end class rectangle_rotator
|
||||
|
||||
enum class arrange
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nana Configuration
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -20,10 +20,13 @@
|
||||
#define PLATFORM_SPEC_HPP <nana/detail/win32/platform_spec.hpp>
|
||||
|
||||
//Test if it is MINGW
|
||||
#if defined(__MINGW32__)
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#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
|
||||
#if (__GNUC__ == 4) && ((__GNUC_MINOR__ < 8) || (__GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ < 1))
|
||||
//Use this flag if MinGW version is older than 4.8.1
|
||||
#define STD_THREAD_NOT_SUPPORTED
|
||||
#endif
|
||||
#endif
|
||||
#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC)
|
||||
//Linux:
|
||||
@ -35,6 +38,13 @@
|
||||
# static_assert(false, "Only Windows and Unix are support now");
|
||||
#endif
|
||||
|
||||
#if defined(NANA_MINGW) || defined(NANA_LINUX)
|
||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ <= 1)
|
||||
//Some functions which are specified in 21.5 Numeric conversions in Strings library have not yet implemented
|
||||
#define STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Here defines some flags that tell Nana what features will be supported.
|
||||
#define NANA_UNICODE
|
||||
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
#undef NANA_WINDOWS
|
||||
#endif
|
||||
|
||||
//Implement workarounds for MinGW
|
||||
#if defined(NANA_MINGW) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 8)
|
||||
//Implement workarounds for GCC/MinGW which version is below 4.8.2
|
||||
#if defined(STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED)
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::stoi in MinGW.
|
||||
|
||||
@ -172,7 +172,7 @@ namespace detail
|
||||
{
|
||||
int pending;
|
||||
{
|
||||
nana::detail::platform_scope_guard psg;
|
||||
nana::detail::platform_scope_guard lock;
|
||||
pending = ::XPending(display_);
|
||||
if(pending)
|
||||
{
|
||||
|
||||
@ -96,7 +96,8 @@ namespace nana
|
||||
//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
|
||||
os_insert = 0x2D, os_del ,
|
||||
os_end = 0x23 , os_home //Pos 1
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -166,7 +166,8 @@ namespace detail
|
||||
bool fullscreen :1; //When the window is maximizing whether it fit for fullscreen.
|
||||
bool borderless :1;
|
||||
bool make_bground_declared : 1; //explicitly make bground for bground effects
|
||||
unsigned Reserved :21;
|
||||
bool ignore_menubar_focus : 1; //A flag indicates whether the menubar sets the focus.
|
||||
unsigned Reserved :20;
|
||||
unsigned char tab; //indicate a window that can receive the keyboard TAB
|
||||
mouse_action action;
|
||||
}flags;
|
||||
@ -175,7 +176,6 @@ namespace detail
|
||||
{
|
||||
caret_descriptor* caret;
|
||||
std::shared_ptr<general_events> events_ptr;
|
||||
general_events* attached_events;
|
||||
}together;
|
||||
|
||||
widget_colors* scheme{ nullptr };
|
||||
|
||||
@ -54,13 +54,14 @@ namespace detail
|
||||
native_window_type root(core_window_t*);
|
||||
|
||||
void set_menubar_taken(core_window_t*);
|
||||
core_window_t* get_menubar_taken();
|
||||
|
||||
//Delay Restores focus when a menu which attached to menubar is closed
|
||||
void delay_restore(int);
|
||||
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 erase_menu(bool try_destroy);
|
||||
|
||||
void get_key_state(arg_keyboard&);
|
||||
bool set_keyboard_shortkey(bool yes);
|
||||
|
||||
@ -23,7 +23,6 @@ namespace nana
|
||||
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_;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Definition of General Events
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -19,7 +19,6 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -43,11 +42,13 @@ namespace nana
|
||||
void events_operation_cancel(event_handle);
|
||||
}//end namespace detail
|
||||
|
||||
/// base clase for all event argument types
|
||||
class event_arg
|
||||
{
|
||||
public:
|
||||
virtual ~event_arg();
|
||||
|
||||
/// ignorable handlers behind the current one in a chain of event handlers will not get called.
|
||||
void stop_propagation() const;
|
||||
bool propagation_stopped() const;
|
||||
private:
|
||||
@ -56,18 +57,19 @@ namespace nana
|
||||
|
||||
struct general_events;
|
||||
|
||||
/// the type of the members of general_events
|
||||
template<typename Arg>
|
||||
class basic_event : public detail::event_interface
|
||||
{
|
||||
public:
|
||||
typedef const typename std::remove_reference<Arg>::type & arg_reference;
|
||||
using arg_reference = const typename std::remove_reference<Arg>::type &;
|
||||
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 };
|
||||
bool unignorable{false};
|
||||
|
||||
@ -89,7 +91,38 @@ namespace nana
|
||||
return event_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
//class emit_counter is a RAII helper for emitting count
|
||||
//It is used for avoiding a try{}catch block which is required for some finial works when
|
||||
//event handlers throw exceptions.
|
||||
class emit_counter
|
||||
{
|
||||
public:
|
||||
emit_counter(basic_event* evt)
|
||||
: evt_{evt}
|
||||
{
|
||||
++evt->emitting_count_;
|
||||
}
|
||||
|
||||
~emit_counter()
|
||||
{
|
||||
if ((0 == --evt_->emitting_count_) && evt_->deleted_flags_)
|
||||
{
|
||||
evt_->deleted_flags_ = false;
|
||||
for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();)
|
||||
{
|
||||
if (i->get()->flag_deleted)
|
||||
i = evt_->dockers_->erase(i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
basic_event * const evt_;
|
||||
};
|
||||
public:
|
||||
/// It will get called firstly, because it is set at the beginning of the chain.
|
||||
template<typename Function>
|
||||
event_handle connect_front(Function && fn)
|
||||
{
|
||||
@ -112,6 +145,7 @@ namespace nana
|
||||
});
|
||||
}
|
||||
|
||||
/// It will not get called if stop_propagation() was called.
|
||||
template<typename Function>
|
||||
event_handle connect(Function && fn)
|
||||
{
|
||||
@ -127,13 +161,15 @@ namespace nana
|
||||
return evt;
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
/// It will not get called if stop_propagation() was called.
|
||||
template<typename Function>
|
||||
event_handle operator()(Function&& fn)
|
||||
{
|
||||
return connect(std::forward<Function>(fn));
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
/// It will get called because it is unignorable.
|
||||
template<typename Function>
|
||||
event_handle connect_unignorable(Function && fn, bool in_front = false)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
@ -157,54 +193,37 @@ namespace nana
|
||||
return (nullptr == dockers_ ? 0 : dockers_->size());
|
||||
}
|
||||
|
||||
void emit(arg_reference& arg) const
|
||||
void emit(arg_reference& arg)
|
||||
{
|
||||
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;
|
||||
emit_counter ec(this);
|
||||
|
||||
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();
|
||||
}
|
||||
const auto dockers_len = dockers.size();
|
||||
|
||||
auto output = transitory;
|
||||
for (auto & dck : dockers)
|
||||
//The dockers may resize when a new event handler is created by a calling handler.
|
||||
//Traverses with position can avaid crash error which caused by a iterator which becomes invalid.
|
||||
for (std::size_t pos = 0; pos < dockers_len; ++pos)
|
||||
{
|
||||
(*output++) = dck.get();
|
||||
}
|
||||
|
||||
bool stop_propagation = false;
|
||||
for (; transitory != output; ++transitory)
|
||||
{
|
||||
auto docker_ptr = *transitory;
|
||||
if (stop_propagation && !docker_ptr->unignorable)
|
||||
auto docker_ptr = dockers[pos].get();
|
||||
if (docker_ptr->flag_deleted)
|
||||
continue;
|
||||
|
||||
auto i = std::find_if(dockers.begin(), dockers.end(), [docker_ptr](std::unique_ptr<docker>& p){
|
||||
return (docker_ptr == p.get());
|
||||
});
|
||||
|
||||
if (i != dockers.end())
|
||||
docker_ptr->invoke(arg);
|
||||
if (arg.propagation_stopped())
|
||||
{
|
||||
docker_ptr->flag_entered = true;
|
||||
docker_ptr->invoke(arg);
|
||||
for (++pos; pos < dockers_len; ++pos)
|
||||
{
|
||||
auto docker_ptr = dockers[pos].get();
|
||||
if (!docker_ptr->unignorable || docker_ptr->flag_deleted)
|
||||
continue;
|
||||
|
||||
if (arg.propagation_stopped())
|
||||
stop_propagation = true;
|
||||
|
||||
docker_ptr->flag_entered = false;
|
||||
|
||||
if (docker_ptr->flag_deleted)
|
||||
dockers.erase(i);
|
||||
docker_ptr->invoke(arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -221,17 +240,20 @@ namespace nana
|
||||
internal_scope_guard lock;
|
||||
if (dockers_)
|
||||
{
|
||||
auto i = std::find_if(dockers_->begin(), dockers_->end(), [evt](const std::unique_ptr<docker>& sp)
|
||||
for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
|
||||
{
|
||||
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);
|
||||
if (reinterpret_cast<detail::docker_interface*>(evt) == i->get())
|
||||
{
|
||||
//Checks whether this event is working now.
|
||||
if (emitting_count_ > 1)
|
||||
{
|
||||
i->get()->flag_deleted = true;
|
||||
deleted_flags_ = true;
|
||||
}
|
||||
else
|
||||
dockers_->erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -392,22 +414,27 @@ namespace nana
|
||||
}
|
||||
};
|
||||
private:
|
||||
unsigned emitting_count_{ 0 };
|
||||
bool deleted_flags_{ false };
|
||||
std::unique_ptr<std::vector<std::unique_ptr<docker>>> dockers_;
|
||||
};
|
||||
|
||||
struct arg_mouse
|
||||
: public event_arg
|
||||
{
|
||||
event_code evt_code;
|
||||
::nana::window window_handle;
|
||||
::nana::point pos;
|
||||
bool left_button;
|
||||
bool mid_button;
|
||||
bool right_button;
|
||||
bool shift;
|
||||
bool ctrl;
|
||||
event_code evt_code; ///<
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
::nana::point pos; ///< cursor position in the event window
|
||||
bool left_button; ///< mouse left button is pressed?
|
||||
bool mid_button; ///< mouse middle button is pressed?
|
||||
bool right_button; ///< mouse right button is pressed?
|
||||
bool shift; ///< keyboard Shift is pressed?
|
||||
bool ctrl; ///< keyboard Ctrl is pressed?
|
||||
};
|
||||
|
||||
/// in arg_wheel event_code is event_code::mouse_wheel
|
||||
/// The type arg_wheel is derived from arg_mouse, a handler
|
||||
/// with prototype void(const arg_mouse&) can be set for mouse_wheel.
|
||||
struct arg_wheel : public arg_mouse
|
||||
{
|
||||
enum class wheel{
|
||||
@ -415,98 +442,99 @@ namespace nana
|
||||
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
|
||||
wheel which; ///< which wheel is rotated
|
||||
bool upwards; ///< true if the wheel is rotated to the top/left, depends on which and false otherwise
|
||||
unsigned distance; ///< expressed in multiples or divisions of 120
|
||||
};
|
||||
|
||||
struct arg_dropfiles : public event_arg
|
||||
struct arg_dropfiles : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
::nana::point pos;
|
||||
std::vector<nana::string> files;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
::nana::point pos; ///< cursor position in the event window
|
||||
std::vector<nana::string> files; ///< external filenames
|
||||
};
|
||||
|
||||
struct arg_expose : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
bool exposed;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
bool exposed; ///< the window is visible?
|
||||
};
|
||||
|
||||
struct arg_focus : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
::nana::native_window_type receiver;
|
||||
bool getting;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
::nana::native_window_type receiver; ///< it is a native window handle, and specified which window receives focus
|
||||
bool getting; ///< the window received focus?
|
||||
};
|
||||
|
||||
struct arg_keyboard : public event_arg
|
||||
{
|
||||
event_code evt_code;
|
||||
::nana::window window_handle;
|
||||
mutable nana::char_t key;
|
||||
mutable bool ignore;
|
||||
bool ctrl;
|
||||
bool shift;
|
||||
event_code evt_code; ///< it is event_code::key_press in current event
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
mutable nana::char_t key; ///< the key corresponding to the key pressed
|
||||
mutable bool ignore; ///< this member is not used
|
||||
bool ctrl; ///< keyboard Ctrl is pressed?
|
||||
bool shift; ///< keyboard Shift is pressed
|
||||
};
|
||||
|
||||
struct arg_move : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
int x;
|
||||
int y;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
int x; ///<
|
||||
int y; ///<
|
||||
};
|
||||
|
||||
struct arg_resized : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
unsigned width; ///< new width in pixels.
|
||||
unsigned height; ///< new height in pixels.
|
||||
};
|
||||
|
||||
struct arg_resizing : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
window_border border;
|
||||
mutable unsigned width;
|
||||
mutable unsigned height;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
window_border border; ///< the window is being resized by moving border
|
||||
mutable unsigned width; ///< new width in pixels. If it is modified, the window's width will be the modified value
|
||||
mutable unsigned height; ///< new height in pixels. If it is modified, the window's height will be the modified value
|
||||
};
|
||||
|
||||
struct arg_unload : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
mutable bool cancel;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
mutable bool cancel; ///<
|
||||
};
|
||||
|
||||
struct arg_destroy : public event_arg
|
||||
{
|
||||
::nana::window window_handle;
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
};
|
||||
|
||||
/// provides some fundamental events that every widget owns.
|
||||
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_mouse> mouse_enter; ///< the cursor enters the window
|
||||
basic_event<arg_mouse> mouse_move; ///< the cursor moves on the window
|
||||
basic_event<arg_mouse> mouse_leave; ///< the cursor leaves the window
|
||||
basic_event<arg_mouse> mouse_down; ///< the user presses the mouse button
|
||||
basic_event<arg_mouse> mouse_up; ///< the user presses the mouse button
|
||||
basic_event<arg_mouse> click; ///< the window is clicked, but occurs after mouse_down and before mouse_up
|
||||
basic_event<arg_mouse> dbl_click; ///< the window is double clicked
|
||||
basic_event<arg_wheel> mouse_wheel; ///< the mouse wheel rotates while the window has focus
|
||||
basic_event<arg_dropfiles> mouse_dropfiles; ///< the mouse drops some external data while the window enable accepting files
|
||||
basic_event<arg_expose> expose; ///< the visibility changes
|
||||
basic_event<arg_focus> focus; ///< the window receives or loses keyboard focus
|
||||
basic_event<arg_keyboard> key_press; ///< a key is pressed while the window has focus. event code is event_code::key_press
|
||||
basic_event<arg_keyboard> key_release; ///< a key is released while the window has focus. event code is event_code::key_release
|
||||
basic_event<arg_keyboard> key_char; ///< a character, whitespace or backspace is pressed. event code is event_code::key_char
|
||||
basic_event<arg_keyboard> shortkey; ///< a defined short key is pressed. event code is event_code::shortkey
|
||||
|
||||
basic_event<arg_move> move;
|
||||
basic_event<arg_resizing> resizing;
|
||||
basic_event<arg_resized> resized;
|
||||
basic_event<arg_move> move; ///< the window changes position
|
||||
basic_event<arg_resizing> resizing; ///< the window is changing its size
|
||||
basic_event<arg_resized> resized; ///< the window is changing its size
|
||||
|
||||
basic_event<arg_destroy> destroy;
|
||||
basic_event<arg_destroy> destroy; ///< the window is destroyed, but occurs when all children have been destroyed
|
||||
};
|
||||
|
||||
namespace detail
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -260,9 +259,14 @@ namespace nana
|
||||
{
|
||||
if(cond_type::is_queue(handle))
|
||||
{
|
||||
auto i = std::find(queue.begin(), queue.end(), handle);
|
||||
if(i != queue.end())
|
||||
queue.erase(i);
|
||||
for (auto i = queue.begin(); i != queue.end(); ++i)
|
||||
{
|
||||
if (handle == *i)
|
||||
{
|
||||
queue.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Implementations of Inner Forward Declaration
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -19,7 +19,6 @@
|
||||
#include "../../paint/graphics.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana{
|
||||
namespace detail
|
||||
@ -62,12 +61,15 @@ namespace nana{
|
||||
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);
|
||||
for (auto i = keybase_.begin(), end = keybase_.end(); i != end; ++i)
|
||||
{
|
||||
if (i->handle == wd)
|
||||
{
|
||||
keybase_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned long> keys(window wd) const
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* @file: nana/gui/place.cpp
|
||||
*
|
||||
* @contributions:
|
||||
* min/max and splitter bar initial weight by qPCR4vir.
|
||||
* min/max and splitter bar initial weight by Ariel Vina-Rodriguez.
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_PLACE_HPP
|
||||
|
||||
@ -77,6 +77,8 @@ namespace API
|
||||
window create_frame(window, const rectangle&, widget* attached);
|
||||
|
||||
paint::graphics* window_graphics(window);
|
||||
|
||||
void delay_restore(bool);
|
||||
}//end namespace dev
|
||||
|
||||
|
||||
@ -193,7 +195,7 @@ namespace API
|
||||
return *comp_wdg_colors;
|
||||
}
|
||||
|
||||
nana::point window_position(window);
|
||||
point window_position(window);
|
||||
void move_window(window, int x, int y);
|
||||
void move_window(window wd, const rectangle&);
|
||||
|
||||
@ -203,9 +205,11 @@ namespace API
|
||||
void draw_through(window, std::function<void()>);
|
||||
void map_through_widgets(window, native_drawable_type);
|
||||
|
||||
nana::size window_size(window);
|
||||
size window_size(window);
|
||||
void window_size(window, const size&);
|
||||
bool window_rectangle(window, rectangle&);
|
||||
size window_outline_size(window);
|
||||
void window_outline_size(window, const size&);
|
||||
bool get_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);
|
||||
@ -235,7 +239,7 @@ namespace API
|
||||
cursor window_cursor(window);
|
||||
|
||||
void activate_window(window);
|
||||
bool is_focus_window(window);
|
||||
bool is_focus_ready(window);
|
||||
window focus_window();
|
||||
void focus_window(window);
|
||||
|
||||
@ -288,7 +292,6 @@ namespace API
|
||||
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.
|
||||
|
||||
|
||||
@ -27,25 +27,37 @@ namespace nana
|
||||
/// The index of monitor.
|
||||
virtual std::size_t get_index() const = 0;
|
||||
|
||||
virtual bool is_primary_monitor() const = 0;
|
||||
|
||||
/// Returns the positional coordinates and size of the display device in reference to the desktop area
|
||||
virtual const ::nana::rectangle& area() const = 0;
|
||||
virtual const ::nana::rectangle& workarea() const = 0;
|
||||
};
|
||||
|
||||
class screen
|
||||
{
|
||||
struct implement;
|
||||
public:
|
||||
static ::nana::size desktop_size();
|
||||
static ::nana::size primary_monitor_size();
|
||||
static std::shared_ptr<display> from_point(const point&);
|
||||
static std::shared_ptr<display> from_window(window);
|
||||
|
||||
screen();
|
||||
|
||||
/// Reload has no preconditions, it's safe to call on moved-from
|
||||
void reload();
|
||||
|
||||
/// Returns the number of display monitors
|
||||
std::size_t count() const;
|
||||
|
||||
std::shared_ptr<display> get_display(std::size_t index) const;
|
||||
std::shared_ptr<display> get_primary() const;
|
||||
display& from_point(const point&);
|
||||
display& from_window(window);
|
||||
|
||||
display& get_display(std::size_t index) const;
|
||||
display& get_primary() const;
|
||||
|
||||
void for_each(std::function<void(display&)>) const;
|
||||
private:
|
||||
std::shared_ptr<implement> impl_;
|
||||
};
|
||||
}//end namespace nana
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/*
|
||||
/**
|
||||
* A Button Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 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
|
||||
* @file: nana/gui/widgets/button.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGET_BUTTON_HPP
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Categorize Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,7 +7,7 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/categorize.hpp
|
||||
* @file: nana/gui/widgets/categorize.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGET_CATEGORIZE_HPP
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/*
|
||||
/**
|
||||
* A CheckBox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 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
|
||||
* @file: nana/gui/widgets/checkbox.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGET_CHECKBOX_HPP
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,7 +7,7 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/combox.hpp
|
||||
* @file: nana/gui/widgets/combox.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGETS_COMBOX_HPP
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A date chooser Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
/**
|
||||
* A float_listbox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Form Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
/**
|
||||
* A Frame Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @file: nana/gui/widgets/frame.hpp
|
||||
*
|
||||
* A frame provides a way to contain the platform window in a stdex GUI Window
|
||||
* @brief A frame provides a way to contain the platform window in a stdex GUI Window
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGET_FRAME_HPP
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
/**
|
||||
* A Label Control Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A List Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -8,6 +8,7 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/listbox.hpp
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*
|
||||
*/
|
||||
|
||||
@ -16,6 +17,7 @@
|
||||
#include "widget.hpp"
|
||||
#include <nana/concepts.hpp>
|
||||
#include <nana/key_type.hpp>
|
||||
//#include <nana/paint/graphics.hpp>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
@ -27,7 +29,7 @@ namespace nana
|
||||
{
|
||||
namespace listbox
|
||||
{
|
||||
typedef std::size_t size_type;
|
||||
using size_type = std::size_t ;
|
||||
|
||||
struct cell
|
||||
{
|
||||
@ -35,7 +37,7 @@ namespace nana
|
||||
{
|
||||
::nana::color bgcolor;
|
||||
::nana::color fgcolor;
|
||||
|
||||
/// ::nana::paint::font font; \todo
|
||||
format() = default;
|
||||
format(const ::nana::color& bgcolor, const ::nana::color& fgcolor);
|
||||
};
|
||||
@ -112,7 +114,8 @@ namespace nana
|
||||
std::size_t pos_{0};
|
||||
};
|
||||
|
||||
struct index_pair
|
||||
/// usefull for both absolute and display (sorted) positions
|
||||
struct index_pair
|
||||
{
|
||||
size_type cat; //The pos of category
|
||||
size_type item; //the pos of item in a category.
|
||||
@ -169,7 +172,8 @@ namespace nana
|
||||
class drawer_header_impl;
|
||||
class drawer_lister_impl;
|
||||
|
||||
class trigger: public drawer_trigger
|
||||
/// mostly works on display positions
|
||||
class trigger: public drawer_trigger
|
||||
{
|
||||
public:
|
||||
trigger();
|
||||
@ -192,19 +196,29 @@ namespace nana
|
||||
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;
|
||||
void key_char(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
|
||||
/// operate with absolute positions and contain only the position but montain pointers to parts of the real items
|
||||
/// item_proxy self, it references and iterators are not invalidated by sort()
|
||||
class item_proxy
|
||||
: public std::iterator<std::input_iterator_tag, item_proxy>
|
||||
{
|
||||
public:
|
||||
item_proxy(essence_t*);
|
||||
item_proxy(essence_t*, const index_pair&);
|
||||
|
||||
/// the main porpose of this it to make obvious that item_proxy operate with absolute positions, and dont get moved during sort()
|
||||
static item_proxy from_display(essence_t *ess, const index_pair &relative) ;
|
||||
item_proxy from_display(const index_pair &relative) const;
|
||||
|
||||
/// posible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort()
|
||||
index_pair to_display() const;
|
||||
|
||||
bool empty() const;
|
||||
|
||||
item_proxy & check(bool ck);
|
||||
@ -237,7 +251,7 @@ namespace nana
|
||||
auto && cells = ores.move_cells();
|
||||
auto cols = columns();
|
||||
cells.resize(cols);
|
||||
for (auto pos = 0; pos < cols; ++pos)
|
||||
for (auto pos = 0u; pos < cols; ++pos)
|
||||
{
|
||||
auto & el = cells[pos];
|
||||
if (el.text.size() == 1 && el.text[0] == nana::char_t(0))
|
||||
@ -318,8 +332,8 @@ namespace nana
|
||||
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;
|
||||
nana::any * _m_value(bool alloc_if_empty);
|
||||
const nana::any * _m_value() const;
|
||||
private:
|
||||
essence_t * ess_;
|
||||
category_t* cat_{nullptr};
|
||||
@ -334,7 +348,7 @@ namespace nana
|
||||
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.
|
||||
/// Append an item at abs 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)
|
||||
{
|
||||
@ -367,13 +381,18 @@ namespace nana
|
||||
item_proxy cbegin() const;
|
||||
item_proxy cend() const;
|
||||
|
||||
item_proxy at(size_type pos) const;
|
||||
item_proxy at(size_type pos_abs) 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.
|
||||
/// Returns the absolute index of a item by its display pos, the index of the item isn't changed after sorting.
|
||||
/// convert from display order to absolute (find the real item in that display pos) but without check from current active sorting, in fact using just the last sorting !!!
|
||||
size_type index_by_display_order(size_type disp_order) const;
|
||||
size_type display_order(size_type pos) const;
|
||||
size_type position() const;
|
||||
|
||||
/// find display order for the real item but without check from current active sorting, in fact using just the last sorting !!!
|
||||
size_type display_order(size_type pos) const;
|
||||
|
||||
/// this cat position
|
||||
size_type position() const;
|
||||
|
||||
/// Returns the number of items
|
||||
size_type size() const;
|
||||
@ -410,9 +429,21 @@ namespace nana
|
||||
private:
|
||||
essence_t* ess_{nullptr};
|
||||
category_t* cat_{nullptr};
|
||||
size_type pos_{0};
|
||||
size_type pos_{0}; ///< Absolute position, not relative to display, and dont change during sort()
|
||||
};
|
||||
}
|
||||
|
||||
struct export_options
|
||||
{
|
||||
nana::string sep = nana::string {STR("\t" )},
|
||||
endl= nana::string {STR("\n")} ;
|
||||
bool only_selected_items{true},
|
||||
only_checked_items {false},
|
||||
only_visible_columns{true};
|
||||
|
||||
using columns_indexs = std::vector<size_type>;
|
||||
columns_indexs columns_order;
|
||||
};
|
||||
}
|
||||
}//end namespace drawerbase
|
||||
|
||||
struct arg_listbox
|
||||
@ -446,12 +477,12 @@ namespace nana
|
||||
}
|
||||
}//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.
|
||||
/*! \brief A rectangle containing a list of strings from which the user can select. This widget contain a list of \a categories, with in turn contain a list of \a items.
|
||||
A category is a text with can be \a selected, \a checked and \a expanded to show the items.
|
||||
An item is formed by \a column-fields, each corresponding to one of the \a headers.
|
||||
An item can be \a selected and \a checked.
|
||||
The user can \a drag the header to \a reisize it or to \a reorganize it.
|
||||
By \a clicking on a header the list get \a reordered, first up, and then down alternatively,
|
||||
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, drawerbase::listbox::scheme>,
|
||||
@ -465,7 +496,9 @@ By \a clicking on a header the list get \a reordered, first up, and then down al
|
||||
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;
|
||||
using cell = drawerbase::listbox::cell;
|
||||
using export_options= drawerbase::listbox::export_options;
|
||||
using columns_indexs= drawerbase::listbox::size_type;
|
||||
public:
|
||||
listbox() = default;
|
||||
listbox(window, bool visible);
|
||||
@ -481,8 +514,11 @@ By \a clicking on a header the list get \a reordered, first up, and then down al
|
||||
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;
|
||||
|
||||
/// add categories in order when use a key?
|
||||
listbox& ordered_categories(bool);
|
||||
|
||||
/// return a proxy to tha cat with the key or create a new one in the right order
|
||||
template<typename Key>
|
||||
cat_proxy operator[](const Key & ck)
|
||||
{
|
||||
@ -507,7 +543,7 @@ By \a clicking on a header the list get \a reordered, first up, and then down al
|
||||
return cat_proxy(&_m_ess(), _m_at_key(p));
|
||||
}
|
||||
|
||||
item_proxy at(const index_pair&) const;
|
||||
item_proxy at(const index_pair &abs_pos) const;
|
||||
|
||||
void insert(const index_pair&, nana::string); ///<Insert a new item with a text in the first column.
|
||||
|
||||
@ -536,20 +572,26 @@ By \a clicking on a header the list get \a reordered, first up, and then down al
|
||||
_m_ease_key(&key);
|
||||
}
|
||||
|
||||
///Sets a strick weak ordering comparer for a column
|
||||
bool sortable() const;
|
||||
void sortable(bool enable);
|
||||
|
||||
///Sets a strict 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);
|
||||
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void sort_col(size_type col, bool reverse = false);
|
||||
size_type sort_col() const;
|
||||
void unsort();
|
||||
|
||||
/// potencially ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void unsort();
|
||||
bool freeze_sort(bool freeze);
|
||||
|
||||
selection selected() const; ///<Get the indexs of all the selected items
|
||||
|
||||
selection selected() const; ///<Get the absolute 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.
|
||||
void move_select(bool upwards); ///<Selects an item besides the current selected item in the display.
|
||||
|
||||
size_type size_categ() const; ///<Get the number of categories
|
||||
size_type size_item() const; ///<The number of items in the default category
|
||||
@ -557,6 +599,7 @@ By \a clicking on a header the list get \a reordered, first up, and then down al
|
||||
|
||||
void enable_single(bool for_selection, bool category_limited);
|
||||
void disable_single(bool for_selection);
|
||||
export_options& def_export_options();
|
||||
private:
|
||||
drawerbase::listbox::essence_t & _m_ess() const;
|
||||
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Menu implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -139,16 +139,16 @@ namespace nana
|
||||
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 image(std::size_t pos, const paint::image& icon);
|
||||
void check_style(std::size_t pos, checks);
|
||||
void checked(std::size_t pos, bool);
|
||||
bool checked(std::size_t pos) const;
|
||||
void enabled(std::size_t pos, bool);///< Enables or disables the mouse or keyboard input for the item.
|
||||
bool enabled(std::size_t pos) const;
|
||||
void erase(std::size_t pos); ///< Removes the item
|
||||
bool link(std::size_t pos, menu& menu_obj);///< Link a menu to the item as a sub menu.
|
||||
menu * link(std::size_t pos); ///< Retrieves a linked sub menu of the item.
|
||||
menu *create_sub_menu(std::size_t pos);
|
||||
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.
|
||||
@ -171,7 +171,6 @@ namespace nana
|
||||
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_;
|
||||
|
||||
@ -24,12 +24,16 @@ namespace nana
|
||||
class item_renderer
|
||||
{
|
||||
public:
|
||||
enum state_t{state_normal, state_highlight, state_selected};
|
||||
typedef nana::paint::graphics& graph_reference;
|
||||
enum class state
|
||||
{
|
||||
normal, highlighted, selected
|
||||
};
|
||||
|
||||
using graph_reference = paint::graphics&;
|
||||
|
||||
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);
|
||||
virtual void background(const point&, const ::nana::size&, state);
|
||||
virtual void caption(const point&, const ::nana::string&);
|
||||
private:
|
||||
window handle_;
|
||||
graph_reference graph_;
|
||||
@ -61,7 +65,6 @@ namespace nana
|
||||
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();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Panel Implementation
|
||||
* Nana C++ Library(http://www.nanaro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -8,8 +8,10 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/panel.hpp
|
||||
* @author: Jinhao
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*
|
||||
* @brief: panel is a widget used for placing some widgets.
|
||||
* @brief panel is a widget used for placing some widgets.
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGETS_PANEL_HPP
|
||||
@ -44,11 +46,13 @@ namespace nana
|
||||
panel(window wd, bool visible)
|
||||
{
|
||||
this->create(wd, rectangle(), visible);
|
||||
this->bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
panel(window wd, const nana::rectangle& r = rectangle(), bool visible = true)
|
||||
{
|
||||
this->create(wd, r, visible);
|
||||
this->bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
bool transparent() const
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Picture Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @file: nana/gui/widgets/picture.hpp
|
||||
*
|
||||
* Used for showing a picture
|
||||
* @brief Used for showing a picture
|
||||
*/
|
||||
#ifndef NANA_GUI_WIDGET_PICTURE_HPP
|
||||
#define NANA_GUI_WIDGET_PICTURE_HPP
|
||||
@ -34,7 +34,7 @@ namespace nana
|
||||
void attached(widget_reference, graph_reference) override;
|
||||
private:
|
||||
void refresh(graph_reference) override;
|
||||
void _m_draw_background();
|
||||
void _m_draw_background(unsigned,unsigned);
|
||||
private:
|
||||
implement * const impl_;
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Progress Indicator Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Scroll Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -8,6 +8,7 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/scroll.hpp
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
#ifndef NANA_GUI_WIDGET_SCROLL_HPP
|
||||
#define NANA_GUI_WIDGET_SCROLL_HPP
|
||||
@ -49,17 +50,17 @@ namespace nana
|
||||
|
||||
struct metrics_type
|
||||
{
|
||||
typedef std::size_t size_type;
|
||||
using size_type = std::size_t;
|
||||
|
||||
size_type peak;
|
||||
size_type range;
|
||||
size_type step;
|
||||
size_type value;
|
||||
size_type peak; ///< the whole total
|
||||
size_type range; ///< how many is shonw on a page, that is, How many to scroll after click on first or second
|
||||
size_type step; ///< how many to scroll by click in forward or backward
|
||||
size_type value; ///< current offset calculated from the very beginnig
|
||||
|
||||
buttons what;
|
||||
bool pressed;
|
||||
size_type scroll_length;
|
||||
int scroll_pos;
|
||||
size_type scroll_length; ///< the lenght in pixels of the central button show how many of the total (peak) is shonw (range)
|
||||
int scroll_pos; ///< in pixels, and correspond to the offsset from the very beginning (value)
|
||||
int scroll_mouse_offset;
|
||||
|
||||
metrics_type();
|
||||
@ -70,11 +71,11 @@ namespace nana
|
||||
public:
|
||||
struct states
|
||||
{
|
||||
enum{none, highlight, actived, selected};
|
||||
enum{ none, highlight, actived, selected };
|
||||
};
|
||||
|
||||
typedef nana::paint::graphics& graph_reference;
|
||||
const static unsigned fixedsize = 16;
|
||||
using graph_reference = paint::graphics&;
|
||||
const static unsigned fixedsize = 16; // make it part of a new "metric" in the widget_scheme
|
||||
|
||||
drawer(metrics_type& m);
|
||||
void set_vertical(bool);
|
||||
@ -114,7 +115,7 @@ namespace nana
|
||||
|
||||
void peak(size_type s)
|
||||
{
|
||||
if(graph_ && (metrics_.peak != s))
|
||||
if (graph_ && (metrics_.peak != s))
|
||||
{
|
||||
metrics_.peak = s;
|
||||
API::refresh_window(widget_->handle());
|
||||
@ -123,10 +124,10 @@ namespace nana
|
||||
|
||||
void value(size_type s)
|
||||
{
|
||||
if(s + metrics_.range > metrics_.peak)
|
||||
if (s + metrics_.range > metrics_.peak)
|
||||
s = metrics_.peak - metrics_.range;
|
||||
|
||||
if(graph_ && (metrics_.value != s))
|
||||
if (graph_ && (metrics_.value != s))
|
||||
{
|
||||
metrics_.value = s;
|
||||
_m_emit_value_changed();
|
||||
@ -137,7 +138,7 @@ namespace nana
|
||||
|
||||
void range(size_type s)
|
||||
{
|
||||
if(graph_ && (metrics_.range != s))
|
||||
if (graph_ && (metrics_.range != s))
|
||||
{
|
||||
metrics_.range = s;
|
||||
API::refresh_window(widget_->handle());
|
||||
@ -151,31 +152,31 @@ namespace nana
|
||||
|
||||
bool make_step(bool forward, unsigned multiple)
|
||||
{
|
||||
if(graph_)
|
||||
if (graph_)
|
||||
{
|
||||
size_type step = (multiple > 1 ? metrics_.step * multiple : metrics_.step);
|
||||
size_type value = metrics_.value;
|
||||
if(forward)
|
||||
if (forward)
|
||||
{
|
||||
size_type maxv = metrics_.peak - metrics_.range;
|
||||
if(metrics_.peak > metrics_.range && value < maxv)
|
||||
if (metrics_.peak > metrics_.range && value < maxv)
|
||||
{
|
||||
if(maxv - value >= step)
|
||||
if (maxv - value >= step)
|
||||
value += step;
|
||||
else
|
||||
value = maxv;
|
||||
}
|
||||
}
|
||||
else if(value)
|
||||
else if (value)
|
||||
{
|
||||
if(value > step)
|
||||
if (value > step)
|
||||
value -= step;
|
||||
else
|
||||
value = 0;
|
||||
}
|
||||
size_type cmpvalue = metrics_.value;
|
||||
metrics_.value = value;
|
||||
if(value != cmpvalue)
|
||||
if (value != cmpvalue)
|
||||
{
|
||||
_m_emit_value_changed();
|
||||
return true;
|
||||
@ -221,24 +222,24 @@ namespace nana
|
||||
void mouse_move(graph_reference graph, const ::nana::arg_mouse& arg) override
|
||||
{
|
||||
bool redraw = false;
|
||||
if(metrics_.pressed && (metrics_.what == buttons::scroll))
|
||||
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)
|
||||
if (cmpvalue != metrics_.value)
|
||||
_m_emit_value_changed();
|
||||
redraw = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
buttons what = drawer_.what(graph, arg.pos);
|
||||
if(metrics_.what != what)
|
||||
if (metrics_.what != what)
|
||||
{
|
||||
redraw = true;
|
||||
metrics_.what = what;
|
||||
}
|
||||
}
|
||||
if(redraw)
|
||||
if (redraw)
|
||||
{
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
API::lazy_refresh();
|
||||
@ -247,11 +248,11 @@ namespace nana
|
||||
|
||||
void mouse_down(graph_reference graph, const arg_mouse& arg) override
|
||||
{
|
||||
if(arg.left_button)
|
||||
if (arg.left_button)
|
||||
{
|
||||
metrics_.pressed = true;
|
||||
metrics_.what = drawer_.what(graph, arg.pos);
|
||||
switch(metrics_.what)
|
||||
switch (metrics_.what)
|
||||
{
|
||||
case buttons::first:
|
||||
case buttons::second:
|
||||
@ -265,13 +266,13 @@ namespace nana
|
||||
break;
|
||||
case buttons::forward:
|
||||
case buttons::backward:
|
||||
{
|
||||
size_type cmpvalue = metrics_.value;
|
||||
drawer_.auto_scroll();
|
||||
if(cmpvalue != metrics_.value)
|
||||
_m_emit_value_changed();
|
||||
}
|
||||
break;
|
||||
{
|
||||
size_type cmpvalue = metrics_.value;
|
||||
drawer_.auto_scroll();
|
||||
if (cmpvalue != metrics_.value)
|
||||
_m_emit_value_changed();
|
||||
}
|
||||
break;
|
||||
default: //Ignore buttons::none
|
||||
break;
|
||||
}
|
||||
@ -294,7 +295,7 @@ namespace nana
|
||||
|
||||
void mouse_leave(graph_reference graph, const arg_mouse&) override
|
||||
{
|
||||
if(metrics_.pressed) return;
|
||||
if (metrics_.pressed) return;
|
||||
|
||||
metrics_.what = buttons::none;
|
||||
drawer_.draw(graph, buttons::none);
|
||||
@ -303,7 +304,7 @@ namespace nana
|
||||
|
||||
void mouse_wheel(graph_reference graph, const arg_wheel& arg) override
|
||||
{
|
||||
if(make_step(arg.upwards == false, 3))
|
||||
if (make_step(arg.upwards == false, 3))
|
||||
{
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
API::lazy_refresh();
|
||||
@ -333,7 +334,7 @@ namespace nana
|
||||
|
||||
/// Provides a way to display an object which is larger than the window's client area.
|
||||
template<bool Vertical>
|
||||
class scroll
|
||||
class scroll // add a widget scheme?
|
||||
: 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;
|
||||
@ -345,29 +346,29 @@ namespace nana
|
||||
|
||||
/// \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.
|
||||
/// @param visible specify the visibility after creation.
|
||||
scroll(window wd, bool visible)
|
||||
{
|
||||
this->create(wd, rectangle(), visible);
|
||||
this->create(wd, rectangle(), visible); // add a widget scheme? and take some colors from these wd?
|
||||
}
|
||||
|
||||
/// \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.
|
||||
/// @param visible specify the visibility after creation.
|
||||
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.
|
||||
/// @param for_less whether it can be scrolled for a less value (backward or "up" if true, forward or "down" if false).
|
||||
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));
|
||||
}
|
||||
|
||||
/// the whole total (peak)
|
||||
size_type amount() const
|
||||
{
|
||||
return this->get_drawer_trigger().metrics().peak;
|
||||
@ -378,7 +379,7 @@ namespace nana
|
||||
return this->get_drawer_trigger().peak(Max);
|
||||
}
|
||||
|
||||
/// Get the range of the widget.
|
||||
/// Get the range of the widget (how many is shonw on a page, that is, How many to scroll after click on first or second)
|
||||
size_type range() const
|
||||
{
|
||||
return this->get_drawer_trigger().metrics().range;
|
||||
@ -390,7 +391,7 @@ namespace nana
|
||||
return this->get_drawer_trigger().range(r);
|
||||
}
|
||||
|
||||
/// \brief Get the value.
|
||||
/// \brief Get the value (current offset calculated from the very beginnig)
|
||||
/// @return the value.
|
||||
size_type value() const
|
||||
{
|
||||
@ -419,12 +420,12 @@ namespace nana
|
||||
return this->get_drawer_trigger().step(s);
|
||||
}
|
||||
|
||||
/// \brief Increase/decrease values by a step.
|
||||
/// \brief Increase/decrease values by a step (alternativelly by some number of steps).
|
||||
/// @param forward it determines whether increase or decrease.
|
||||
/// @return true if the value is changed.
|
||||
bool make_step(bool forward)
|
||||
bool make_step(bool forward, unsigned steps = 1)
|
||||
{
|
||||
if(this->get_drawer_trigger().make_step(forward, 1))
|
||||
if (this->get_drawer_trigger().make_step(forward, steps))
|
||||
{
|
||||
API::refresh_window(this->handle());
|
||||
return true;
|
||||
@ -437,13 +438,17 @@ namespace nana
|
||||
/// @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;
|
||||
return this->make_step(forward, 3); // set this 3 in the metrics of the widget scheme ?
|
||||
}
|
||||
|
||||
/// \brief Increase/decrease values by a page as if it is scrolled page up.
|
||||
/// @param forward it determines whether increase or decrease.
|
||||
/// @return true if the vlaue is changed.
|
||||
bool make_page_scroll(bool forward)
|
||||
{
|
||||
return this->make_step(forward, range() - 1);
|
||||
}
|
||||
|
||||
};//end class scroll
|
||||
}//end namespace nana
|
||||
#endif
|
||||
|
||||
@ -157,7 +157,8 @@ namespace nana{ namespace widgets
|
||||
|
||||
void set_accept(std::function<bool(char_type)>);
|
||||
void set_accept(accepts);
|
||||
bool respone_keyboard(char_type);
|
||||
bool respond_char(char_type);
|
||||
bool respond_key(char_type);
|
||||
|
||||
void typeface_changed();
|
||||
|
||||
@ -227,7 +228,6 @@ namespace nana{ namespace widgets
|
||||
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();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Slider Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Spin box widget
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Tabbar implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,8 +7,8 @@
|
||||
* (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.
|
||||
* @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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Textbox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Toolbar Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Tree Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,12 +7,12 @@
|
||||
* (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:
|
||||
* @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.
|
||||
* The treebox would have a vertical scrollbar if there are too many nodes
|
||||
* to display. It does not have an horizontal scrollbar:
|
||||
* the widget will adjust the node's displaying position for fitting.
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGETS_TREEBOX_HPP
|
||||
@ -332,12 +332,13 @@ namespace nana
|
||||
}//end namespace treebox
|
||||
}//end namespace drawerbase
|
||||
|
||||
struct arg_treebox
|
||||
/// a type of treebox event parameter
|
||||
struct arg_treebox
|
||||
: public event_arg
|
||||
{
|
||||
treebox& widget;
|
||||
drawerbase::treebox::item_proxy & item;
|
||||
bool operated;
|
||||
treebox& widget; ///< where the event occurs
|
||||
drawerbase::treebox::item_proxy & item; ///< the operated node
|
||||
bool operated; ///< operation state of the event
|
||||
|
||||
arg_treebox(treebox&, drawerbase::treebox::item_proxy&, bool operated);
|
||||
};
|
||||
@ -349,28 +350,30 @@ namespace nana
|
||||
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;
|
||||
basic_event<arg_treebox> expanded; ///< a user expands or shrinks a node
|
||||
basic_event<arg_treebox> checked; ///< a user checks or unchecks a node
|
||||
basic_event<arg_treebox> selected; ///< a user selects or unselects a node
|
||||
basic_event<arg_treebox> hovered; ///< a user moves the cursor over a node
|
||||
};
|
||||
}//end namespace treebox
|
||||
}//end namespace drawerbase
|
||||
|
||||
/// Displays a hierarchical list of items, such as the files and directories on a disk.
|
||||
class treebox
|
||||
/// \brief Displays a hierarchical list of items, such as the files and directories on a disk.
|
||||
/// See also in [documentation](http://nanapro.org/en-us/help/widgets/treebox.htm)
|
||||
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.
|
||||
/// A type refers to the item and is also used to iterate through the nodes.
|
||||
typedef drawerbase::treebox::item_proxy item_proxy;
|
||||
|
||||
/// state images for the node
|
||||
typedef drawerbase::treebox::node_image_tag node_image_type;
|
||||
|
||||
/// The interface of treebox item renderer
|
||||
/// The interface of treebox user-defined item renderer
|
||||
typedef drawerbase::treebox::renderer_interface renderer_interface;
|
||||
|
||||
/// The interface of treebox compset_placer
|
||||
/// The interface of treebox compset_placer to define the position of node components
|
||||
typedef drawerbase::treebox::compset_placer_interface compset_placer_interface;
|
||||
|
||||
/// The default constructor without creating the widget.
|
||||
@ -378,7 +381,7 @@ namespace nana
|
||||
|
||||
/// \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.
|
||||
/// @param visible specifying the visibility after creating.
|
||||
treebox(window wd, bool visible);
|
||||
|
||||
/// \brief The construct that creates a widget.
|
||||
@ -388,16 +391,16 @@ namespace nana
|
||||
treebox(window, const nana::rectangle& = rectangle(), bool visible = true);
|
||||
|
||||
template<typename ItemRenderer>
|
||||
treebox & renderer(const ItemRenderer & rd)
|
||||
treebox & renderer(const ItemRenderer & rd) ///< set user-defined node renderer
|
||||
{
|
||||
get_drawer_trigger().renderer(::nana::pat::cloneable<renderer_interface>(rd));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const nana::pat::cloneable<renderer_interface> & renderer() const;
|
||||
const nana::pat::cloneable<renderer_interface> & renderer() const; ///< get user-defined node renderer
|
||||
|
||||
template<typename Placer>
|
||||
treebox & placer(const Placer & r)
|
||||
treebox & placer(const Placer & r) ///< location of a node components
|
||||
{
|
||||
get_drawer_trigger().placer(::nana::pat::cloneable<compset_placer_interface>(r));
|
||||
return *this;
|
||||
@ -406,38 +409,51 @@ namespace nana
|
||||
const nana::pat::cloneable<compset_placer_interface> & placer() const;
|
||||
|
||||
/// \brief Eanble the widget to be draws automatically when it is operated.
|
||||
///
|
||||
/// The treebox automatically redraws after certain operations, but,
|
||||
/// under some circumstances, it is good to disable the automatic drawing mode,
|
||||
/// for example, before adding nodes in a loop, disable the mode to avoiding
|
||||
/// frequent and useless refresh for better performance, and then, after
|
||||
/// the operations, enable the automatic redraw mode again.
|
||||
/// @param bool whether to enable.
|
||||
void auto_draw(bool);
|
||||
|
||||
/// \brief Enable the checkbox for each item of the widget.
|
||||
/// @param bool wheter to enable.
|
||||
/// \brief Enable the checkboxs for each item of the widget.
|
||||
/// @param bool indicates whether to show or hide the checkboxs.
|
||||
treebox & checkable(bool enable);
|
||||
|
||||
/// Determinte whether the checkbox is enabled.
|
||||
bool checkable() const;
|
||||
|
||||
bool checkable() const; ///< Determinte whether the checkboxs are enabled.
|
||||
|
||||
node_image_type& icon(const nana::string& id) const;
|
||||
/// \brief Creates an icon scheme with the specified name.
|
||||
///
|
||||
/// The icon scheme includes 3 images for node states.
|
||||
/// These states are 'normal', 'hovered' and 'expanded'.
|
||||
/// If 'hovered' or 'expanded' are not set, it uses 'normal' state image for these 2 states.
|
||||
/// See also in [documentation](http://nanapro.org/en-us/help/widgets/treebox.htm)
|
||||
node_image_type& icon(const nana::string& id ///< the name of an icon scheme. If the name is not existing, it creates a new scheme for the name.
|
||||
) 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
|
||||
item_proxy insert(const nana::string& path_key, ///< specifies the node hierarchy
|
||||
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.
|
||||
nana::string title ///< title used for displaying in the new node.
|
||||
);
|
||||
item_proxy erase(item_proxy i);
|
||||
item_proxy erase(item_proxy i); ///< Removes the node at pos and return the Item proxy following the removed node
|
||||
|
||||
void erase(const nana::string& keypath);
|
||||
void erase(const nana::string& keypath); ///< Removes the node by the key path.
|
||||
|
||||
nana::string make_key_path(item_proxy i, const nana::string& splitter) const;///<returns the key path
|
||||
item_proxy selected() const;
|
||||
item_proxy selected() const; ///< returns the selected node
|
||||
};//end class treebox
|
||||
}//end namespace nana
|
||||
#endif
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* The fundamental widget class implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -409,6 +409,16 @@ namespace nana
|
||||
{
|
||||
API::map_through_widgets(handle(), drawable);
|
||||
}
|
||||
|
||||
void outline_size(const ::nana::size& sz)
|
||||
{
|
||||
API::window_outline_size(handle(), sz);
|
||||
}
|
||||
|
||||
::nana::size outline_size() const
|
||||
{
|
||||
return API::window_outline_size(handle());
|
||||
}
|
||||
protected:
|
||||
DrawerTrigger& get_drawer_trigger()
|
||||
{
|
||||
|
||||
@ -22,10 +22,10 @@ namespace nana
|
||||
virtual ~key_interface(){}
|
||||
|
||||
virtual bool same_type(const key_interface*) const = 0;
|
||||
virtual bool compare(const key_interface*) const = 0;
|
||||
virtual bool compare(const key_interface*) const = 0; ///< is this key less than right key? [call it less(rk), less_than(rk) or compare_less(rk)?: if (lk.less_than(rk )) ]
|
||||
}; //end class key_interface
|
||||
|
||||
//Use less compare for equal compare
|
||||
//Use less compare for equal compare [call it equal_by_less()?]
|
||||
inline bool pred_equal_by_less(const key_interface * left, const key_interface* right)
|
||||
{
|
||||
return (left->compare(right) == false) && (right->compare(left) == false);
|
||||
|
||||
@ -1,3 +1,15 @@
|
||||
/*
|
||||
* Bitmap Format Graphics Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 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_bmp.hpp
|
||||
* @contributors: Ryan Gonzalez
|
||||
*/
|
||||
#ifndef NANA_PAINT_DETAIL_IMAGE_BMP_HPP
|
||||
#define NANA_PAINT_DETAIL_IMAGE_BMP_HPP
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Paint Image Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -39,6 +40,8 @@ namespace paint
|
||||
bool empty() const;
|
||||
operator unspecified_bool_t() const;
|
||||
void close();
|
||||
|
||||
bool alpha() const;
|
||||
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.
|
||||
|
||||
@ -14,7 +14,13 @@
|
||||
#define NANA_SYSTEM_DATAEXCH_HPP
|
||||
#include <nana/basic_types.hpp>
|
||||
|
||||
namespace nana{ namespace system{
|
||||
namespace nana{
|
||||
|
||||
namespace paint{
|
||||
class graphics;
|
||||
}
|
||||
|
||||
namespace system{
|
||||
/// a data exchange mechanism through Windows Clipboard, X11 Selection.
|
||||
class dataexch
|
||||
{
|
||||
@ -26,6 +32,7 @@ namespace nana{ namespace system{
|
||||
|
||||
void set(const nana::char_t* text);
|
||||
void set(const nana::string& text);
|
||||
bool set(const nana::paint::graphics& g);
|
||||
void get(nana::string& str);
|
||||
private:
|
||||
bool _m_set(unsigned type, const void* buf, std::size_t size);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/basic_types.cpp
|
||||
* @contributos: Jan
|
||||
*/
|
||||
|
||||
#include <nana/basic_types.hpp>
|
||||
@ -18,6 +19,8 @@
|
||||
#endif
|
||||
#include <algorithm>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
//class color
|
||||
@ -736,12 +739,12 @@ namespace nana
|
||||
|
||||
int rectangle::right() const
|
||||
{
|
||||
return static_cast<int>(x + width);
|
||||
return x + static_cast<int>(width);
|
||||
}
|
||||
|
||||
int rectangle::bottom() const
|
||||
{
|
||||
return static_cast<int>(y + height);
|
||||
return y + static_cast<int>(height);
|
||||
}
|
||||
|
||||
bool rectangle::is_hit(int pos_x, int pos_y) const
|
||||
@ -753,7 +756,7 @@ namespace nana
|
||||
bool rectangle::is_hit(const point& pos) const
|
||||
{
|
||||
return (x <= pos.x && pos.x < x + static_cast<int>(width)) &&
|
||||
(y <= pos.y && pos.y < y + static_cast<int>(height));
|
||||
(y <= pos.y && pos.y < y + static_cast<int>(height));
|
||||
}
|
||||
|
||||
bool rectangle::empty() const
|
||||
@ -762,65 +765,65 @@ namespace nana
|
||||
}
|
||||
//end struct rectangle
|
||||
|
||||
//class area_rotator
|
||||
area_rotator::area_rotator(bool rotated, const ::nana::rectangle& area)
|
||||
//class rectangle_rotator
|
||||
rectangle_rotator::rectangle_rotator(bool rotated, const ::nana::rectangle& area)
|
||||
: rotated_(rotated),
|
||||
area_(area)
|
||||
{}
|
||||
|
||||
int area_rotator::x() const
|
||||
int rectangle_rotator::x() const
|
||||
{
|
||||
return (rotated_ ? area_.y : area_.x);
|
||||
}
|
||||
|
||||
int & area_rotator::x_ref()
|
||||
int & rectangle_rotator::x_ref()
|
||||
{
|
||||
return (rotated_ ? area_.y : area_.x);
|
||||
}
|
||||
|
||||
int area_rotator::y() const
|
||||
int rectangle_rotator::y() const
|
||||
{
|
||||
return (rotated_ ? area_.x : area_.y);
|
||||
}
|
||||
|
||||
int & area_rotator::y_ref()
|
||||
int & rectangle_rotator::y_ref()
|
||||
{
|
||||
return (rotated_ ? area_.x : area_.y);
|
||||
}
|
||||
|
||||
unsigned area_rotator::w() const
|
||||
unsigned rectangle_rotator::w() const
|
||||
{
|
||||
return (rotated_ ? area_.height : area_.width);
|
||||
}
|
||||
|
||||
unsigned & area_rotator::w_ref()
|
||||
unsigned & rectangle_rotator::w_ref()
|
||||
{
|
||||
return (rotated_ ? area_.height : area_.width);
|
||||
}
|
||||
|
||||
unsigned area_rotator::h() const
|
||||
unsigned rectangle_rotator::h() const
|
||||
{
|
||||
return (rotated_ ? area_.width : area_.height);
|
||||
}
|
||||
|
||||
unsigned & area_rotator::h_ref()
|
||||
unsigned & rectangle_rotator::h_ref()
|
||||
{
|
||||
return (rotated_ ? area_.width : area_.height);
|
||||
}
|
||||
|
||||
int area_rotator::right() const
|
||||
int rectangle_rotator::right() const
|
||||
{
|
||||
return (rotated_ ? area_.y + static_cast<int>(area_.height) : area_.x + static_cast<int>(area_.width));
|
||||
}
|
||||
|
||||
int area_rotator::bottom() const
|
||||
int rectangle_rotator::bottom() const
|
||||
{
|
||||
return (rotated_ ? area_.x + static_cast<int>(area_.width) : area_.y + static_cast<int>(area_.height));
|
||||
}
|
||||
|
||||
const ::nana::rectangle& area_rotator::result() const
|
||||
const ::nana::rectangle& rectangle_rotator::result() const
|
||||
{
|
||||
return area_;
|
||||
}
|
||||
//end class area_rotator
|
||||
//end class rectangle_rotator
|
||||
}
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
#include PLATFORM_SPEC_HPP
|
||||
#endif
|
||||
|
||||
#if defined(NANA_MINGW) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 8)
|
||||
//Implement workarounds for GCC/MinGW which version is below 4.8.2
|
||||
#if defined(STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED)
|
||||
#include <sstream>
|
||||
namespace std
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Platform Specification Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Nana Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -841,7 +841,10 @@ namespace detail
|
||||
if((attr.your_event_mask & addr->input_context_event_mask) == addr->input_context_event_mask)
|
||||
{
|
||||
XSetWindowAttributes new_attr;
|
||||
new_attr.event_mask = (attr.your_event_mask & ~addr->input_context_event_mask);
|
||||
|
||||
//Don't remove the KeyPress and KeyRelease mask(0x3), otherwise the window will not receive
|
||||
//Keyboard events after destroying caret
|
||||
new_attr.event_mask = (attr.your_event_mask & ~(addr->input_context_event_mask & (~0x3)));
|
||||
::XChangeWindowAttributes(display_, reinterpret_cast<Window>(wd), CWEventMask, &new_attr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,6 +347,7 @@ namespace nana
|
||||
flags.destroying = false;
|
||||
flags.borderless = false;
|
||||
flags.make_bground_declared = false;
|
||||
flags.ignore_menubar_focus = false;
|
||||
|
||||
visible = false;
|
||||
|
||||
@ -355,7 +356,6 @@ namespace nana
|
||||
effect.bground_fade_rate = 0;
|
||||
|
||||
together.caret = nullptr;
|
||||
together.attached_events = nullptr;
|
||||
|
||||
extra_width = extra_height = 0;
|
||||
|
||||
@ -368,16 +368,15 @@ namespace nana
|
||||
|
||||
bool basic_window::set_events(const std::shared_ptr<general_events>& p)
|
||||
{
|
||||
if (together.attached_events)
|
||||
if (together.events_ptr)
|
||||
return false;
|
||||
together.events_ptr = p;
|
||||
together.attached_events = p.get();
|
||||
return true;
|
||||
}
|
||||
|
||||
general_events * basic_window::get_events() const
|
||||
{
|
||||
return together.attached_events;
|
||||
return together.events_ptr.get();
|
||||
}
|
||||
//end struct basic_window
|
||||
}//end namespace detail
|
||||
|
||||
@ -146,6 +146,9 @@ namespace nana
|
||||
|
||||
void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::event_arg& event_arg)
|
||||
{
|
||||
auto retain = wd->together.events_ptr;
|
||||
auto evts_ptr = retain.get();
|
||||
|
||||
switch (evt_code)
|
||||
{
|
||||
case event_code::click:
|
||||
@ -162,35 +165,36 @@ namespace nana
|
||||
|
||||
void(::nana::detail::drawer::*drawer_event_fn)(const arg_mouse&);
|
||||
::nana::basic_event<arg_mouse>* evt_addr;
|
||||
|
||||
switch (evt_code)
|
||||
{
|
||||
case event_code::click:
|
||||
drawer_event_fn = &drawer::click;
|
||||
evt_addr = &wd->together.attached_events->click;
|
||||
evt_addr = &evts_ptr->click;
|
||||
break;
|
||||
case event_code::dbl_click:
|
||||
drawer_event_fn = &drawer::dbl_click;
|
||||
evt_addr = &wd->together.attached_events->dbl_click;
|
||||
evt_addr = &evts_ptr->dbl_click;
|
||||
break;
|
||||
case event_code::mouse_enter:
|
||||
drawer_event_fn = &drawer::mouse_enter;
|
||||
evt_addr = &wd->together.attached_events->mouse_enter;
|
||||
evt_addr = &evts_ptr->mouse_enter;
|
||||
break;
|
||||
case event_code::mouse_move:
|
||||
drawer_event_fn = &drawer::mouse_move;
|
||||
evt_addr = &wd->together.attached_events->mouse_move;
|
||||
evt_addr = &evts_ptr->mouse_move;
|
||||
break;
|
||||
case event_code::mouse_leave:
|
||||
drawer_event_fn = &drawer::mouse_leave;
|
||||
evt_addr = &wd->together.attached_events->mouse_leave;
|
||||
evt_addr = &evts_ptr->mouse_leave;
|
||||
break;
|
||||
case event_code::mouse_down:
|
||||
drawer_event_fn = &drawer::mouse_down;
|
||||
evt_addr = &wd->together.attached_events->mouse_down;
|
||||
evt_addr = &evts_ptr->mouse_down;
|
||||
break;
|
||||
case event_code::mouse_up:
|
||||
drawer_event_fn = &drawer::mouse_up;
|
||||
evt_addr = &wd->together.attached_events->mouse_up;
|
||||
evt_addr = &evts_ptr->mouse_up;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid mouse event code");
|
||||
@ -209,7 +213,7 @@ namespace nana
|
||||
{
|
||||
wd->drawer.mouse_wheel(*arg);
|
||||
if (!draw_only)
|
||||
wd->together.attached_events->mouse_wheel.emit(*arg);
|
||||
evts_ptr->mouse_wheel.emit(*arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -229,19 +233,19 @@ namespace nana
|
||||
{
|
||||
case event_code::key_press:
|
||||
drawer_event_fn = &drawer::key_press;
|
||||
evt_addr = &wd->together.attached_events->key_press;
|
||||
evt_addr = &evts_ptr->key_press;
|
||||
break;
|
||||
case event_code::key_char:
|
||||
drawer_event_fn = &drawer::key_char;
|
||||
evt_addr = &wd->together.attached_events->key_char;
|
||||
evt_addr = &evts_ptr->key_char;
|
||||
break;
|
||||
case event_code::key_release:
|
||||
drawer_event_fn = &drawer::key_release;
|
||||
evt_addr = &wd->together.attached_events->key_release;
|
||||
evt_addr = &evts_ptr->key_release;
|
||||
break;
|
||||
case event_code::shortkey:
|
||||
drawer_event_fn = &drawer::shortkey;
|
||||
evt_addr = &wd->together.attached_events->shortkey;
|
||||
evt_addr = &evts_ptr->shortkey;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid keyboard event code");
|
||||
@ -256,7 +260,7 @@ namespace nana
|
||||
{
|
||||
auto arg = dynamic_cast<const arg_expose*>(&event_arg);
|
||||
if (arg)
|
||||
wd->together.attached_events->expose.emit(*arg);
|
||||
evts_ptr->expose.emit(*arg);
|
||||
}
|
||||
break;
|
||||
case event_code::focus:
|
||||
@ -266,7 +270,7 @@ namespace nana
|
||||
{
|
||||
wd->drawer.focus(*arg);
|
||||
if (!draw_only)
|
||||
wd->together.attached_events->focus.emit(*arg);
|
||||
evts_ptr->focus.emit(*arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -277,7 +281,7 @@ namespace nana
|
||||
{
|
||||
wd->drawer.move(*arg);
|
||||
if (!draw_only)
|
||||
wd->together.attached_events->move.emit(*arg);
|
||||
evts_ptr->move.emit(*arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -288,7 +292,7 @@ namespace nana
|
||||
{
|
||||
wd->drawer.resizing(*arg);
|
||||
if (!draw_only)
|
||||
wd->together.attached_events->resizing.emit(*arg);
|
||||
evts_ptr->resizing.emit(*arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -299,7 +303,7 @@ namespace nana
|
||||
{
|
||||
wd->drawer.resized(*arg);
|
||||
if (!draw_only)
|
||||
wd->together.attached_events->resized.emit(*arg);
|
||||
evts_ptr->resized.emit(*arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -309,9 +313,9 @@ namespace nana
|
||||
auto arg = dynamic_cast<const arg_unload*>(&event_arg);
|
||||
if (arg && (wd->other.category == category::flags::root))
|
||||
{
|
||||
auto evt_ptr = dynamic_cast<events_root_extension*>(wd->together.attached_events);
|
||||
if (evt_ptr)
|
||||
evt_ptr->unload.emit(*arg);
|
||||
auto evt_root = dynamic_cast<events_root_extension*>(evts_ptr);
|
||||
if (evt_root)
|
||||
evt_root->unload.emit(*arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -320,7 +324,7 @@ namespace nana
|
||||
{
|
||||
auto arg = dynamic_cast<const arg_destroy*>(&event_arg);
|
||||
if (arg)
|
||||
wd->together.attached_events->destroy.emit(*arg);
|
||||
evts_ptr->destroy.emit(*arg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Bedrock Selector
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Nana Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@ -21,8 +21,6 @@
|
||||
#include <nana/detail/linux_X11/platform_spec.hpp>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
typedef detail::edge_nimbus_renderer<detail::bedrock::core_window_t> edge_nimbus_renderer_t;
|
||||
@ -351,12 +349,13 @@ namespace nana
|
||||
{
|
||||
if(p)
|
||||
{
|
||||
auto i = std::find(dynamic_drawing_objects_.begin(), dynamic_drawing_objects_.end(), p);
|
||||
if (i != dynamic_drawing_objects_.end())
|
||||
{
|
||||
delete (*i);
|
||||
dynamic_drawing_objects_.erase(i);
|
||||
}
|
||||
for (auto i = dynamic_drawing_objects_.begin(); i != dynamic_drawing_objects_.end(); ++i)
|
||||
if (*i == p)
|
||||
{
|
||||
delete (*i);
|
||||
dynamic_drawing_objects_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,12 +41,6 @@ namespace nana
|
||||
reinterpret_cast<detail::docker_interface*>(evt)->get_event()->remove(evt);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t events_operation::size() const
|
||||
{
|
||||
lock_guard lock(mutex_);
|
||||
return register_.size();
|
||||
}
|
||||
//end namespace events_operation
|
||||
}//end namespace detail
|
||||
}//end namespace nana
|
||||
@ -102,27 +102,18 @@ namespace detail
|
||||
{
|
||||
struct thread_context_cache
|
||||
{
|
||||
unsigned tid;
|
||||
thread_context *object;
|
||||
unsigned tid{ 0 };
|
||||
thread_context *object{ nullptr };
|
||||
}tcontext;
|
||||
|
||||
cache_type()
|
||||
{
|
||||
tcontext.tid = 0;
|
||||
tcontext.object = nullptr;
|
||||
}
|
||||
}cache;
|
||||
|
||||
struct menu_tag
|
||||
{
|
||||
menu_tag()
|
||||
:taken_window(nullptr), window(nullptr), owner(nullptr), has_keyboard(false)
|
||||
{}
|
||||
|
||||
core_window_t* taken_window;
|
||||
native_window_type window;
|
||||
native_window_type owner;
|
||||
bool has_keyboard;
|
||||
core_window_t* taken_window{ nullptr };
|
||||
bool delay_restore{ false };
|
||||
native_window_type window{ nullptr };
|
||||
native_window_type owner{ nullptr };
|
||||
bool has_keyboard{ false };
|
||||
}menu;
|
||||
|
||||
struct keyboard_tracking_state_tag
|
||||
@ -282,14 +273,39 @@ namespace detail
|
||||
|
||||
void bedrock::set_menubar_taken(core_window_t* wd)
|
||||
{
|
||||
auto pre = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = wd;
|
||||
|
||||
//assigning of a nullptr taken window is to restore the focus of pre taken
|
||||
if ((!wd) && pre)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
wd_manager.set_focus(pre, false);
|
||||
wd_manager.update(pre, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
bedrock::core_window_t* bedrock::get_menubar_taken()
|
||||
//0:Enable delay, 1:Cancel, 2:Restores, 3: Restores when menu is destroying
|
||||
void bedrock::delay_restore(int state)
|
||||
{
|
||||
core_window_t* wd = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = nullptr;
|
||||
return wd;
|
||||
switch (state)
|
||||
{
|
||||
case 0: //Enable
|
||||
break;
|
||||
case 1: //Cancel
|
||||
break;
|
||||
case 2: //Restore if key released
|
||||
//restores the focus when menu is closed by pressing keyboard
|
||||
if (!impl_->menu.window)
|
||||
set_menubar_taken(nullptr);
|
||||
break;
|
||||
case 3: //Restores if destroying
|
||||
//when the menu is destroying, restores the focus if delay restore is not declared
|
||||
if (!impl_->menu.delay_restore)
|
||||
set_menubar_taken(nullptr);
|
||||
}
|
||||
|
||||
impl_->menu.delay_restore = (0 == state);
|
||||
}
|
||||
|
||||
bool bedrock::close_menu_if_focus_other_window(native_window_type wd)
|
||||
@ -304,7 +320,7 @@ namespace detail
|
||||
else
|
||||
return false;
|
||||
}
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -314,7 +330,7 @@ namespace detail
|
||||
{
|
||||
if(menu_window && impl_->menu.window != menu_window)
|
||||
{
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
impl_->menu.window = menu_window;
|
||||
impl_->menu.owner = native_interface::get_owner_window(menu_window);
|
||||
impl_->menu.has_keyboard = has_keyboard;
|
||||
@ -338,21 +354,13 @@ namespace detail
|
||||
return impl_->menu.window;
|
||||
}
|
||||
|
||||
void bedrock::remove_menu()
|
||||
void bedrock::erase_menu(bool try_destroy)
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
if (impl_->menu.window)
|
||||
{
|
||||
native_window_type delwin = impl_->menu.window;
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
native_interface::close_window(delwin);
|
||||
}
|
||||
}
|
||||
if (try_destroy)
|
||||
native_interface::close_window(impl_->menu.window);
|
||||
|
||||
void bedrock::empty_menu()
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
{
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
}
|
||||
@ -363,6 +371,7 @@ namespace detail
|
||||
XKeyEvent xkey;
|
||||
nana::detail::platform_spec::instance().read_keystate(xkey);
|
||||
arg.ctrl = (xkey.state & ControlMask);
|
||||
arg.shift = (xkey.state & ShiftMask);
|
||||
}
|
||||
|
||||
bool bedrock::set_keyboard_shortkey(bool yes)
|
||||
@ -372,6 +381,11 @@ namespace detail
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool bedrock::whether_keyboard_shortkey() const
|
||||
{
|
||||
return impl_->keyboard_tracking_state.has_shortkey_occured;
|
||||
}
|
||||
|
||||
element_store& bedrock::get_element_store() const
|
||||
{
|
||||
return impl_->estore;
|
||||
@ -569,7 +583,7 @@ namespace detail
|
||||
delete msg.u.mouse_drop.files;
|
||||
arg.pos.x = msg.u.mouse_drop.x - msgwd->pos_root.x;
|
||||
arg.pos.y = msg.u.mouse_drop.y - msgwd->pos_root.y;
|
||||
msgwd->together.attached_events->mouse_dropfiles.emit(arg);
|
||||
msgwd->together.events_ptr->mouse_dropfiles.emit(arg);
|
||||
brock.wd_manager.do_lazy_refresh(msgwd, false);
|
||||
}
|
||||
break;
|
||||
@ -700,8 +714,8 @@ namespace detail
|
||||
msgwnd = brock.wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y);
|
||||
if(nullptr == msgwnd) break;
|
||||
|
||||
if((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.remove_menu();
|
||||
if ((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.erase_menu(true);
|
||||
else
|
||||
brock.close_menu_if_focus_other_window(msgwnd->root);
|
||||
|
||||
@ -719,12 +733,11 @@ namespace detail
|
||||
if(kill_focus != new_focus)
|
||||
brock.wd_manager.do_lazy_refresh(kill_focus, false);
|
||||
}
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
msgwnd->root_widget->other.attribute.root->context.focus_changed = false;
|
||||
|
||||
context.event_window = msgwnd;
|
||||
|
||||
pressed_wd = nullptr;
|
||||
//make_eventinfo(ei, msgwnd, message, xevent);
|
||||
msgwnd->flags.action = mouse_action::pressed;
|
||||
arg_mouse arg;
|
||||
assign_arg(arg, msgwnd, ButtonPress, xevent);
|
||||
@ -753,7 +766,7 @@ namespace detail
|
||||
nana::point mspos{xevent.xbutton.x, xevent.xbutton.y};
|
||||
while(msgwnd)
|
||||
{
|
||||
if(msgwnd->together.attached_events->mouse_wheel.length() != 0)
|
||||
if(msgwnd->together.events_ptr->mouse_wheel.length() != 0)
|
||||
{
|
||||
mspos -= msgwnd->pos_root;
|
||||
arg_wheel arg;
|
||||
@ -774,6 +787,8 @@ namespace detail
|
||||
msgwnd->flags.action = mouse_action::normal;
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
|
||||
arg_mouse arg;
|
||||
assign_arg(arg, msgwnd, message, xevent);
|
||||
|
||||
@ -795,27 +810,29 @@ namespace detail
|
||||
{
|
||||
if(hit)
|
||||
msgwnd->flags.action = mouse_action::over;
|
||||
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
auto evt_ptr = retain.get();
|
||||
|
||||
auto events_ptr = msgwnd->together.events_ptr;
|
||||
arg.evt_code = event_code::mouse_up;
|
||||
emit_drawer(&drawer::mouse_up, msgwnd, arg, &context);
|
||||
|
||||
if(fire_click)
|
||||
{
|
||||
arg.evt_code = event_code::click;
|
||||
msgwnd->together.attached_events->click.emit(arg);
|
||||
evt_ptr->click.emit(arg);
|
||||
}
|
||||
|
||||
if (brock.wd_manager.available(msgwnd))
|
||||
{
|
||||
arg.evt_code = event_code::mouse_up;
|
||||
msgwnd->together.attached_events->mouse_up.emit(arg);
|
||||
evt_ptr->mouse_up.emit(arg);
|
||||
}
|
||||
}
|
||||
else if(fire_click)
|
||||
{
|
||||
arg.evt_code = event_code::click;
|
||||
msgwnd->together.attached_events->click.emit(arg);
|
||||
msgwnd->together.events_ptr->click.emit(arg);
|
||||
}
|
||||
brock.wd_manager.do_lazy_refresh(msgwnd, false);
|
||||
}
|
||||
@ -828,8 +845,11 @@ namespace detail
|
||||
if(brock.wd_manager.available(msgwnd))
|
||||
{
|
||||
//The msgwnd may be destroyed if the window is destroyed by calling native interface of close_window().
|
||||
if(msgwnd->root == brock.get_menu())
|
||||
brock.empty_menu();
|
||||
if (msgwnd->root == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore not decleared
|
||||
}
|
||||
|
||||
spec.remove(native_window);
|
||||
brock.wd_manager.destroy(msgwnd);
|
||||
@ -928,6 +948,9 @@ namespace detail
|
||||
nana::detail::platform_spec::instance().write_keystate(xevent.xkey);
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
if (brock.get_menu())
|
||||
brock.delay_restore(0); //Enable delay restore
|
||||
|
||||
if(msgwnd->root != brock.get_menu())
|
||||
msgwnd = brock.focus();
|
||||
|
||||
@ -961,8 +984,8 @@ namespace detail
|
||||
else
|
||||
{
|
||||
nana::detail::platform_scope_guard psg;
|
||||
status = XLookupBoth;
|
||||
len = ::XLookupString(&xevent.xkey, keybuf, 32, &keysym, 0);
|
||||
status = XLookupKeySym;
|
||||
keysym = ::XLookupKeysym(&xevent.xkey, 0);
|
||||
}
|
||||
|
||||
keybuf[len] = 0;
|
||||
@ -999,7 +1022,9 @@ namespace detail
|
||||
context.platform.keychar = keychar;
|
||||
if(keychar == keyboard::tab && (false == (msgwnd->flags.tab & detail::tab_type::eating))) //Tab
|
||||
{
|
||||
auto the_next = brock.wd_manager.tabstop(msgwnd, true);
|
||||
arg_keyboard argkey;
|
||||
brock.get_key_state(argkey);
|
||||
auto the_next = brock.wd_manager.tabstop(msgwnd, !argkey.shift);
|
||||
if(the_next)
|
||||
{
|
||||
brock.wd_manager.set_focus(the_next, false);
|
||||
@ -1010,12 +1035,31 @@ namespace detail
|
||||
else if(keyboard::alt == keychar)
|
||||
{
|
||||
context.is_alt_pressed = true;
|
||||
if (brock.whether_keyboard_shortkey() == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if (msgwnd)
|
||||
{
|
||||
bool focused = (brock.focus() == msgwnd);
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_press;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
arg.ignore = false;
|
||||
arg.key = static_cast<nana::char_t>(keychar);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = (focused && (brock.focus() != msgwnd));
|
||||
}
|
||||
else
|
||||
brock.erase_menu(true);
|
||||
}
|
||||
}
|
||||
else if(keychar)
|
||||
else
|
||||
{
|
||||
arg_keyboard arg;
|
||||
arg.ignore = false;
|
||||
arg.key = keychar;
|
||||
arg.key = keychar ? keychar : xevent.xkey.keycode;
|
||||
arg.evt_code = event_code::key_press;
|
||||
brock.get_key_state(arg);
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@ -1061,7 +1105,7 @@ namespace detail
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
brock.get_key_state(arg);
|
||||
|
||||
msgwnd->together.attached_events->key_char.emit(arg);
|
||||
msgwnd->together.events_ptr->key_char.emit(arg);
|
||||
if(arg.ignore == false && brock.wd_manager.available(msgwnd))
|
||||
brock.emit_drawer(event_code::key_char, msgwnd, arg, &context);
|
||||
}
|
||||
@ -1092,11 +1136,35 @@ namespace detail
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
}
|
||||
brock.delay_restore(2); //Restores while key release
|
||||
}
|
||||
else
|
||||
{
|
||||
context.is_alt_pressed = false;
|
||||
brock.set_keyboard_shortkey(false);
|
||||
if (brock.set_keyboard_shortkey(false) == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if (msgwnd)
|
||||
{
|
||||
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
|
||||
if (set_focus)
|
||||
brock.wd_manager.set_focus(msgwnd, false);
|
||||
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_release;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
arg.ignore = false;
|
||||
arg.key = static_cast<nana::char_t>(context.platform.keychar);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
|
||||
if (!set_focus)
|
||||
{
|
||||
brock.set_menubar_taken(nullptr);
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <nana/config.hpp>
|
||||
#include PLATFORM_SPEC_HPP
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/screen.hpp>
|
||||
#if defined(NANA_WINDOWS)
|
||||
#if defined(NANA_MINGW) && defined(STD_THREAD_NOT_SUPPORTED)
|
||||
#include <nana/std_mutex.hpp>
|
||||
@ -35,10 +36,10 @@ namespace nana{
|
||||
#if defined(NANA_WINDOWS)
|
||||
static HICON icon(const nana::paint::image& img)
|
||||
{
|
||||
paint::detail::image_ico * ico = dynamic_cast<paint::detail::image_ico*>(img.image_ptr_.get());
|
||||
auto ico = dynamic_cast<paint::detail::image_ico*>(img.image_ptr_.get());
|
||||
if(ico && ico->ptr())
|
||||
return *(ico->ptr());
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@ -51,17 +52,13 @@ namespace nana{
|
||||
{
|
||||
struct window_extra_t
|
||||
{
|
||||
HICON ico;
|
||||
|
||||
window_extra_t()
|
||||
: ico(0)
|
||||
{}
|
||||
HICON ico{nullptr};
|
||||
};
|
||||
|
||||
typedef std::map<native_window_type, window_extra_t> map_t;
|
||||
|
||||
private:
|
||||
tray_manager(){}
|
||||
tray_manager() = default;
|
||||
public:
|
||||
typedef window_extra_t extra_t;
|
||||
|
||||
@ -205,19 +202,21 @@ namespace nana{
|
||||
if(owner && (nested == false))
|
||||
::ClientToScreen(reinterpret_cast<HWND>(owner), &pt);
|
||||
|
||||
HWND wnd = ::CreateWindowEx(style_ex, STR("NanaWindowInternal"), STR("Nana Window"),
|
||||
HWND native_wd = ::CreateWindowEx(style_ex, STR("NanaWindowInternal"), STR("Nana Window"),
|
||||
style,
|
||||
pt.x, pt.y, 100, 100,
|
||||
reinterpret_cast<HWND>(owner), 0, ::GetModuleHandle(0), 0);
|
||||
|
||||
//A window may have a border, this should be adjusted the client area fit for the specified size.
|
||||
::RECT client;
|
||||
::GetClientRect(wnd, &client); //The right and bottom of client by GetClientRect indicate the width and height of the area
|
||||
::GetClientRect(native_wd, &client); //The right and bottom of client by GetClientRect indicate the width and height of the area
|
||||
::RECT wd_area;
|
||||
::GetWindowRect(wnd, &wd_area);
|
||||
wd_area.right -= wd_area.left;
|
||||
wd_area.bottom -= wd_area.top;
|
||||
if(nested)
|
||||
::GetWindowRect(native_wd, &wd_area);
|
||||
|
||||
//a dimension with borders and caption title
|
||||
wd_area.right -= wd_area.left; //wd_area.right = width
|
||||
wd_area.bottom -= wd_area.top; //wd_area.bottom = height
|
||||
if (nested)
|
||||
{
|
||||
wd_area.left = pt.x;
|
||||
wd_area.top = pt.y;
|
||||
@ -226,14 +225,15 @@ namespace nana{
|
||||
int delta_w = static_cast<int>(r.width) - client.right;
|
||||
int delta_h = static_cast<int>(r.height) - client.bottom;
|
||||
|
||||
::MoveWindow(wnd, wd_area.left, wd_area.top, wd_area.right + delta_w, wd_area.bottom + delta_h, true);
|
||||
::MoveWindow(native_wd, wd_area.left, wd_area.top, wd_area.right + delta_w, wd_area.bottom + delta_h, true);
|
||||
|
||||
::GetClientRect(native_wd, &client);
|
||||
::GetWindowRect(native_wd, &wd_area);
|
||||
|
||||
::GetClientRect(wnd, &client);
|
||||
::GetWindowRect(wnd, &wd_area);
|
||||
wd_area.right -= wd_area.left;
|
||||
wd_area.bottom -= wd_area.top;
|
||||
|
||||
window_result result = {reinterpret_cast<native_window_type>(wnd),
|
||||
window_result result = { reinterpret_cast<native_window_type>(native_wd),
|
||||
static_cast<unsigned>(client.right), static_cast<unsigned>(client.bottom),
|
||||
static_cast<unsigned>(wd_area.right - client.right), static_cast<unsigned>(wd_area.bottom - client.bottom)};
|
||||
#elif defined(NANA_X11)
|
||||
@ -556,6 +556,7 @@ namespace nana{
|
||||
{
|
||||
::EnableWindow(native_wd, true);
|
||||
::SetActiveWindow(native_wd);
|
||||
::SetForegroundWindow(native_wd);
|
||||
}
|
||||
else
|
||||
::PostMessage(native_wd, nana::detail::messages::async_activate, 0, 0);
|
||||
@ -580,27 +581,30 @@ namespace nana{
|
||||
//event, when the client receives the event, the specified window has been already
|
||||
//destroyed. This is a feature which is different from Windows. So the following
|
||||
//works should be handled before calling XDestroyWindow.
|
||||
auto & bedrock = bedrock::instance();
|
||||
if(wd == bedrock.get_menu())
|
||||
bedrock.empty_menu();
|
||||
auto & brock = bedrock::instance();
|
||||
if(wd == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore is not decleard
|
||||
}
|
||||
|
||||
Display* disp = restrict::spec.open_display();
|
||||
restrict::spec.remove(wd);
|
||||
auto iwd = bedrock.wd_manager.root(wd);
|
||||
auto iwd = brock.wd_manager.root(wd);
|
||||
if(iwd)
|
||||
{
|
||||
{
|
||||
//Before calling window_manager::destroy, make sure the window is invisible.
|
||||
//It is a behavior like Windows.
|
||||
nana::detail::platform_scope_guard psg;
|
||||
nana::detail::platform_scope_guard lock;
|
||||
restrict::spec.set_error_handler();
|
||||
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
::XFlush(disp);
|
||||
restrict::spec.rev_error_handler();
|
||||
}
|
||||
bedrock.wd_manager.destroy(iwd);
|
||||
bedrock.rt_manager.remove_if_exists(iwd);
|
||||
bedrock.wd_manager.destroy_handle(iwd);
|
||||
brock.wd_manager.destroy(iwd);
|
||||
brock.rt_manager.remove_if_exists(iwd);
|
||||
brock.wd_manager.destroy_handle(iwd);
|
||||
}
|
||||
|
||||
nana::detail::platform_scope_guard psg;
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/detail/win32/bedrock.cpp
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
|
||||
#include <nana/config.hpp>
|
||||
@ -184,17 +185,18 @@ namespace detail
|
||||
{
|
||||
struct thread_context_cache
|
||||
{
|
||||
unsigned tid = 0;
|
||||
thread_context *object = nullptr;
|
||||
unsigned tid{ 0 };
|
||||
thread_context *object{ nullptr };
|
||||
}tcontext;
|
||||
}cache;
|
||||
|
||||
struct menu_tag
|
||||
{
|
||||
core_window_t* taken_window = nullptr;
|
||||
native_window_type window = nullptr;
|
||||
native_window_type owner = nullptr;
|
||||
bool has_keyboard = false;
|
||||
core_window_t* taken_window{ nullptr };
|
||||
bool delay_restore{ false };
|
||||
native_window_type window{ nullptr };
|
||||
native_window_type owner{ nullptr };
|
||||
bool has_keyboard{false};
|
||||
}menu;
|
||||
|
||||
struct keyboard_tracking_state_tag
|
||||
@ -266,12 +268,6 @@ namespace detail
|
||||
::MessageBoxA(0, ss.str().c_str(), ("Nana C++ Library"), MB_OK);
|
||||
}
|
||||
|
||||
if(evt_operation.size())
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"Nana.GUI detects a memory leaks in events operation, "<<static_cast<unsigned>(evt_operation.size())<<" event(s) are not uninstalled.";
|
||||
::MessageBoxA(0, ss.str().c_str(), ("Nana C++ Library"), MB_OK);
|
||||
}
|
||||
delete impl_;
|
||||
delete pi_data_;
|
||||
}
|
||||
@ -855,7 +851,7 @@ namespace detail
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
if ((reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW) && (!msgwnd->visible))
|
||||
brock.event_expose(msgwnd, true);
|
||||
else if((reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_HIDEWINDOW) && msgwnd->visible)
|
||||
else if ((reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_HIDEWINDOW) && msgwnd->visible)
|
||||
brock.event_expose(msgwnd, false);
|
||||
|
||||
def_window_proc = true;
|
||||
@ -875,6 +871,7 @@ namespace detail
|
||||
if (!brock.emit(event_code::focus, focus, arg, true, &context))
|
||||
brock.wd_manager.set_focus(msgwnd, true);
|
||||
}
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_KILLFOCUS:
|
||||
if(msgwnd->other.attribute.root->focus)
|
||||
@ -895,10 +892,14 @@ namespace detail
|
||||
//focus_changed means that during an event procedure if the focus is changed
|
||||
if(brock.wd_manager.available(msgwnd))
|
||||
msgwnd->root_widget->other.attribute.root->context.focus_changed = true;
|
||||
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_MOUSEACTIVATE:
|
||||
if(msgwnd->flags.take_active == false)
|
||||
return MA_NOACTIVATE;
|
||||
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK:
|
||||
pressed_wd = nullptr;
|
||||
@ -926,8 +927,8 @@ namespace detail
|
||||
if(nullptr == msgwnd) break;
|
||||
|
||||
//if event on the menubar, just remove the menu if it is not associating with the menubar
|
||||
if((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.remove_menu();
|
||||
if ((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.erase_menu(true);
|
||||
else
|
||||
brock.close_menu_if_focus_other_window(msgwnd->root);
|
||||
|
||||
@ -948,6 +949,8 @@ namespace detail
|
||||
arg_mouse arg;
|
||||
assign_arg(arg, msgwnd, message, pmdec);
|
||||
msgwnd->flags.action = mouse_action::pressed;
|
||||
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
if (brock.emit(event_code::mouse_down, msgwnd, arg, true, &context))
|
||||
{
|
||||
//If a root_window is created during the mouse_down event, Nana.GUI will ignore the mouse_up event.
|
||||
@ -982,6 +985,8 @@ namespace detail
|
||||
msgwnd->flags.action = mouse_action::normal;
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
|
||||
nana::arg_mouse arg;
|
||||
assign_arg(arg, msgwnd, message, pmdec);
|
||||
|
||||
@ -1011,19 +1016,19 @@ namespace detail
|
||||
if (fire_click)
|
||||
{
|
||||
arg.evt_code = event_code::click;
|
||||
msgwnd->together.attached_events->click.emit(arg);
|
||||
retain->click.emit(arg);
|
||||
}
|
||||
|
||||
if (brock.wd_manager.available(msgwnd))
|
||||
{
|
||||
arg.evt_code = event_code::mouse_up;
|
||||
msgwnd->together.attached_events->mouse_up.emit(arg);
|
||||
retain->mouse_up.emit(arg);
|
||||
}
|
||||
}
|
||||
else if (fire_click)
|
||||
{
|
||||
arg.evt_code = event_code::click;
|
||||
msgwnd->together.attached_events->click.emit(arg);
|
||||
retain->click.emit(arg);
|
||||
}
|
||||
brock.wd_manager.do_lazy_refresh(msgwnd, false);
|
||||
}
|
||||
@ -1103,7 +1108,7 @@ namespace detail
|
||||
case WM_MOUSEHWHEEL:
|
||||
{
|
||||
//The focus window receives the message in Windows system, it should be redirected to the hovered window
|
||||
::POINT scr_pos{ int(LOWORD(lParam)), int(HIWORD(lParam)) }; //Screen position
|
||||
::POINT scr_pos{ pmdec.mouse.x, pmdec.mouse.y}; //Screen position
|
||||
auto pointer_wd = ::WindowFromPoint(scr_pos);
|
||||
if (pointer_wd == root_window)
|
||||
{
|
||||
@ -1114,7 +1119,7 @@ namespace detail
|
||||
auto evt_wd = scrolled_wd;
|
||||
while (evt_wd)
|
||||
{
|
||||
if (evt_wd->together.attached_events->mouse_wheel.length() != 0)
|
||||
if (evt_wd->together.events_ptr->mouse_wheel.length() != 0)
|
||||
{
|
||||
def_window_proc = false;
|
||||
nana::point mspos{ scr_pos.x, scr_pos.y };
|
||||
@ -1189,7 +1194,7 @@ namespace detail
|
||||
brock.wd_manager.calc_window_point(msgwnd, dropfiles.pos);
|
||||
dropfiles.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
|
||||
msgwnd->together.attached_events->mouse_dropfiles.emit(dropfiles);
|
||||
msgwnd->together.events_ptr->mouse_dropfiles.emit(dropfiles);
|
||||
brock.wd_manager.do_lazy_refresh(msgwnd, false);
|
||||
}
|
||||
}
|
||||
@ -1308,6 +1313,7 @@ namespace detail
|
||||
}
|
||||
break;
|
||||
case WM_SYSCHAR:
|
||||
def_window_proc = true;
|
||||
brock.set_keyboard_shortkey(true);
|
||||
msgwnd = brock.wd_manager.find_shortkey(native_window, static_cast<unsigned long>(wParam));
|
||||
if(msgwnd)
|
||||
@ -1319,17 +1325,17 @@ namespace detail
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
arg.ignore = false;
|
||||
brock.emit(event_code::shortkey, msgwnd, arg, true, &context);
|
||||
def_window_proc = false;
|
||||
}
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
if(brock.whether_keyboard_shortkey() == false)
|
||||
def_window_proc = true;
|
||||
if (brock.whether_keyboard_shortkey() == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if(msgwnd)
|
||||
if (msgwnd)
|
||||
{
|
||||
brock.wd_manager.set_focus(msgwnd, false);
|
||||
|
||||
bool focused = (brock.focus() == msgwnd);
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_press;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@ -1337,18 +1343,26 @@ namespace detail
|
||||
arg.key = static_cast<nana::char_t>(wParam);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = (focused && (brock.focus() != msgwnd));
|
||||
}
|
||||
else if(brock.get_menu())
|
||||
brock.remove_menu();
|
||||
else
|
||||
brock.erase_menu(true);
|
||||
}
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_SYSKEYUP:
|
||||
def_window_proc = true;
|
||||
if(brock.set_keyboard_shortkey(false) == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if(msgwnd)
|
||||
{
|
||||
//Don't call default window proc to avoid popuping system menu.
|
||||
def_window_proc = false;
|
||||
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
|
||||
if (set_focus)
|
||||
brock.wd_manager.set_focus(msgwnd, false);
|
||||
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_release;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@ -1356,21 +1370,30 @@ namespace detail
|
||||
arg.key = static_cast<nana::char_t>(wParam);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
|
||||
if (!set_focus)
|
||||
{
|
||||
brock.set_menubar_taken(nullptr);
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
if(msgwnd->root != brock.get_menu())
|
||||
auto menu_wd = brock.get_menu();
|
||||
if (menu_wd)
|
||||
brock.delay_restore(0); //Enable delay restore
|
||||
|
||||
if (msgwnd->root != menu_wd)
|
||||
msgwnd = brock.focus();
|
||||
|
||||
if(msgwnd)
|
||||
{
|
||||
if((wParam == 9) && (false == (msgwnd->flags.tab & tab_type::eating))) //Tab
|
||||
{
|
||||
auto the_next = brock.wd_manager.tabstop(msgwnd, true);
|
||||
auto the_next = brock.wd_manager.tabstop(msgwnd, (::GetKeyState(VK_SHIFT) >= 0));
|
||||
if(the_next)
|
||||
{
|
||||
brock.wd_manager.set_focus(the_next, false);
|
||||
@ -1388,6 +1411,17 @@ namespace detail
|
||||
arg.key = static_cast<nana::char_t>(wParam);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||
|
||||
if (msgwnd->root_widget->other.attribute.root->menubar == msgwnd)
|
||||
{
|
||||
//In order to keep the focus on the menubar, cancel the delay_restore
|
||||
//when pressing ESC to close the menu which is popuped by the menubar.
|
||||
//If no menu popuped by the menubar, it should enable delay restore to
|
||||
//restore the focus for taken window.
|
||||
|
||||
int cmd = (menu_wd && (keyboard::escape == static_cast<nana::char_t>(wParam)) ? 1 : 0);
|
||||
brock.delay_restore(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1405,7 +1439,7 @@ namespace detail
|
||||
brock.get_key_state(arg);
|
||||
arg.ignore = false;
|
||||
|
||||
msgwnd->together.attached_events->key_char.emit(arg);
|
||||
msgwnd->together.events_ptr->key_char.emit(arg);
|
||||
if ((false == arg.ignore) && brock.wd_manager.available(msgwnd))
|
||||
brock.emit_drawer(event_code::key_char, msgwnd, arg, &context);
|
||||
|
||||
@ -1432,6 +1466,8 @@ namespace detail
|
||||
}
|
||||
else
|
||||
brock.set_keyboard_shortkey(false);
|
||||
|
||||
brock.delay_restore(2); //Restores while key release
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
{
|
||||
@ -1449,8 +1485,12 @@ namespace detail
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY:
|
||||
if(msgwnd->root == brock.get_menu())
|
||||
brock.empty_menu();
|
||||
if (msgwnd->root == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore not decleared
|
||||
}
|
||||
|
||||
brock.wd_manager.destroy(msgwnd);
|
||||
|
||||
nana::detail::platform_spec::instance().release_window_icon(msgwnd->root);
|
||||
@ -1513,14 +1553,40 @@ namespace detail
|
||||
|
||||
void bedrock::set_menubar_taken(core_window_t* wd)
|
||||
{
|
||||
auto pre = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = wd;
|
||||
|
||||
//assigning of a nullptr taken window is to restore the focus of pre taken
|
||||
//don't restore the focus if pre is a menu.
|
||||
if ((!wd) && pre && (pre->root != get_menu()))
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
wd_manager.set_focus(pre, false);
|
||||
wd_manager.update(pre, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
bedrock::core_window_t* bedrock::get_menubar_taken()
|
||||
//0:Enable delay, 1:Cancel, 2:Restores, 3: Restores when menu is destroying
|
||||
void bedrock::delay_restore(int state)
|
||||
{
|
||||
core_window_t* wd = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = nullptr;
|
||||
return wd;
|
||||
switch (state)
|
||||
{
|
||||
case 0: //Enable
|
||||
break;
|
||||
case 1: //Cancel
|
||||
break;
|
||||
case 2: //Restore if key released
|
||||
//restores the focus when menu is closed by pressing keyboard
|
||||
if ((!impl_->menu.window) && impl_->menu.delay_restore)
|
||||
set_menubar_taken(nullptr);
|
||||
break;
|
||||
case 3: //Restores if destroying
|
||||
//when the menu is destroying, restores the focus if delay restore is not declared
|
||||
if (!impl_->menu.delay_restore)
|
||||
set_menubar_taken(nullptr);
|
||||
}
|
||||
|
||||
impl_->menu.delay_restore = (0 == state);
|
||||
}
|
||||
|
||||
bool bedrock::close_menu_if_focus_other_window(native_window_type wd)
|
||||
@ -1535,7 +1601,7 @@ namespace detail
|
||||
else
|
||||
return false;
|
||||
}
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1545,7 +1611,7 @@ namespace detail
|
||||
{
|
||||
if(menu_wd && impl_->menu.window != menu_wd)
|
||||
{
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
|
||||
impl_->menu.window = menu_wd;
|
||||
impl_->menu.owner = native_interface::get_owner_window(menu_wd);
|
||||
@ -1569,21 +1635,13 @@ namespace detail
|
||||
return impl_->menu.window;
|
||||
}
|
||||
|
||||
void bedrock::remove_menu()
|
||||
void bedrock::erase_menu(bool try_destroy)
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
{
|
||||
auto delwin = impl_->menu.window;
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
native_interface::close_window(delwin);
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::empty_menu()
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
if (impl_->menu.window)
|
||||
{
|
||||
if (try_destroy)
|
||||
native_interface::close_window(impl_->menu.window);
|
||||
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/detail/window_manager.cpp
|
||||
*
|
||||
* @author: Jinhao
|
||||
* @contributors: Katsuhisa Yuasa
|
||||
*/
|
||||
|
||||
#include <nana/config.hpp>
|
||||
@ -20,7 +21,6 @@
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/gui/detail/effects_renderer.hpp>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -191,7 +191,7 @@ namespace detail
|
||||
switch(evtid)
|
||||
{
|
||||
case event_code::mouse_drop:
|
||||
wd->flags.dropable = (is_make || (0 != wd->together.attached_events->mouse_dropfiles.length()));
|
||||
wd->flags.dropable = (is_make || (0 != wd->together.events_ptr->mouse_dropfiles.length()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -875,7 +875,16 @@ namespace detail
|
||||
if (!root_has_been_focused)
|
||||
native_interface::set_focus(root_wd->root);
|
||||
|
||||
brock.set_menubar_taken(wd);
|
||||
//A fix by Katsuhisa Yuasa
|
||||
//The menubar token window will be redirected to the prev focus window when the new
|
||||
//focus window is a menubar.
|
||||
//The focus window will be restore to the prev focus which losts the focus becuase of
|
||||
//memberbar.
|
||||
if (wd == wd->root_widget->other.attribute.root->menubar)
|
||||
wd = prev_focus;
|
||||
|
||||
if (wd != wd->root_widget->other.attribute.root->menubar)
|
||||
brock.set_menubar_taken(wd);
|
||||
}
|
||||
return prev_focus;
|
||||
}
|
||||
@ -975,11 +984,15 @@ namespace detail
|
||||
}
|
||||
else
|
||||
{
|
||||
auto i = std::find_if(attr_cap.begin(), attr_cap.end(),
|
||||
[wd](const std::pair<core_window_t*, bool> & x){ return (x.first == wd);});
|
||||
for (auto i = attr_cap.begin(), end = attr_cap.end(); i != end; ++i)
|
||||
{
|
||||
if (i->first == wd)
|
||||
{
|
||||
attr_cap.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i != attr_cap.end())
|
||||
attr_cap.erase(i);
|
||||
return attr_.capture.window;
|
||||
}
|
||||
return wd;
|
||||
|
||||
@ -973,6 +973,7 @@ namespace nana
|
||||
|
||||
const nana::char_t * filter;
|
||||
nana::string filter_holder;
|
||||
nana::string default_extension;
|
||||
if(impl_->filters.size())
|
||||
{
|
||||
for(auto & f : impl_->filters)
|
||||
@ -990,6 +991,21 @@ namespace nana
|
||||
}
|
||||
filter_holder += fs;
|
||||
filter_holder += static_cast<nana::string::value_type>('\0');
|
||||
|
||||
//Get the default file extentsion
|
||||
if (default_extension.empty())
|
||||
{
|
||||
pos = fs.find_last_of('.');
|
||||
if (pos != fs.npos)
|
||||
{
|
||||
fs = fs.substr(pos + 1);
|
||||
if (fs != L"*")
|
||||
{
|
||||
default_extension = fs;
|
||||
ofn.lpstrDefExt = default_extension.data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
filter = filter_holder.data();
|
||||
}
|
||||
@ -1002,6 +1018,10 @@ namespace nana
|
||||
ofn.lpstrFileTitle = nullptr;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = (impl_->path.size() ? impl_->path.c_str() : nullptr);
|
||||
|
||||
if (!impl_->open_or_save)
|
||||
ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode
|
||||
|
||||
if(FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn)))
|
||||
return false;
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/layout_utility.hpp
|
||||
*
|
||||
* @contributors: Ryan Gonzalez
|
||||
*
|
||||
*/
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
/*
|
||||
* Implementation 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.cpp
|
||||
*/
|
||||
* Implementation of Notifier
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 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.cpp
|
||||
* @contributors: Jan
|
||||
*/
|
||||
#include <nana/deploy.hpp>
|
||||
#include <nana/gui/programming_interface.hpp>
|
||||
#include <nana/gui/notifier.hpp>
|
||||
@ -16,7 +17,12 @@
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#if defined(NANA_MINGW) && defined(STD_THREAD_NOT_SUPPORTED)
|
||||
#include <nana/std_mutex.hpp>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <nana/detail/win32/platform_spec.hpp>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
/**
|
||||
* An Implementation of Place for Layout
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -558,18 +559,22 @@ namespace nana
|
||||
return token::identifier;
|
||||
}
|
||||
|
||||
std::string err = "an invalid character '";
|
||||
err += *sp_;
|
||||
err += "'";
|
||||
|
||||
_m_throw_error(err);
|
||||
_m_throw_error(*sp_);
|
||||
return token::error; //Useless, just for syntax correction.
|
||||
}
|
||||
private:
|
||||
void _m_throw_error(char err_char)
|
||||
{
|
||||
std::string str = "place: invalid character '";
|
||||
str += err_char;
|
||||
str += '\'';
|
||||
_m_throw_error(str);
|
||||
}
|
||||
|
||||
void _m_throw_error(const std::string& err)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "place: invalid character '" << err_char << "' at " << static_cast<unsigned>(sp_ - divstr_);
|
||||
ss << "place: " << err << " at " << static_cast<unsigned>(sp_ - divstr_);
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
@ -578,8 +583,7 @@ namespace nana
|
||||
if (token::equal != read())
|
||||
_m_throw_error("an equal sign is required after '" + idstr_ + "'");
|
||||
|
||||
const char* p = sp_;
|
||||
for (; *p == ' '; ++p);
|
||||
const char* p = _m_eat_whitespace(sp_);
|
||||
|
||||
auto neg_ptr = p;
|
||||
if ('-' == *p)
|
||||
@ -598,8 +602,7 @@ namespace nana
|
||||
if (token::equal != read())
|
||||
_m_throw_error("an equal sign is required after '" + idstr + "'");
|
||||
|
||||
const char* p = sp_;
|
||||
for (; *p == ' ' || *p == '\t'; ++p);
|
||||
const char* p = _m_eat_whitespace(sp_);
|
||||
|
||||
reparray_.reset();
|
||||
auto tk = read();
|
||||
@ -619,14 +622,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
void _m_throw_error(const std::string& err)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "place: " << err << " at " << static_cast<unsigned>(sp_ - divstr_);
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
const char* _m_eat_whitespace(const char* sp)
|
||||
static const char* _m_eat_whitespace(const char* sp)
|
||||
{
|
||||
while (*sp && !isgraph(*sp))
|
||||
++sp;
|
||||
@ -677,7 +673,7 @@ namespace nana
|
||||
|
||||
if (gotcha)
|
||||
{
|
||||
for (; *sp == ' ' || *sp == '\t'; ++sp);
|
||||
sp = _m_eat_whitespace(sp);
|
||||
if ('%' == *sp)
|
||||
{
|
||||
if (number_t::kind::integer == number_.kind_of())
|
||||
@ -757,6 +753,20 @@ namespace nana
|
||||
for (auto & e : fastened)
|
||||
API::show_window(e.handle, vsb);
|
||||
}
|
||||
|
||||
static event_handle erase_element(std::vector<element_t>& elements, window handle)
|
||||
{
|
||||
for (auto i = elements.begin(), end = elements.end(); i != end; ++i)
|
||||
{
|
||||
if (i->handle == handle)
|
||||
{
|
||||
auto evt_destroy = i->evt_destroy;
|
||||
elements.erase(i);
|
||||
return evt_destroy;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
private:
|
||||
//The defintion is moved after the definition of class division
|
||||
template<typename Function>
|
||||
@ -768,15 +778,8 @@ namespace nana
|
||||
{
|
||||
return API::events(wd).destroy.connect([this](const arg_destroy& arg)
|
||||
{
|
||||
for (auto i = elements.begin(), end = elements.end(); i != end; ++i)
|
||||
{
|
||||
if (arg.window_handle == i->handle)
|
||||
{
|
||||
elements.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
place_ptr_->collocate();
|
||||
if (erase_element(elements, arg.window_handle))
|
||||
place_ptr_->collocate();
|
||||
});
|
||||
}
|
||||
|
||||
@ -815,13 +818,7 @@ namespace nana
|
||||
//does not change the layout.
|
||||
auto evt = API::events(wd).destroy([this](const arg_destroy& arg)
|
||||
{
|
||||
auto destroyed_wd = arg.window_handle;
|
||||
auto i = std::find_if(fastened.begin(), fastened.end(), [destroyed_wd](element_t& e){
|
||||
return (e.handle == destroyed_wd);
|
||||
});
|
||||
|
||||
if (i != fastened.end())
|
||||
fastened.erase(i);
|
||||
erase_element(fastened, arg.window_handle);
|
||||
});
|
||||
|
||||
fastened.emplace_back(wd, evt);
|
||||
@ -929,16 +926,9 @@ namespace nana
|
||||
{
|
||||
for (auto & child : div->children)
|
||||
{
|
||||
if (child->field)
|
||||
{
|
||||
if (vsb)
|
||||
{
|
||||
if (child->visible)
|
||||
child->field->visible(true);
|
||||
}
|
||||
else
|
||||
child->field->visible(false);
|
||||
}
|
||||
if (child->field && (!vsb || child->visible))
|
||||
child->field->visible(vsb);
|
||||
|
||||
_m_visible_for_child(child.get(), vsb);
|
||||
}
|
||||
}
|
||||
@ -985,7 +975,7 @@ namespace nana
|
||||
const bool vert = (kind::arrange != kind_of_division);
|
||||
|
||||
auto area_margined = margin_area();
|
||||
area_rotator area(vert, area_margined);
|
||||
rectangle_rotator area(vert, area_margined);
|
||||
auto area_px = area.w();
|
||||
|
||||
auto fa = _m_fixed_and_adjustable(kind_of_division, area_px);
|
||||
@ -1001,7 +991,7 @@ namespace nana
|
||||
if(!child->display) //Ignore the division if the corresponding field is not displayed.
|
||||
continue;
|
||||
|
||||
area_rotator child_area(vert, child->field_area);
|
||||
rectangle_rotator child_area(vert, child->field_area);
|
||||
child_area.x_ref() = static_cast<int>(position);
|
||||
child_area.y_ref() = area.y();
|
||||
child_area.h_ref() = area.h();
|
||||
@ -1510,17 +1500,6 @@ namespace nana
|
||||
class place::implement::div_splitter
|
||||
: public division
|
||||
{
|
||||
struct div_block
|
||||
{
|
||||
division * div;
|
||||
int pixels;
|
||||
double scale;
|
||||
|
||||
div_block(division* d, int px)
|
||||
: div(d), pixels(px)
|
||||
{}
|
||||
};
|
||||
|
||||
enum{splitter_px = 4};
|
||||
public:
|
||||
div_splitter(place_parts::number_t init_weight)
|
||||
@ -1533,14 +1512,9 @@ namespace nana
|
||||
this->weight.assign(splitter_px);
|
||||
}
|
||||
|
||||
void leaf_left(division * d)
|
||||
void set_leaf(bool is_left, division * d)
|
||||
{
|
||||
leaf_left_ = d;
|
||||
}
|
||||
|
||||
void leaf_right(division * d)
|
||||
{
|
||||
leaf_right_ = d;
|
||||
(is_left ? leaf_left_ : leaf_right_) = d;
|
||||
}
|
||||
|
||||
void direction(bool horizontal)
|
||||
@ -1565,8 +1539,9 @@ namespace nana
|
||||
|
||||
auto px_ptr = &nana::rectangle::width;
|
||||
|
||||
auto area_left = leaf_left_->margin_area();
|
||||
auto area_right = leaf_right_->margin_area();
|
||||
//Use field_area of leaf, not margin_area. Otherwise splitter would be at wrong position
|
||||
auto area_left = leaf_left_->field_area;
|
||||
auto area_right = leaf_right_->field_area;
|
||||
|
||||
if (nana::cursor::size_we != splitter_cursor_)
|
||||
{
|
||||
@ -1590,7 +1565,7 @@ namespace nana
|
||||
return;
|
||||
|
||||
const bool vert = (::nana::cursor::size_we != splitter_cursor_);
|
||||
auto area_px = area_rotator(vert, div_owner->margin_area()).w();
|
||||
auto area_px = rectangle_rotator(vert, div_owner->margin_area()).w();
|
||||
int delta = (vert ? splitter_.pos().y - begin_point_.y : splitter_.pos().x - begin_point_.x);
|
||||
|
||||
int total_pixels = static_cast<int>(left_pixels_ + right_pixels_);
|
||||
@ -1631,8 +1606,8 @@ namespace nana
|
||||
{
|
||||
const bool vert = (::nana::cursor::size_we != splitter_cursor_);
|
||||
|
||||
area_rotator left(vert, leaf_left_->field_area);
|
||||
area_rotator right(vert, leaf_right_->field_area);
|
||||
rectangle_rotator left(vert, leaf_left_->field_area);
|
||||
rectangle_rotator right(vert, leaf_right_->field_area);
|
||||
auto area_px = right.right() - left.x();
|
||||
auto right_px = static_cast<int>(limit_px(leaf_right_, init_weight_.get_value(area_px), static_cast<unsigned>(area_px)));
|
||||
|
||||
@ -1642,7 +1617,7 @@ namespace nana
|
||||
else if (pos > limited_range.right())
|
||||
pos = limited_range.right();
|
||||
|
||||
area_rotator sp_r(vert, field_area);
|
||||
nana::rectangle_rotator sp_r(vert, field_area);
|
||||
sp_r.x_ref() = pos;
|
||||
|
||||
left.w_ref() = static_cast<unsigned>(pos - left.x());
|
||||
@ -1658,7 +1633,7 @@ namespace nana
|
||||
leaf_right_->collocate(wd);
|
||||
|
||||
//Set the leafs' weight
|
||||
area_rotator area(vert, div_owner->field_area);
|
||||
rectangle_rotator area(vert, div_owner->field_area);
|
||||
|
||||
double imd_rate = 100.0 / static_cast<int>(area.w());
|
||||
leaf_left_->weight.assign_percent(imd_rate * static_cast<int>(left.w()));
|
||||
@ -1673,14 +1648,14 @@ namespace nana
|
||||
splitter_.move(this->field_area);
|
||||
}
|
||||
private:
|
||||
area_rotator _m_update_splitter_range()
|
||||
rectangle_rotator _m_update_splitter_range()
|
||||
{
|
||||
const bool vert = (cursor::size_ns == splitter_cursor_);
|
||||
|
||||
area_rotator area(vert, div_owner->margin_area());
|
||||
rectangle_rotator area(vert, div_owner->margin_area());
|
||||
|
||||
area_rotator left(vert, leaf_left_->field_area);
|
||||
area_rotator right(vert, leaf_right_->field_area);
|
||||
rectangle_rotator left(vert, leaf_left_->field_area);
|
||||
rectangle_rotator right(vert, leaf_right_->field_area);
|
||||
|
||||
const int left_base = left.x(), right_base = right.right();
|
||||
int pos = left_base;
|
||||
@ -1785,7 +1760,7 @@ namespace nana
|
||||
if (!children.empty() && (division::kind::splitter != children.back()->kind_of_division))
|
||||
{
|
||||
auto splitter = new div_splitter(tknizer.number());
|
||||
splitter->leaf_left(children.back().get());
|
||||
splitter->set_leaf(true, children.back().get());
|
||||
children.back()->div_next = splitter;
|
||||
children.emplace_back(splitter);
|
||||
}
|
||||
@ -1797,7 +1772,7 @@ namespace nana
|
||||
{
|
||||
children.back()->div_next = div.get();
|
||||
if (division::kind::splitter == children.back()->kind_of_division)
|
||||
dynamic_cast<div_splitter&>(*children.back()).leaf_right(div.get());
|
||||
dynamic_cast<div_splitter&>(*children.back()).set_leaf(false, div.get());
|
||||
}
|
||||
children.emplace_back(div.release());
|
||||
}
|
||||
@ -2182,29 +2157,14 @@ namespace nana
|
||||
bool recollocate = false;
|
||||
for (auto & fld : impl_->fields)
|
||||
{
|
||||
auto & elements = fld.second->elements;
|
||||
for (auto i = elements.begin(); i != elements.end();)
|
||||
auto evt = fld.second->erase_element(fld.second->elements, handle);
|
||||
if (evt)
|
||||
{
|
||||
if (i->handle == handle)
|
||||
{
|
||||
API::umake_event(i->evt_destroy);
|
||||
i = elements.erase(i);
|
||||
recollocate |= (nullptr != fld.second->attached);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
API::umake_event(evt);
|
||||
recollocate |= (nullptr != fld.second->attached);
|
||||
}
|
||||
|
||||
auto i = std::find_if(fld.second->fastened.begin(), fld.second->fastened.end(), [handle](implement::field_impl::element_t& e)
|
||||
{
|
||||
return (e.handle == handle);
|
||||
});
|
||||
|
||||
if (i != fld.second->fastened.end())
|
||||
{
|
||||
API::umake_event(i->evt_destroy);
|
||||
fld.second->fastened.erase(i);
|
||||
}
|
||||
API::umake_event( fld.second->erase_element(fld.second->fastened, handle));
|
||||
}
|
||||
|
||||
if (recollocate)
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
/*
|
||||
* Nana GUI Programming Interface Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 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.cpp
|
||||
* @author: Jinhao
|
||||
*/
|
||||
|
||||
#include <nana/gui/programming_interface.hpp>
|
||||
@ -15,7 +16,6 @@
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/widgets/widget.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -53,7 +53,7 @@ namespace API
|
||||
if (!restrict::window_manager.available(reinterpret_cast<restrict::core_window_t*>(wd)))
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<restrict::core_window_t*>(wd)->together.attached_events;
|
||||
return reinterpret_cast<restrict::core_window_t*>(wd)->together.events_ptr.get();
|
||||
}
|
||||
}//end namespace detail
|
||||
|
||||
@ -239,6 +239,11 @@ namespace API
|
||||
return &reinterpret_cast<restrict::core_window_t*>(wd)->drawer.graphics;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void delay_restore(bool enable)
|
||||
{
|
||||
restrict::bedrock.delay_restore(enable ? 0 : 1);
|
||||
}
|
||||
}//end namespace dev
|
||||
|
||||
//exit
|
||||
@ -259,8 +264,20 @@ namespace API
|
||||
if((wd->thread_id == tid) && (wd->root != root))
|
||||
{
|
||||
root = wd->root;
|
||||
if(roots.cend() == std::find(roots.cbegin(), roots.cend(), root))
|
||||
for (auto i = roots.cbegin(); i != roots.cend(); ++i)
|
||||
{
|
||||
if (*i == root)
|
||||
{
|
||||
root = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!root)
|
||||
{
|
||||
root = wd->root;
|
||||
roots.push_back(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,7 +615,7 @@ namespace API
|
||||
nana::size window_size(window wd)
|
||||
{
|
||||
nana::rectangle r;
|
||||
API::window_rectangle(wd, r);
|
||||
API::get_window_rectangle(wd, r);
|
||||
return{ r.width, r.height };
|
||||
}
|
||||
|
||||
@ -618,7 +635,46 @@ namespace API
|
||||
}
|
||||
}
|
||||
|
||||
bool window_rectangle(window wd, rectangle& r)
|
||||
::nana::size window_outline_size(window wd)
|
||||
{
|
||||
auto iwd = reinterpret_cast<restrict::core_window_t*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (!restrict::window_manager.available(iwd))
|
||||
return{};
|
||||
|
||||
auto sz = window_size(wd);
|
||||
sz.width += iwd->extra_width;
|
||||
sz.height += iwd->extra_height;
|
||||
return sz;
|
||||
}
|
||||
|
||||
void window_outline_size(window wd, const size& sz)
|
||||
{
|
||||
auto iwd = reinterpret_cast<restrict::core_window_t*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::window_manager.available(iwd))
|
||||
{
|
||||
if (category::flags::root == iwd->other.category)
|
||||
{
|
||||
size inner_size = sz;
|
||||
if (inner_size.width < iwd->extra_width)
|
||||
inner_size.width = 0;
|
||||
else
|
||||
inner_size.width -= iwd->extra_width;
|
||||
|
||||
if (inner_size.height < iwd->extra_height)
|
||||
inner_size.height = 0;
|
||||
else
|
||||
inner_size.height -= iwd->extra_height;
|
||||
|
||||
window_size(wd, inner_size);
|
||||
}
|
||||
else
|
||||
window_size(wd, sz);
|
||||
}
|
||||
}
|
||||
|
||||
bool get_window_rectangle(window wd, rectangle& r)
|
||||
{
|
||||
auto iwd = reinterpret_cast<restrict::core_window_t*>(wd);
|
||||
internal_scope_guard lock;
|
||||
@ -751,7 +807,7 @@ namespace API
|
||||
return cursor::arrow;
|
||||
}
|
||||
|
||||
bool is_focus_window(window wd)
|
||||
bool is_focus_ready(window wd)
|
||||
{
|
||||
auto iwd = reinterpret_cast<restrict::core_window_t*>(wd);
|
||||
internal_scope_guard lock;
|
||||
@ -1163,17 +1219,6 @@ namespace API
|
||||
}
|
||||
}
|
||||
|
||||
void restore_menubar_taken_window()
|
||||
{
|
||||
auto wd = restrict::bedrock.get_menubar_taken();
|
||||
if(wd)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
restrict::window_manager.set_focus(wd, false);
|
||||
restrict::window_manager.update(wd, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_window_zoomed(window wd, bool ask_for_max)
|
||||
{
|
||||
auto const iwd = reinterpret_cast<restrict::core_window_t*>(wd);
|
||||
|
||||
@ -25,39 +25,22 @@ namespace nana
|
||||
: public display
|
||||
{
|
||||
public:
|
||||
real_display(std::size_t number)
|
||||
: index_(number)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
DISPLAY_DEVICE disp;
|
||||
disp.cb = sizeof disp;
|
||||
if (::EnumDisplayDevices(nullptr, static_cast<DWORD>(index_), &disp, 0))
|
||||
{
|
||||
DEVMODE mode;
|
||||
mode.dmSize = sizeof mode;
|
||||
if (::EnumDisplaySettings(disp.DeviceName, ENUM_CURRENT_SETTINGS, &mode))
|
||||
{
|
||||
area_.x = mode.dmPosition.x;
|
||||
area_.y = mode.dmPosition.y;
|
||||
area_.width = mode.dmPelsWidth;
|
||||
area_.height = mode.dmPelsHeight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (0 == index_)
|
||||
{
|
||||
area_ = detail::native_interface::primary_monitor_size();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
throw std::invalid_argument("Nana.Screen: Invalid monitor index.");
|
||||
}
|
||||
real_display() = default; //For requirement of vector
|
||||
|
||||
real_display(std::size_t number, const ::nana::rectangle& r)
|
||||
: index_(number), area_(r)
|
||||
#if defined(NANA_WINDOWS)
|
||||
real_display(std::size_t number, const MONITORINFOEX& mi)
|
||||
: index_(number),
|
||||
is_primary_(mi.dwFlags & /*MONITORINFOF_PRIMARY*/ 0x1),
|
||||
area_(mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top),
|
||||
workarea_(mi.rcWork.left, mi.rcWork.top, mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top)
|
||||
{
|
||||
}
|
||||
#else
|
||||
real_display(std::size_t number, const ::nana::rectangle& r)
|
||||
: index_(number), is_primary_(true), area_(r), workarea_(r)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
//Implementation of display
|
||||
std::size_t get_index() const override
|
||||
@ -65,13 +48,25 @@ namespace nana
|
||||
return index_;
|
||||
}
|
||||
|
||||
bool is_primary_monitor() const override
|
||||
{
|
||||
return is_primary_;
|
||||
}
|
||||
|
||||
const ::nana::rectangle& area() const override
|
||||
{
|
||||
return area_;
|
||||
}
|
||||
|
||||
const ::nana::rectangle& workarea() const override
|
||||
{
|
||||
return workarea_;
|
||||
}
|
||||
private:
|
||||
const std::size_t index_;
|
||||
std::size_t index_;
|
||||
bool is_primary_;
|
||||
::nana::rectangle area_;
|
||||
::nana::rectangle workarea_;
|
||||
};
|
||||
|
||||
//class screen
|
||||
@ -92,7 +87,61 @@ namespace nana
|
||||
return ::nana::detail::native_interface::primary_monitor_size();
|
||||
}
|
||||
|
||||
std::shared_ptr<display> screen::from_point(const point& pos)
|
||||
|
||||
struct screen::implement
|
||||
{
|
||||
std::vector<real_display> displays;
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
void load_monitors()
|
||||
{
|
||||
std::vector<real_display> tmp;
|
||||
::EnumDisplayMonitors(nullptr, nullptr, implement::enum_proc, reinterpret_cast<LPARAM>(&tmp));
|
||||
tmp.swap(displays);
|
||||
}
|
||||
|
||||
static BOOL __stdcall enum_proc(HMONITOR handle, HDC context, LPRECT r, LPARAM self_ptr)
|
||||
{
|
||||
auto disp_cont = reinterpret_cast<std::vector<real_display>*>(self_ptr);
|
||||
MONITORINFOEX mi;
|
||||
mi.cbSize = sizeof(MONITORINFOEX);
|
||||
if (::GetMonitorInfo(handle, &mi))
|
||||
disp_cont->emplace_back(disp_cont->size(), mi);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
void load_monitors()
|
||||
{
|
||||
displays.clear();
|
||||
displays.emplace_back(0, primary_monitor_size());
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
screen::screen()
|
||||
: impl_(std::make_shared<implement>())
|
||||
{
|
||||
impl_->load_monitors();
|
||||
}
|
||||
|
||||
void screen::reload()
|
||||
{
|
||||
//It is only when the screen is a moved-from object that impl_ is empty
|
||||
if (!impl_)
|
||||
std::make_shared<implement>().swap(impl_);
|
||||
|
||||
impl_->load_monitors();
|
||||
}
|
||||
|
||||
std::size_t screen::count() const
|
||||
{
|
||||
return impl_->displays.size();
|
||||
}
|
||||
|
||||
|
||||
display& screen::from_point(const point& pos)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
typedef HMONITOR(__stdcall * MonitorFromPointT)(POINT, DWORD);
|
||||
@ -107,87 +156,47 @@ namespace nana
|
||||
mi.cbSize = sizeof mi;
|
||||
if (::GetMonitorInfo(monitor, &mi))
|
||||
{
|
||||
DISPLAY_DEVICE disp;
|
||||
disp.cb = sizeof disp;
|
||||
|
||||
DWORD index = 0;
|
||||
while (::EnumDisplayDevices(nullptr, index++, &disp, 0))
|
||||
for (auto & disp : impl_->displays)
|
||||
{
|
||||
DEVMODE mode;
|
||||
mode.dmSize = sizeof mode;
|
||||
if (::EnumDisplaySettings(disp.DeviceName, ENUM_CURRENT_SETTINGS, &mode))
|
||||
{
|
||||
if (mode.dmPosition.x == mi.rcWork.left && mode.dmPosition.y == mi.rcWork.top &&
|
||||
(static_cast<int>(mode.dmPelsWidth) == mi.rcWork.right - mi.rcWork.left) &&
|
||||
(static_cast<int>(mode.dmPelsHeight) == mi.rcWork.bottom - mi.rcWork.top))
|
||||
{
|
||||
return std::make_shared<real_display>(static_cast<std::size_t>(index - 1), rectangle{ mode.dmPosition.x, mode.dmPosition.y, static_cast<unsigned>(mode.dmPelsWidth), static_cast<unsigned>(mode.dmPelsHeight) });
|
||||
}
|
||||
}
|
||||
auto & r = disp.area();
|
||||
if (r.x == mi.rcMonitor.left && r.y == mi.rcMonitor.top &&
|
||||
r.width == unsigned(mi.rcMonitor.right - mi.rcMonitor.left) &&
|
||||
r.height == unsigned(mi.rcMonitor.bottom - mi.rcMonitor.top)
|
||||
)
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return screen().get_primary();
|
||||
return get_primary();
|
||||
}
|
||||
|
||||
std::shared_ptr<display> screen::from_window(window wd)
|
||||
display& screen::from_window(window wd)
|
||||
{
|
||||
::nana::point pos;
|
||||
API::calc_screen_point(wd, pos);
|
||||
return from_point(pos);
|
||||
}
|
||||
|
||||
std::size_t screen::count() const
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
DISPLAY_DEVICE disp;
|
||||
disp.cb = sizeof disp;
|
||||
|
||||
DWORD index = 0;
|
||||
while (::EnumDisplayDevices(nullptr, index++, &disp, 0));
|
||||
return static_cast<std::size_t>(index - 1);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
display& screen::get_display(std::size_t index) const
|
||||
{
|
||||
return impl_->displays.at(index);
|
||||
}
|
||||
|
||||
std::shared_ptr<display> screen::get_display(std::size_t index) const
|
||||
display& screen::get_primary() const
|
||||
{
|
||||
return std::make_shared<real_display>(index);
|
||||
}
|
||||
for (auto & disp : impl_->displays)
|
||||
if (disp.is_primary_monitor())
|
||||
return disp;
|
||||
|
||||
std::shared_ptr<display> screen::get_primary() const
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
//return rectangle(mi.rcWork.left, mi.rcWork.top,
|
||||
// mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top);
|
||||
DISPLAY_DEVICE disp;
|
||||
disp.cb = sizeof disp;
|
||||
|
||||
DWORD index = 0;
|
||||
while (::EnumDisplayDevices(nullptr, index++, &disp, 0))
|
||||
{
|
||||
DEVMODE mode;
|
||||
mode.dmSize = sizeof mode;
|
||||
if (::EnumDisplaySettings(disp.DeviceName, ENUM_CURRENT_SETTINGS, &mode))
|
||||
{
|
||||
if (mode.dmPosition.x == 0 && mode.dmPosition.y == 0)
|
||||
return std::make_shared<real_display>(static_cast<std::size_t>(index - 1), rectangle{ mode.dmPosition.x, mode.dmPosition.y, static_cast<unsigned>(mode.dmPelsWidth), static_cast<unsigned>(mode.dmPelsHeight) });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return std::make_shared<real_display>(0);
|
||||
throw std::logic_error("no primary monitor found");
|
||||
}
|
||||
|
||||
void screen::for_each(std::function<void(display&)> fn) const
|
||||
{
|
||||
auto n = count();
|
||||
for (decltype(n) i = 0; i < n; ++i)
|
||||
{
|
||||
real_display disp(i);
|
||||
for (auto & disp : impl_->displays)
|
||||
fn(disp);
|
||||
}
|
||||
}
|
||||
//end class screen
|
||||
}
|
||||
|
||||
@ -109,11 +109,11 @@ namespace nana
|
||||
{
|
||||
public:
|
||||
#if defined(NANA_WINDOWS)
|
||||
timer_core(timer_identifier tmid, const nana::basic_event<arg_elapse>& evt_elapse)
|
||||
timer_core(timer_identifier tmid, basic_event<arg_elapse>& evt_elapse)
|
||||
: timer_(tmid), evt_elapse_(evt_elapse)
|
||||
{}
|
||||
#else
|
||||
timer_core(const nana::basic_event<arg_elapse>& evt_elapse)
|
||||
timer_core(basic_event<arg_elapse>& evt_elapse)
|
||||
: timer_(this), evt_elapse_(evt_elapse)
|
||||
{}
|
||||
#endif
|
||||
@ -138,7 +138,7 @@ namespace nana
|
||||
}
|
||||
private:
|
||||
const timer_identifier timer_;
|
||||
const nana::basic_event<arg_elapse> & evt_elapse_;
|
||||
nana::basic_event<arg_elapse> & evt_elapse_;
|
||||
}; //end class timer_core
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* A Tooltip Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -34,14 +35,14 @@ namespace nana
|
||||
|
||||
nana::point pos_by_screen(nana::point pos, const nana::size& sz, bool overlap_allowed)
|
||||
{
|
||||
auto scr_area = screen::from_point(pos)->area();
|
||||
if (pos.x + sz.width > scr_area.x + scr_area.width)
|
||||
pos.x = static_cast<int>(scr_area.x + scr_area.width - sz.width);
|
||||
auto scr_area = screen().from_point(pos).workarea();
|
||||
if (pos.x + static_cast<int>(sz.width) > scr_area.right())
|
||||
pos.x = scr_area.right() - static_cast<int>(sz.width);
|
||||
if (pos.x < scr_area.x)
|
||||
pos.x = scr_area.x;
|
||||
|
||||
if (pos.y + sz.height >= scr_area.y + scr_area.height)
|
||||
pos.y = static_cast<int>(scr_area.y + scr_area.height - sz.height);
|
||||
if (pos.y + static_cast<int>(sz.height) >= scr_area.bottom())
|
||||
pos.y = scr_area.bottom() - static_cast<int>(sz.height);
|
||||
else if (!overlap_allowed)
|
||||
pos.y += 20; //Add some pixels to avoid overlapping between cursor and tip window.
|
||||
|
||||
@ -77,7 +78,7 @@ namespace nana
|
||||
void tooltip_text(const nana::string& text) override
|
||||
{
|
||||
label_.caption(text);
|
||||
auto text_s = label_.measure(screen::from_window(label_)->area().width * 2 / 3);
|
||||
auto text_s = label_.measure(screen().from_window(label_).workarea().width * 2 / 3);
|
||||
this->size(nana::size{ text_s.width + 10, text_s.height + 10 });
|
||||
label_.move(rectangle{ 5, 5, text_s.width, text_s.height });
|
||||
|
||||
|
||||
@ -129,22 +129,26 @@ namespace checkbox
|
||||
checkbox::checkbox(window wd, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
checkbox::checkbox(window wd, const nana::string& text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
checkbox::checkbox(window wd, const nana::char_t* text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
checkbox::checkbox(window wd, const nana::rectangle& r, bool visible)
|
||||
{
|
||||
bgcolor(API::bgcolor(wd));
|
||||
create(wd, r, visible);
|
||||
}
|
||||
|
||||
|
||||
@ -677,6 +677,7 @@ namespace nana
|
||||
if(!drawer_->widget_ptr()->enabled())
|
||||
return;
|
||||
|
||||
bool call_other_keys = false;
|
||||
if(drawer_->editable())
|
||||
{
|
||||
bool is_move_up = false;
|
||||
@ -684,7 +685,7 @@ namespace nana
|
||||
{
|
||||
case keyboard::os_arrow_left:
|
||||
case keyboard::os_arrow_right:
|
||||
drawer_->editor()->move(arg.key);
|
||||
drawer_->editor()->respond_key(arg.key);
|
||||
drawer_->editor()->reset_caret();
|
||||
break;
|
||||
case keyboard::os_arrow_up:
|
||||
@ -692,6 +693,8 @@ namespace nana
|
||||
case keyboard::os_arrow_down:
|
||||
drawer_->move_items(is_move_up, true);
|
||||
break;
|
||||
default:
|
||||
call_other_keys = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -706,14 +709,19 @@ namespace nana
|
||||
case keyboard::os_arrow_down:
|
||||
drawer_->move_items(is_move_up, true);
|
||||
break;
|
||||
default:
|
||||
call_other_keys = true;
|
||||
}
|
||||
}
|
||||
if (call_other_keys)
|
||||
drawer_->editor()->respond_key(arg.key);
|
||||
|
||||
API::lazy_refresh();
|
||||
}
|
||||
|
||||
void trigger::key_char(graph_reference graph, const arg_keyboard& arg)
|
||||
{
|
||||
if (drawer_->editor()->respone_keyboard(arg.key))
|
||||
if (drawer_->editor()->respond_char(arg.key))
|
||||
API::lazy_refresh();
|
||||
}
|
||||
//end class trigger
|
||||
|
||||
@ -37,21 +37,25 @@ namespace nana
|
||||
::nana::color clr{ 0xaf, 0xc7, 0xe3 };
|
||||
graph.rectangle(r, false, clr);
|
||||
|
||||
auto right = r.right() - 1;
|
||||
auto bottom = r.bottom() - 1;
|
||||
graph.set_color(colors::white);
|
||||
graph.set_pixel(r.x, r.y);
|
||||
graph.set_pixel(r.x + r.width - 1, r.y);
|
||||
graph.set_pixel(r.x, r.y + r.height - 1);
|
||||
graph.set_pixel(r.x + r.width - 1, r.y + r.height - 1);
|
||||
graph.set_pixel(right, r.y);
|
||||
graph.set_pixel(r.x, bottom);
|
||||
graph.set_pixel(right, bottom);
|
||||
|
||||
--right;
|
||||
--bottom;
|
||||
graph.set_color(clr);
|
||||
graph.set_pixel(r.x + 1, r.y + 1);
|
||||
graph.set_pixel(r.x + r.width - 2, r.y + 1);
|
||||
graph.set_pixel(r.x + 1, r.y + r.height - 2);
|
||||
graph.set_pixel(r.x + r.width - 2, r.y + r.height - 2);
|
||||
graph.set_pixel(right, r.y + 1);
|
||||
graph.set_pixel(r.x + 1, bottom);
|
||||
graph.set_pixel(right, bottom);
|
||||
|
||||
nana::rectangle po_r(r);
|
||||
graph.rectangle(po_r.pare_off(1), false, { 0xEB, 0xF4, 0xFB });
|
||||
graph.gradual_rectangle(po_r.pare_off(1), { 0xDD, 0xEC, 0xFD }, { 0xC2, 0xDC, 0xFD }, true);
|
||||
graph.rectangle(po_r.pare_off(1), false, static_cast<color_rgb>(0xEBF4FB));
|
||||
graph.gradual_rectangle(po_r.pare_off(1), static_cast<color_rgb>(0xDDECFD), static_cast<color_rgb>(0xC2DCFD), true);
|
||||
}
|
||||
else
|
||||
graph.rectangle(r, true, colors::white);
|
||||
@ -113,13 +117,8 @@ namespace nana
|
||||
class drawer_impl
|
||||
{
|
||||
public:
|
||||
typedef widget& widget_reference;
|
||||
typedef nana::paint::graphics& graph_reference;
|
||||
|
||||
drawer_impl()
|
||||
: widget_(nullptr), graph_(nullptr), image_pixels_(16),
|
||||
ignore_first_mouseup_(true), module_(nullptr)
|
||||
{}
|
||||
using widget_reference = widget&;
|
||||
using graph_reference = paint::graphics&;
|
||||
|
||||
void clear_state()
|
||||
{
|
||||
@ -151,25 +150,19 @@ namespace nana
|
||||
{
|
||||
if(scrollbar_.empty()) return;
|
||||
|
||||
bool update = false;
|
||||
const auto before_change = state_.offset_y;
|
||||
if(upwards)
|
||||
{
|
||||
if(state_.offset_y)
|
||||
{
|
||||
if (before_change)
|
||||
--(state_.offset_y);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((state_.offset_y + module_->max_items) < module_->items.size())
|
||||
{
|
||||
if ((before_change + module_->max_items) < module_->items.size())
|
||||
++(state_.offset_y);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(update)
|
||||
if(before_change != state_.offset_y)
|
||||
{
|
||||
draw();
|
||||
scrollbar_.value(state_.offset_y);
|
||||
@ -323,8 +316,7 @@ namespace nana
|
||||
state_.renderer->image(_m_image_enabled(), image_pixels_);
|
||||
for(std::size_t i = state_.offset_y; i < items; ++i)
|
||||
{
|
||||
item_renderer::state_t state = item_renderer::StateNone;
|
||||
if(i == state_.index) state = item_renderer::StateHighlighted;
|
||||
auto state = (i != state_.index ? item_renderer::StateNone : item_renderer::StateHighlighted);
|
||||
|
||||
state_.renderer->render(*widget_, *graph_, item_r, module_->items[i].get(), state);
|
||||
item_r.y += item_pixels;
|
||||
@ -384,20 +376,20 @@ namespace nana
|
||||
scrollbar_.close();
|
||||
}
|
||||
private:
|
||||
widget * widget_;
|
||||
nana::paint::graphics * graph_;
|
||||
unsigned image_pixels_; //Define the width pixels of the image area
|
||||
widget * widget_{nullptr};
|
||||
nana::paint::graphics * graph_{nullptr};
|
||||
unsigned image_pixels_{16}; //Define the width pixels of the image area
|
||||
|
||||
bool ignore_first_mouseup_;
|
||||
bool ignore_first_mouseup_{true};
|
||||
struct state_type
|
||||
{
|
||||
std::size_t offset_y;
|
||||
std::size_t index; //The index of the selected item.
|
||||
std::size_t offset_y{0};
|
||||
std::size_t index{npos}; //The index of the selected item.
|
||||
|
||||
item_renderer * const orig_renderer;
|
||||
item_renderer * renderer;
|
||||
|
||||
state_type(): offset_y(0), index(npos), orig_renderer(new def_item_renderer), renderer(orig_renderer){}
|
||||
state_type(): orig_renderer(new def_item_renderer), renderer(orig_renderer){}
|
||||
~state_type()
|
||||
{
|
||||
delete orig_renderer;
|
||||
@ -405,7 +397,7 @@ namespace nana
|
||||
}state_;
|
||||
nana::scroll<true> scrollbar_;
|
||||
|
||||
const module_def* module_;
|
||||
const module_def* module_{nullptr};
|
||||
};
|
||||
|
||||
//class drawer_impl;
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: source/gui/widgets/label.cpp
|
||||
* @author: Jinhao
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/label.hpp>
|
||||
@ -586,8 +588,6 @@ namespace nana
|
||||
|
||||
std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos)
|
||||
{
|
||||
std::pair<std::size_t, std::size_t> r;
|
||||
|
||||
std::size_t n = i->data_ptr->text().length();
|
||||
while(pos >= n)
|
||||
{
|
||||
@ -765,23 +765,27 @@ namespace nana
|
||||
label::label(window wd, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
label::label(window wd, const nana::string& text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
label::label(window wd, const nana::char_t* text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
label::label(window wd, const rectangle& r, bool visible)
|
||||
{
|
||||
create(wd, r, visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
label& label::transparent(bool enabled)
|
||||
@ -847,24 +851,16 @@ namespace nana
|
||||
|
||||
label& label::text_align(align th, align_v tv)
|
||||
{
|
||||
internal_scope_guard isg;
|
||||
internal_scope_guard lock;
|
||||
auto impl = get_drawer_trigger().impl();
|
||||
|
||||
bool to_update = false;
|
||||
if(impl->text_align != th)
|
||||
if (th != impl->text_align || tv != impl->text_align_v)
|
||||
{
|
||||
impl->text_align = th;
|
||||
to_update = true;
|
||||
}
|
||||
|
||||
if(impl->text_align_v != tv)
|
||||
{
|
||||
impl->text_align_v = tv;
|
||||
to_update = true;
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
|
||||
if(to_update)
|
||||
API::refresh_window(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Menu implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -106,7 +106,7 @@ namespace nana
|
||||
sz.width -= 30;
|
||||
sz.height -= 2;
|
||||
graph.rectangle(false, colors::gray_border);
|
||||
graph.rectangle({ 1, 1, 28, sz.height }, true, { 0xf6, 0xf6, 0xf6 });
|
||||
graph.rectangle({ 1, 1, 28, sz.height }, true, static_cast<color_rgb>(0xf6f6f6));
|
||||
graph.rectangle({ 29, 1, sz.width, sz.height }, true, colors::white);
|
||||
}
|
||||
|
||||
@ -122,17 +122,17 @@ namespace nana
|
||||
nana::point(r.x + r.width - 1, r.y + r.height - 1)
|
||||
};
|
||||
|
||||
graph.set_color({0xc0, 0xdd, 0xfc});
|
||||
graph.set_color(static_cast<color_rgb>(0xc0ddfc));
|
||||
for(int i = 0; i < 4; ++i)
|
||||
graph.set_pixel(points[i].x, points[i].y);
|
||||
|
||||
if(at.enabled)
|
||||
graph.gradual_rectangle(nana::rectangle(r).pare_off(1), { 0xE8, 0xF0, 0xF4 }, { 0xDB,0xEC,0xF4 }, true);
|
||||
graph.gradual_rectangle(nana::rectangle(r).pare_off(1), static_cast<color_rgb>(0xE8F0F4), static_cast<color_rgb>(0xDBECF4), true);
|
||||
}
|
||||
|
||||
if(at.checked && (checks::none != at.check_style))
|
||||
{
|
||||
graph.rectangle(r, false, { 0xCD, 0xD3, 0xE6 });
|
||||
graph.rectangle(r, false, static_cast<color_rgb>(0xCDD3E6));
|
||||
|
||||
::nana::color clr(0xE6, 0xEF, 0xF4);
|
||||
graph.rectangle(nana::rectangle(r).pare_off(1), true, clr);
|
||||
@ -151,7 +151,7 @@ namespace nana
|
||||
|
||||
void item_text(graph_reference graph, const nana::point& pos, const nana::string& text, unsigned text_pixels, const attr& at)
|
||||
{
|
||||
graph.set_color(at.enabled ? colors::black : colors::gray_border);
|
||||
graph.set_text_color(at.enabled ? colors::black : colors::gray_border);
|
||||
nana::paint::text_renderer tr(graph);
|
||||
tr.render(pos, text.c_str(), text.length(), text_pixels, true);
|
||||
}
|
||||
@ -363,59 +363,58 @@ namespace nana
|
||||
bool goto_next(bool forword)
|
||||
{
|
||||
state_.nullify_mouse = true;
|
||||
if(menu_->items.size())
|
||||
{
|
||||
std::size_t index = state_.active;
|
||||
if (menu_->items.empty())
|
||||
return false;
|
||||
|
||||
bool end = false;
|
||||
while(true)
|
||||
auto pos = state_.active;
|
||||
const auto lastpos = menu_->items.size() - 1;
|
||||
|
||||
bool end = false;
|
||||
while(true)
|
||||
{
|
||||
if(forword)
|
||||
{
|
||||
if(forword)
|
||||
if(pos == lastpos)
|
||||
{
|
||||
if(index == menu_->items.size() - 1)
|
||||
if (end)
|
||||
{
|
||||
if(end == false)
|
||||
{
|
||||
end = true;
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = npos;
|
||||
break;
|
||||
}
|
||||
pos = npos;
|
||||
break;
|
||||
}
|
||||
else
|
||||
++index;
|
||||
|
||||
end = true;
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(index == 0 || index == npos)
|
||||
{
|
||||
if(end == false)
|
||||
{
|
||||
end = true;
|
||||
index = menu_->items.size() - 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
--index;
|
||||
}
|
||||
if(menu_->items.at(index).flags.splitter == false)
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
|
||||
if(index != npos && index != state_.active)
|
||||
else
|
||||
{
|
||||
state_.active = index;
|
||||
state_.sub_window = false;
|
||||
|
||||
draw();
|
||||
return true;
|
||||
if(pos == 0 || pos == npos)
|
||||
{
|
||||
if (end)
|
||||
break;
|
||||
|
||||
end = true;
|
||||
pos = lastpos;
|
||||
}
|
||||
else
|
||||
--pos;
|
||||
}
|
||||
|
||||
if(! menu_->items.at(pos).flags.splitter)
|
||||
break;
|
||||
}
|
||||
|
||||
if(pos != npos && pos != state_.active)
|
||||
{
|
||||
state_.active = pos;
|
||||
state_.sub_window = false;
|
||||
|
||||
draw();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -486,30 +485,32 @@ namespace nana
|
||||
std::size_t index = 0;
|
||||
for(auto & m : menu_->items)
|
||||
{
|
||||
if(std::tolower(m.hotkey) == key)
|
||||
if (std::tolower(m.hotkey) != key)
|
||||
{
|
||||
if(!m.flags.splitter)
|
||||
{
|
||||
if(m.sub_menu)
|
||||
{
|
||||
state_.active = index;
|
||||
state_.active_timestamp = nana::system::timestamp();
|
||||
|
||||
draw();
|
||||
API::update_window(*widget_);
|
||||
return 2;
|
||||
}
|
||||
else if(m.flags.enabled)
|
||||
{
|
||||
std::move(fn_close_tree_)();
|
||||
item_proxy ip(index, m);
|
||||
m.functor.operator()(ip);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
++index;
|
||||
continue;
|
||||
}
|
||||
++index;
|
||||
|
||||
if(!m.flags.splitter)
|
||||
{
|
||||
if(m.sub_menu)
|
||||
{
|
||||
state_.active = index;
|
||||
state_.active_timestamp = nana::system::timestamp();
|
||||
|
||||
draw();
|
||||
API::update_window(*widget_);
|
||||
return 2;
|
||||
}
|
||||
else if(m.flags.enabled)
|
||||
{
|
||||
std::move(fn_close_tree_)();
|
||||
item_proxy ip(index, m);
|
||||
m.functor.operator()(ip);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -529,53 +530,53 @@ namespace nana
|
||||
|
||||
int text_top_off = (item_h_px - graph_->text_extent_size(STR("jh({[")).height) / 2;
|
||||
|
||||
std::size_t index = 0;
|
||||
std::size_t pos = 0;
|
||||
for(auto & m : menu_->items)
|
||||
{
|
||||
if(false == m.flags.splitter)
|
||||
{
|
||||
renderer_interface::attr attr = _m_make_renderer_attr(index == state_.active, m);
|
||||
//Draw item background
|
||||
renderer->item(*graph_, item_r, attr);
|
||||
|
||||
//Draw text, the text is transformed from orignal for hotkey character
|
||||
nana::char_t hotkey;
|
||||
nana::string::size_type hotkey_pos;
|
||||
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
|
||||
|
||||
if(m.image.empty() == false)
|
||||
renderer->item_image(*graph_, nana::point(item_r.x + 5, item_r.y + (item_h_px - m.image.size().height) / 2), m.image);
|
||||
|
||||
renderer->item_text(*graph_, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
|
||||
|
||||
if(hotkey)
|
||||
{
|
||||
m.hotkey = hotkey;
|
||||
if(m.flags.enabled)
|
||||
{
|
||||
unsigned off_w = (hotkey_pos ? graph_->text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
|
||||
nana::size hotkey_size = graph_->text_extent_size(text.c_str() + hotkey_pos, 1);
|
||||
int x = item_r.x + 40 + off_w;
|
||||
int y = item_r.y + text_top_off + hotkey_size.height;
|
||||
|
||||
graph_->set_color(colors::black);
|
||||
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
|
||||
}
|
||||
}
|
||||
|
||||
if(m.sub_menu)
|
||||
renderer->sub_arrow(*graph_, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
|
||||
|
||||
item_r.y += item_r.height + 1;
|
||||
}
|
||||
else
|
||||
if(m.flags.splitter)
|
||||
{
|
||||
graph_->set_color(colors::gray_border);
|
||||
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph_->width()) - 1, item_r.y });
|
||||
item_r.y += 2;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
|
||||
//Draw item background
|
||||
renderer->item(*graph_, item_r, attr);
|
||||
|
||||
//Draw text, the text is transformed from orignal for hotkey character
|
||||
nana::char_t hotkey;
|
||||
nana::string::size_type hotkey_pos;
|
||||
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
|
||||
|
||||
if(m.image.empty() == false)
|
||||
renderer->item_image(*graph_, nana::point(item_r.x + 5, item_r.y + (item_h_px - m.image.size().height) / 2), m.image);
|
||||
|
||||
renderer->item_text(*graph_, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
|
||||
|
||||
if(hotkey)
|
||||
{
|
||||
m.hotkey = hotkey;
|
||||
if(m.flags.enabled)
|
||||
{
|
||||
unsigned off_w = (hotkey_pos ? graph_->text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
|
||||
nana::size hotkey_size = graph_->text_extent_size(text.c_str() + hotkey_pos, 1);
|
||||
int x = item_r.x + 40 + off_w;
|
||||
int y = item_r.y + text_top_off + hotkey_size.height;
|
||||
|
||||
graph_->set_color(colors::black);
|
||||
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
|
||||
}
|
||||
}
|
||||
|
||||
++index;
|
||||
if(m.sub_menu)
|
||||
renderer->sub_arrow(*graph_, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
|
||||
|
||||
item_r.y += item_r.height + 1;
|
||||
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
private:
|
||||
@ -592,9 +593,9 @@ namespace nana
|
||||
std::size_t _m_get_index_by_pos(int x, int y) const
|
||||
{
|
||||
if( (x < static_cast<int>(detail_.border.x)) ||
|
||||
(x > static_cast<int>(graph_->width() - detail_.border.x)) ||
|
||||
(x > static_cast<int>(graph_->width()) - static_cast<int>(detail_.border.x)) ||
|
||||
(y < static_cast<int>(detail_.border.y)) ||
|
||||
(y > static_cast<int>(graph_->height() - detail_.border.y)))
|
||||
(y > static_cast<int>(graph_->height()) - static_cast<int>(detail_.border.y)))
|
||||
return npos;
|
||||
|
||||
int pos = detail_.border.y;
|
||||
@ -659,14 +660,14 @@ namespace nana
|
||||
API::calc_screen_point(*widget_, pos);
|
||||
|
||||
//get the screen coordinates of the widget pos.
|
||||
auto scr_area = screen::from_point(detail_.monitor_pos)->area();
|
||||
auto scr_area = screen().from_point(detail_.monitor_pos).workarea();
|
||||
|
||||
if(pos.x + size.width > scr_area.x + scr_area.width)
|
||||
pos.x = static_cast<int>(scr_area.x + scr_area.width - size.width);
|
||||
if(pos.x + static_cast<int>(size.width) > scr_area.right())
|
||||
pos.x = scr_area.right() - static_cast<int>(size.width);
|
||||
if(pos.x < scr_area.x) pos.x = scr_area.x;
|
||||
|
||||
if(pos.y + size.height > scr_area.y + scr_area.height)
|
||||
pos.y = static_cast<int>(scr_area.y + scr_area.height - size.height);
|
||||
if(pos.y + static_cast<int>(size.height) > scr_area.bottom())
|
||||
pos.y = scr_area.bottom() - static_cast<int>(size.height);
|
||||
if(pos.y < scr_area.y) pos.y = scr_area.y;
|
||||
|
||||
auto owner = API::get_owner_window(*widget_);
|
||||
@ -705,7 +706,7 @@ namespace nana
|
||||
|
||||
menu_window(window wd, const point& pos, renderer_interface * rdptr)
|
||||
: base_type(wd, false, rectangle(pos, nana::size(2, 2)), appear::bald<appear::floating>()),
|
||||
want_focus_(nullptr == wd),
|
||||
want_focus_(nullptr == wd || (API::focus_window() != wd)),
|
||||
event_focus_(nullptr)
|
||||
{
|
||||
caption(STR("nana menu window"));
|
||||
@ -729,11 +730,6 @@ namespace nana
|
||||
API::activate_window(this->parent());
|
||||
API::take_active(this->handle(), false, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
activate();
|
||||
focus();
|
||||
}
|
||||
|
||||
if(submenu_.parent == nullptr)
|
||||
{
|
||||
@ -753,14 +749,6 @@ namespace nana
|
||||
pick();
|
||||
});
|
||||
|
||||
if (want_focus_)
|
||||
{
|
||||
event_focus_ = events().focus.connect_unignorable([this](const arg_focus& arg)
|
||||
{
|
||||
_m_focus_changed(arg);
|
||||
});
|
||||
}
|
||||
|
||||
timer_.interval(100);
|
||||
timer_.elapse([this]{
|
||||
this->_m_check_repeatly();
|
||||
@ -768,6 +756,30 @@ namespace nana
|
||||
timer_.start();
|
||||
|
||||
show();
|
||||
|
||||
if (want_focus_)
|
||||
{
|
||||
event_focus_ = events().focus.connect_unignorable([this](const arg_focus& arg)
|
||||
{
|
||||
//when the focus of the menu window is losing, close the menu.
|
||||
//But here is not every menu window may have focus event installed,
|
||||
//It is only installed when the owner of window is the desktop window.
|
||||
|
||||
if (false == arg.getting && (arg.receiver != API::root(*this)))
|
||||
{
|
||||
for (auto child = submenu_.child; child; child = child->submenu_.child)
|
||||
{
|
||||
if (API::root(child->handle()) == arg.receiver)
|
||||
return;
|
||||
}
|
||||
|
||||
_m_close_all();
|
||||
}
|
||||
});
|
||||
|
||||
focus();
|
||||
activate();
|
||||
}
|
||||
}
|
||||
|
||||
void goto_next(bool forward)
|
||||
@ -783,39 +795,33 @@ namespace nana
|
||||
API::update_window(object->handle());
|
||||
}
|
||||
|
||||
bool goto_submenu()
|
||||
bool submenu(bool enter)
|
||||
{
|
||||
menu_window * object = this;
|
||||
while(object->submenu_.child)
|
||||
while (object->submenu_.child)
|
||||
object = object->submenu_.child;
|
||||
|
||||
state_.auto_popup_submenu = false;
|
||||
|
||||
if (enter)
|
||||
{
|
||||
if (object->submenu_.parent)
|
||||
{
|
||||
auto & sub = object->submenu_.parent->submenu_;
|
||||
sub.child = nullptr;
|
||||
sub.object = nullptr;
|
||||
|
||||
object->close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nana::point pos;
|
||||
menu_type * sbm = object->get_drawer_trigger().retrive_sub_menu(pos, 0);
|
||||
return object->_m_show_submenu(sbm, pos, true);
|
||||
}
|
||||
|
||||
bool exit_submenu()
|
||||
{
|
||||
menu_window * object =this;
|
||||
while(object->submenu_.child)
|
||||
object = object->submenu_.child;
|
||||
|
||||
state_.auto_popup_submenu = false;
|
||||
|
||||
if (object->submenu_.parent)
|
||||
{
|
||||
auto & sub = object->submenu_.parent->submenu_;
|
||||
sub.child = nullptr;
|
||||
sub.object = nullptr;
|
||||
|
||||
object->close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int send_shortkey(nana::char_t key)
|
||||
{
|
||||
menu_window * object = this;
|
||||
@ -832,62 +838,52 @@ namespace nana
|
||||
object = object->submenu_.child;
|
||||
|
||||
auto active = object->get_drawer_trigger().active();
|
||||
if (active != npos)
|
||||
auto * menu = object->get_drawer_trigger().data();
|
||||
if ((npos == active) || !menu)
|
||||
return;
|
||||
|
||||
menu_item_type & item = menu->items.at(active);
|
||||
if (item.flags.splitter == false && item.sub_menu == nullptr)
|
||||
{
|
||||
auto * menu = object->get_drawer_trigger().data();
|
||||
if (menu)
|
||||
//There is a situation that menu will not call functor if the item style is check_option
|
||||
//and it is checked before clicking.
|
||||
bool call_functor = true;
|
||||
|
||||
if (checks::highlight == item.style)
|
||||
{
|
||||
menu_item_type & item = menu->items.at(active);
|
||||
if (item.flags.splitter == false && item.sub_menu == nullptr)
|
||||
item.flags.checked = !item.flags.checked;
|
||||
}
|
||||
else if (checks::option == item.style)
|
||||
{
|
||||
//Forward Looks for a splitter
|
||||
auto pos = active;
|
||||
while (pos)
|
||||
{
|
||||
//There is a situation that menu will not call functor if the item style is check_option
|
||||
//and it is checked before clicking.
|
||||
bool call_functor = true;
|
||||
|
||||
if (checks::highlight == item.style)
|
||||
{
|
||||
item.flags.checked = !item.flags.checked;
|
||||
}
|
||||
else if (checks::option == item.style)
|
||||
{
|
||||
if (active > 0)
|
||||
{
|
||||
//clear the checked state in front of active if it is check_option.
|
||||
auto i = active;
|
||||
do
|
||||
{
|
||||
--i;
|
||||
menu_item_type & im = menu->items.at(i);
|
||||
if (im.flags.splitter) break;
|
||||
|
||||
if (checks::option == im.style && im.flags.checked)
|
||||
im.flags.checked = false;
|
||||
} while (i);
|
||||
}
|
||||
|
||||
for (auto i = active + 1; i < menu->items.size(); ++i)
|
||||
{
|
||||
menu_item_type & im = menu->items.at(i);
|
||||
if (im.flags.splitter) break;
|
||||
|
||||
if ((checks::option == im.style) && im.flags.checked)
|
||||
im.flags.checked = false;
|
||||
}
|
||||
|
||||
item.flags.checked = true;
|
||||
}
|
||||
|
||||
this->_m_close_all(); //means deleting this;
|
||||
//The deleting operation has moved here, because item.functor.operator()(ip)
|
||||
//may create a window, which make a killing focus for menu window, if so the close_all
|
||||
//operation preformences after item.functor.operator()(ip), that would be deleting this object twice!
|
||||
|
||||
if (call_functor && item.flags.enabled && item.functor)
|
||||
{
|
||||
item_type::item_proxy ip(active, item);
|
||||
item.functor.operator()(ip);
|
||||
}
|
||||
if (menu->items.at(--pos).flags.splitter)
|
||||
break;
|
||||
}
|
||||
|
||||
for (; pos < menu->items.size(); ++pos)
|
||||
{
|
||||
menu_item_type & im = menu->items.at(pos);
|
||||
if (im.flags.splitter) break;
|
||||
|
||||
if ((checks::option == im.style) && im.flags.checked)
|
||||
im.flags.checked = false;
|
||||
}
|
||||
|
||||
item.flags.checked = true;
|
||||
}
|
||||
|
||||
this->_m_close_all(); //means deleting this;
|
||||
//The deleting operation has moved here, because item.functor.operator()(ip)
|
||||
//may create a window, which make a killing focus for menu window, if so the close_all
|
||||
//operation preformences after item.functor.operator()(ip), that would be deleting this object twice!
|
||||
|
||||
if (call_functor && item.flags.enabled && item.functor)
|
||||
{
|
||||
item_type::item_proxy ip(active, item);
|
||||
item.functor.operator()(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -943,50 +939,29 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
//when the focus of the menu window is losing, close the menu.
|
||||
//But here is not every menu window may have focus event installed,
|
||||
//It is only installed when the owner of window is the desktop window.
|
||||
void _m_focus_changed(const arg_focus& arg)
|
||||
{
|
||||
if (false == arg.getting)
|
||||
{
|
||||
for (auto child = submenu_.child; child; child = child->submenu_.child)
|
||||
{
|
||||
if (API::root(child->handle()) == arg.receiver)
|
||||
return;
|
||||
}
|
||||
|
||||
_m_close_all();
|
||||
}
|
||||
}
|
||||
|
||||
void _m_key_down(const arg_keyboard& arg)
|
||||
{
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_up:
|
||||
this->goto_next(false);
|
||||
break;
|
||||
case keyboard::os_arrow_down:
|
||||
this->goto_next(true);
|
||||
this->goto_next(keyboard::os_arrow_down == arg.key);
|
||||
break;
|
||||
case keyboard::os_arrow_left:
|
||||
this->exit_submenu();
|
||||
break;
|
||||
case keyboard::os_arrow_right:
|
||||
this->goto_submenu();
|
||||
this->submenu(keyboard::os_arrow_right == arg.key);
|
||||
break;
|
||||
case keyboard::enter:
|
||||
this->pick();
|
||||
break;
|
||||
default:
|
||||
if(2 != send_shortkey(arg.key))
|
||||
if (2 != send_shortkey(arg.key))
|
||||
{
|
||||
if(API::empty_window(*this) == false)
|
||||
if (API::empty_window(*this) == false)
|
||||
close();
|
||||
}
|
||||
else
|
||||
goto_submenu();
|
||||
this->submenu(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1165,7 +1140,7 @@ namespace nana
|
||||
{
|
||||
if(impl_->mbuilder.set_sub_menu(index, menu_obj.impl_->mbuilder.data()))
|
||||
{
|
||||
implement::info& minfo = impl_->sub_container[index];
|
||||
auto& minfo = impl_->sub_container[index];
|
||||
minfo.handle = &menu_obj;
|
||||
minfo.kill = false;
|
||||
return true;
|
||||
@ -1184,9 +1159,10 @@ namespace nana
|
||||
menu *menu::create_sub_menu(std::size_t index)
|
||||
{
|
||||
menu * sub = new menu;
|
||||
if(link(index, *sub))
|
||||
|
||||
if (this->link(index, *sub))
|
||||
{
|
||||
implement::info& minfo = impl_->sub_container[index];
|
||||
auto& minfo = impl_->sub_container[index];
|
||||
minfo.handle = sub;
|
||||
minfo.kill = true;
|
||||
return sub;
|
||||
@ -1255,12 +1231,12 @@ namespace nana
|
||||
|
||||
bool menu::goto_submen()
|
||||
{
|
||||
return (impl_->uiobj ? impl_->uiobj->goto_submenu() : false);
|
||||
return (impl_->uiobj ? impl_->uiobj->submenu(true) : false);
|
||||
}
|
||||
|
||||
bool menu::exit_submenu()
|
||||
{
|
||||
return (impl_->uiobj ? impl_->uiobj->exit_submenu() : false);
|
||||
return (impl_->uiobj ? impl_->uiobj->submenu(false) : false);
|
||||
}
|
||||
|
||||
std::size_t menu::size() const
|
||||
@ -1311,21 +1287,17 @@ namespace nana
|
||||
impl_->mbuilder.renderer(rd);
|
||||
}
|
||||
|
||||
void menu::_m_destroy_menu_window()
|
||||
{
|
||||
impl_->uiobj = nullptr;
|
||||
if(impl_->destroy_answer)
|
||||
impl_->destroy_answer();
|
||||
}
|
||||
|
||||
void menu::_m_popup(window wd, int x, int y, bool called_by_menubar)
|
||||
{
|
||||
if (impl_->mbuilder.data().items.size())
|
||||
{
|
||||
close();
|
||||
|
||||
impl_->uiobj = &(form_loader<drawerbase::menu::menu_window, false>()(wd, point(x, y), &(*impl_->mbuilder.renderer())));
|
||||
impl_->uiobj->events().destroy.connect_unignorable([this]{
|
||||
_m_destroy_menu_window();
|
||||
impl_->uiobj = nullptr;
|
||||
if (impl_->destroy_answer)
|
||||
impl_->destroy_answer();
|
||||
});
|
||||
impl_->uiobj->popup(impl_->mbuilder.data(), called_by_menubar);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Menubar implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -30,21 +30,21 @@ namespace nana
|
||||
{
|
||||
struct item_type
|
||||
{
|
||||
item_type(const nana::string& text, unsigned long shortkey)
|
||||
item_type(const ::nana::string& text, unsigned long shortkey)
|
||||
: text(text), shortkey(shortkey)
|
||||
{}
|
||||
|
||||
nana::string text;
|
||||
::nana::string text;
|
||||
unsigned long shortkey;
|
||||
nana::menu menu_obj;
|
||||
nana::point pos;
|
||||
nana::size size;
|
||||
::nana::menu menu_obj;
|
||||
::nana::point pos;
|
||||
::nana::size size;
|
||||
};
|
||||
|
||||
class trigger::itembase
|
||||
{
|
||||
public:
|
||||
typedef std::vector<item_type*> container;
|
||||
using container = std::vector<item_type*>;
|
||||
|
||||
~itembase()
|
||||
{
|
||||
@ -52,22 +52,12 @@ namespace nana
|
||||
delete i;
|
||||
}
|
||||
|
||||
void append(const nana::string& text, unsigned long shortkey)
|
||||
void append(const ::nana::string& text, unsigned long shortkey)
|
||||
{
|
||||
if(shortkey && shortkey < 0x61) shortkey += (0x61 - 0x41);
|
||||
cont_.push_back(new item_type(text, shortkey));
|
||||
}
|
||||
|
||||
nana::menu* get_menu(std::size_t index) const
|
||||
{
|
||||
return (index < cont_.size() ? &(cont_[index]->menu_obj) : nullptr);
|
||||
}
|
||||
|
||||
const item_type& at(std::size_t index) const
|
||||
{
|
||||
return *cont_.at(index);
|
||||
}
|
||||
|
||||
std::size_t find(unsigned long shortkey) const
|
||||
{
|
||||
if(shortkey)
|
||||
@ -98,19 +88,19 @@ namespace nana
|
||||
:handle_(wd), graph_(graph)
|
||||
{}
|
||||
|
||||
void item_renderer::background(const nana::point& pos, const nana::size& size, state_t state)
|
||||
void item_renderer::background(const nana::point& pos, const nana::size& size, state item_state)
|
||||
{
|
||||
auto bground = API::fgcolor(handle_);
|
||||
::nana::color border, body, corner;
|
||||
|
||||
switch(state)
|
||||
switch (item_state)
|
||||
{
|
||||
case item_renderer::state_highlight:
|
||||
case state::highlighted:
|
||||
border = colors::highlight;
|
||||
body.from_rgb(0xC0, 0xDD, 0xFC);
|
||||
corner = body.blend(bground, 0.5);
|
||||
break;
|
||||
case item_renderer::state_selected:
|
||||
case state::selected:
|
||||
border = colors::dark_border;
|
||||
body = colors::white;
|
||||
corner = body.blend(bground, 0.5);
|
||||
@ -122,17 +112,19 @@ namespace nana
|
||||
nana::rectangle r(pos, size);
|
||||
graph_.rectangle(r, false, border);
|
||||
|
||||
int right = pos.x + static_cast<int>(size.width) - 1;
|
||||
int bottom = pos.y + static_cast<int>(size.height) - 1;
|
||||
graph_.set_color(corner);
|
||||
graph_.set_pixel(pos.x, pos.y);
|
||||
graph_.set_pixel(pos.x + size.width - 1, pos.y);
|
||||
graph_.set_pixel(pos.x, pos.y + size.height - 1);
|
||||
graph_.set_pixel(pos.x + size.width - 1, pos.y + size.height - 1);
|
||||
graph_.set_pixel(right, pos.y);
|
||||
graph_.set_pixel(pos.x, bottom);
|
||||
graph_.set_pixel(right, bottom);
|
||||
graph_.rectangle(r.pare_off(1), true, body);
|
||||
}
|
||||
|
||||
void item_renderer::caption(int x, int y, const nana::string& text)
|
||||
void item_renderer::caption(const point& pos, const nana::string& text)
|
||||
{
|
||||
graph_.string({ x, y }, text, colors::black);
|
||||
graph_.string(pos, text, colors::black);
|
||||
}
|
||||
//end class item_renderer
|
||||
|
||||
@ -146,23 +138,28 @@ namespace nana
|
||||
delete items_;
|
||||
}
|
||||
|
||||
nana::menu* trigger::push_back(const nana::string& text)
|
||||
nana::menu* trigger::push_back(const ::nana::string& text)
|
||||
{
|
||||
nana::string::value_type shkey;
|
||||
::nana::char_t shkey;
|
||||
API::transform_shortkey_text(text, shkey, nullptr);
|
||||
|
||||
if(shkey)
|
||||
API::register_shortkey(widget_->handle(), shkey);
|
||||
|
||||
auto i = items_->cont().size();
|
||||
auto pos = items_->cont().size();
|
||||
items_->append(text, shkey);
|
||||
_m_draw();
|
||||
return items_->get_menu(i);
|
||||
API::update_window(*widget_);
|
||||
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
nana::menu* trigger::at(std::size_t index) const
|
||||
nana::menu* trigger::at(std::size_t pos) const
|
||||
{
|
||||
return items_->get_menu(index);
|
||||
if (pos < items_->cont().size())
|
||||
return &(items_->cont()[pos]->menu_obj);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::size_t trigger::size() const
|
||||
@ -219,22 +216,17 @@ namespace nana
|
||||
void trigger::mouse_down(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
state_.nullify_mouse = false;
|
||||
|
||||
state_.active = _m_item_by_pos(arg.pos);
|
||||
if(state_.menu_active == false)
|
||||
|
||||
if (npos != state_.active)
|
||||
{
|
||||
if(state_.active != npos)
|
||||
{
|
||||
if (!state_.menu_active)
|
||||
state_.menu_active = true;
|
||||
_m_popup_menu();
|
||||
}
|
||||
else
|
||||
_m_total_close();
|
||||
}
|
||||
else if(npos == state_.active)
|
||||
_m_total_close();
|
||||
else
|
||||
|
||||
_m_popup_menu();
|
||||
}
|
||||
else
|
||||
_m_total_close();
|
||||
|
||||
_m_draw();
|
||||
API::lazy_refresh();
|
||||
@ -256,7 +248,6 @@ namespace nana
|
||||
_m_draw();
|
||||
API::lazy_refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void trigger::focus(graph_reference, const arg_focus& arg)
|
||||
@ -281,10 +272,10 @@ namespace nana
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_down:
|
||||
state_.menu->goto_next(true); break;
|
||||
case keyboard::backspace:
|
||||
case keyboard::os_arrow_up:
|
||||
state_.menu->goto_next(false); break;
|
||||
state_.menu->goto_next(keyboard::os_arrow_down == arg.key);
|
||||
break;
|
||||
case keyboard::os_arrow_right:
|
||||
if(state_.menu->goto_submen() == false)
|
||||
_m_move(false);
|
||||
@ -305,17 +296,26 @@ namespace nana
|
||||
state_.menu->pick();
|
||||
break;
|
||||
default:
|
||||
if(2 != state_.menu->send_shortkey(arg.key))
|
||||
//Katsuhisa Yuasa: menubar key_press improvements
|
||||
//send_shortkey has 3 states, 0 = UNKNOWN KEY, 1 = ITEM, 2 = GOTO SUBMENU
|
||||
int sk_state = state_.menu->send_shortkey(arg.key);
|
||||
switch(sk_state)
|
||||
{
|
||||
if(state_.active != npos)
|
||||
case 0: //UNKNOWN KEY
|
||||
break;
|
||||
case 1: //ITEM
|
||||
if (state_.active != npos)
|
||||
{
|
||||
_m_total_close();
|
||||
if(arg.key == 18) //ALT
|
||||
if (arg.key == 18) //ALT
|
||||
state_.behavior = state_.behavior_focus;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2: //GOTO SUBMENU
|
||||
state_.menu->goto_submen();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -323,19 +323,34 @@ namespace nana
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_right:
|
||||
_m_move(false);
|
||||
break;
|
||||
case keyboard::backspace:
|
||||
case keyboard::os_arrow_left:
|
||||
_m_move(true);
|
||||
_m_move(keyboard::os_arrow_right != arg.key);
|
||||
break;
|
||||
case keyboard::os_arrow_up:
|
||||
case keyboard::os_arrow_down:
|
||||
case keyboard::enter:
|
||||
state_.menu_active = true;
|
||||
if(_m_popup_menu())
|
||||
state_.menu->goto_next(true);
|
||||
break;
|
||||
case keyboard::escape:
|
||||
if(state_.behavior == state_.behavior_focus)
|
||||
{
|
||||
state_.active= npos;
|
||||
state_.behavior = state_.behavior_none;
|
||||
API::restore_menubar_taken_window();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::size_t index = items_->find(arg.key);
|
||||
if(index != npos)
|
||||
{
|
||||
state_.active = index;
|
||||
state_.menu_active = true;
|
||||
if(_m_popup_menu())
|
||||
state_.menu->goto_next(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,20 +434,37 @@ namespace nana
|
||||
|
||||
bool trigger::_m_popup_menu()
|
||||
{
|
||||
if(state_.menu_active && (state_.menu != items_->get_menu(state_.active)))
|
||||
{
|
||||
std::size_t index = state_.active;
|
||||
_m_close_menu();
|
||||
state_.active = index;
|
||||
auto& items = items_->cont();
|
||||
|
||||
state_.menu = items_->get_menu(state_.active);
|
||||
if(state_.menu)
|
||||
auto pos = state_.active;
|
||||
if (pos >= items.size())
|
||||
return false;
|
||||
|
||||
if(state_.menu_active && (state_.menu != &(items[pos]->menu_obj)))
|
||||
{
|
||||
API::dev::delay_restore(true);
|
||||
_m_close_menu();
|
||||
API::dev::delay_restore(false);
|
||||
state_.active = pos;
|
||||
|
||||
auto & m = items[pos];
|
||||
state_.menu = &(m->menu_obj);
|
||||
state_.menu->destroy_answer([this]
|
||||
{
|
||||
const item_type &m = items_->at(state_.active);
|
||||
state_.menu->destroy_answer(std::bind(&trigger::_m_unload_menu_window, this));
|
||||
menu_accessor::popup(*state_.menu, widget_->handle(), m.pos.x, m.pos.y + m.size.height);
|
||||
return true;
|
||||
}
|
||||
state_.menu = nullptr;
|
||||
if (state_.passive_close)
|
||||
{
|
||||
_m_total_close();
|
||||
|
||||
_m_draw();
|
||||
API::update_window(widget_->handle());
|
||||
}
|
||||
});
|
||||
|
||||
if (API::focus_window() != this->widget_->handle())
|
||||
API::focus_window(widget_->handle());
|
||||
menu_accessor::popup(*state_.menu, *widget_, m->pos.x, m->pos.y + static_cast<int>(m->size.height));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -443,8 +475,6 @@ namespace nana
|
||||
state_.menu_active = false;
|
||||
state_.behavior = state_.behavior_none;
|
||||
|
||||
API::restore_menubar_taken_window();
|
||||
|
||||
auto pos = API::cursor_position();
|
||||
API::calc_window_point(widget_->handle(), pos);
|
||||
state_.active = _m_item_by_pos(pos);
|
||||
@ -463,17 +493,6 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
|
||||
void trigger::_m_unload_menu_window()
|
||||
{
|
||||
state_.menu = nullptr;
|
||||
if(state_.passive_close)
|
||||
{
|
||||
_m_total_close();
|
||||
_m_draw();
|
||||
API::update_window(widget_->handle());
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t trigger::_m_item_by_pos(const ::nana::point& pos)
|
||||
{
|
||||
if((2 <= pos.x) && (2 <= pos.y) && (pos.y < 25))
|
||||
@ -521,9 +540,9 @@ namespace nana
|
||||
for(auto i : items_->cont())
|
||||
{
|
||||
//Transform the text if it contains the hotkey character
|
||||
nana::string::value_type hotkey;
|
||||
nana::string::size_type hotkey_pos;
|
||||
nana::string text = API::transform_shortkey_text(i->text, hotkey, &hotkey_pos);
|
||||
::nana::char_t hotkey;
|
||||
::nana::string::size_type hotkey_pos;
|
||||
auto text = API::transform_shortkey_text(i->text, hotkey, &hotkey_pos);
|
||||
|
||||
nana::size text_s = graph_->text_extent_size(text);
|
||||
|
||||
@ -532,10 +551,11 @@ namespace nana
|
||||
i->pos = item_pos;
|
||||
i->size = item_s;
|
||||
|
||||
item_renderer::state_t state = (index != state_.active ? ird.state_normal : (state_.menu_active ? ird.state_selected : ird.state_highlight));
|
||||
ird.background(item_pos, item_s, state);
|
||||
using state = item_renderer::state;
|
||||
state item_state = (index != state_.active ? state::normal : (state_.menu_active ? state::selected : state::highlighted));
|
||||
ird.background(item_pos, item_s, item_state);
|
||||
|
||||
if(state == ird.state_selected)
|
||||
if (state::selected == item_state)
|
||||
{
|
||||
int x = item_pos.x + item_s.width;
|
||||
int y1 = item_pos.y + 2, y2 = item_pos.y + item_s.height - 1;
|
||||
@ -545,7 +565,7 @@ namespace nana
|
||||
|
||||
//Draw text, the text is transformed from orignal for hotkey character
|
||||
int text_top_off = (item_s.height - text_s.height) / 2;
|
||||
ird.caption(item_pos.x + 8, item_pos.y + text_top_off, text);
|
||||
ird.caption({ item_pos.x + 8, item_pos.y + text_top_off }, text);
|
||||
|
||||
if(hotkey)
|
||||
{
|
||||
@ -566,7 +586,12 @@ namespace nana
|
||||
|
||||
//struct state_type
|
||||
trigger::state_type::state_type()
|
||||
:active(npos), behavior(behavior_none), menu_active(false), passive_close(true), nullify_mouse(false), menu(nullptr)
|
||||
: active(npos),
|
||||
behavior(behavior_none),
|
||||
menu_active(false),
|
||||
passive_close(true),
|
||||
nullify_mouse(false),
|
||||
menu(nullptr)
|
||||
{}
|
||||
//end struct state_type
|
||||
//end class trigger
|
||||
|
||||
@ -109,8 +109,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
if (fit_size.width < graphsize.width || fit_size.height < graphsize.height)
|
||||
_m_draw_background();
|
||||
_m_draw_background(fit_size.width, fit_size.height);
|
||||
|
||||
backimg.image.stretch(valid_area, graph, { pos, fit_size });
|
||||
}
|
||||
@ -141,14 +140,15 @@ namespace nana
|
||||
break;
|
||||
}
|
||||
|
||||
if (valid_area.width < graphsize.width || valid_area.height < graphsize.height)
|
||||
_m_draw_background();
|
||||
_m_draw_background(valid_area.width, valid_area.height);
|
||||
|
||||
backimg.image.paste(valid_area, graph, pos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_m_draw_background(graphsize.width, graphsize.height);
|
||||
|
||||
color invalid_clr_for_call;
|
||||
backimg.bground->draw(graph, invalid_clr_for_call, invalid_clr_for_call, graphsize, element_state::normal);
|
||||
}
|
||||
@ -156,18 +156,22 @@ namespace nana
|
||||
graph.setsta();
|
||||
}
|
||||
|
||||
void drawer::_m_draw_background()
|
||||
void drawer::_m_draw_background(unsigned w, unsigned h)
|
||||
{
|
||||
auto graph = impl_->graph_ptr;
|
||||
|
||||
if (graph && (bground_mode::basic != API::effects_bground_mode(*impl_->wdg_ptr)))
|
||||
{
|
||||
auto & bground = impl_->gradual_bground;
|
||||
if (bground.gradual_from.invisible() || bground.gradual_to.invisible())
|
||||
graph->rectangle(true, impl_->wdg_ptr->bgcolor());
|
||||
else if (bground.gradual_from == bground.gradual_to)
|
||||
graph->rectangle(true, bground.gradual_from);
|
||||
else
|
||||
graph->gradual_rectangle(graph->size(), bground.gradual_from, bground.gradual_to, !bground.horizontal);
|
||||
if (w < graph->size().width || h < graph->size().width || impl_->backimg.image.alpha())
|
||||
{
|
||||
auto & bground = impl_->gradual_bground;
|
||||
if (bground.gradual_from.invisible() || bground.gradual_to.invisible())
|
||||
graph->rectangle(true, impl_->wdg_ptr->bgcolor());
|
||||
else if (bground.gradual_from == bground.gradual_to)
|
||||
graph->rectangle(true, bground.gradual_from);
|
||||
else
|
||||
graph->gradual_rectangle(graph->size(), bground.gradual_from, bground.gradual_to, !bground.horizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
//end class drawer
|
||||
|
||||
@ -52,20 +52,11 @@ namespace nana
|
||||
pos = screen_pos.x;
|
||||
}
|
||||
|
||||
if(scale >= fixedsize * 2)
|
||||
{
|
||||
if(pos < static_cast<int>(fixedsize))
|
||||
return buttons::first;
|
||||
if(pos > static_cast<int>(scale - fixedsize))
|
||||
return buttons::second;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pos < static_cast<int>(scale / 2))
|
||||
return buttons::first;
|
||||
if(pos > static_cast<int>(scale / 2))
|
||||
return buttons::second;
|
||||
}
|
||||
const auto bound_pos = static_cast<int>(scale >= fixedsize * 2 ? fixedsize : scale / 2);
|
||||
if (pos < bound_pos)
|
||||
return buttons::first;
|
||||
if (pos > static_cast<int>(scale) - bound_pos)
|
||||
return buttons::second;
|
||||
|
||||
if(metrics_.scroll_length)
|
||||
{
|
||||
@ -100,7 +91,7 @@ namespace nana
|
||||
metrics_.scroll_pos = pos;
|
||||
auto value_max = metrics_.peak - metrics_.range;
|
||||
metrics_.value = pos * value_max / scroll_area;
|
||||
if(metrics_.value < metrics_.peak - metrics_.range)
|
||||
if(metrics_.value < value_max)
|
||||
{
|
||||
int selfpos = static_cast<int>(metrics_.value * scroll_area / value_max);
|
||||
int nextpos = static_cast<int>((metrics_.value + 1) * scroll_area / value_max);
|
||||
@ -115,22 +106,22 @@ namespace nana
|
||||
|
||||
void drawer::auto_scroll()
|
||||
{
|
||||
if(_m_check())
|
||||
if (!_m_check())
|
||||
return;
|
||||
|
||||
if(buttons::forward == metrics_.what)
|
||||
{ //backward
|
||||
if(metrics_.value <= metrics_.range)
|
||||
metrics_.value = 0;
|
||||
else
|
||||
metrics_.value -= (metrics_.range-1);
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
if(buttons::forward == metrics_.what)
|
||||
{ //backward
|
||||
if(metrics_.value <= metrics_.range)
|
||||
metrics_.value = 0;
|
||||
else
|
||||
metrics_.value -= metrics_.range;
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
if(metrics_.peak - metrics_.range - metrics_.value <= metrics_.range)
|
||||
metrics_.value = metrics_.peak - metrics_.range;
|
||||
else
|
||||
metrics_.value += metrics_.range;
|
||||
}
|
||||
if(metrics_.peak - metrics_.range - metrics_.value <= metrics_.range)
|
||||
metrics_.value = metrics_.peak - metrics_.range;
|
||||
else
|
||||
metrics_.value += (metrics_.range-1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,26 +132,20 @@ namespace nana
|
||||
|
||||
_m_background(graph);
|
||||
|
||||
::nana::rectangle r(graph.size());
|
||||
if(vertical_)
|
||||
{
|
||||
r.y = r.height - fixedsize;
|
||||
r.height = fixedsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.x = r.width - fixedsize;
|
||||
r.width = fixedsize;
|
||||
}
|
||||
rectangle_rotator r(vertical_, graph.size());
|
||||
r.x_ref() = static_cast<int>(r.w() - fixedsize);
|
||||
r.w_ref() = fixedsize;
|
||||
|
||||
int state = ((_m_check() == false || what == buttons::none) ? states::none : states::highlight);
|
||||
int moused_state = (_m_check() ? (metrics_.pressed ? states::selected : states::actived) : states::none);
|
||||
|
||||
auto result = r.result();
|
||||
|
||||
//draw first
|
||||
_m_draw_button(graph, { 0, 0, r.width, r.height }, buttons::first, (buttons::first == what ? moused_state : state));
|
||||
_m_draw_button(graph, { 0, 0, result.width, result.height }, buttons::first, (buttons::first == what ? moused_state : state));
|
||||
|
||||
//draw second
|
||||
_m_draw_button(graph, r, buttons::second, (buttons::second == what ? moused_state : state));
|
||||
_m_draw_button(graph, result, buttons::second, (buttons::second == what ? moused_state : state));
|
||||
|
||||
//draw scroll
|
||||
_m_draw_scroll(graph, (buttons::scroll == what ? moused_state : states::highlight));
|
||||
@ -171,64 +156,61 @@ namespace nana
|
||||
{
|
||||
graph.rectangle(true, {0xf0, 0xf0, 0xf0});
|
||||
|
||||
if(metrics_.pressed && _m_check())
|
||||
if (!metrics_.pressed || !_m_check())
|
||||
return;
|
||||
|
||||
nana::rectangle_rotator r(vertical_, graph.size());
|
||||
if(metrics_.what == buttons::forward)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
unsigned width = graph.width(), height = graph.height();
|
||||
|
||||
if(metrics_.what == buttons::forward)
|
||||
{
|
||||
*(vertical_ ? &y : &x) = fixedsize;
|
||||
*(vertical_ ? &height: &width) = metrics_.scroll_pos;
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
*(vertical_ ? &y : &x) = static_cast<int>(fixedsize + metrics_.scroll_pos + metrics_.scroll_length);
|
||||
*(vertical_ ? &height: &width) = static_cast<unsigned>((vertical_ ? graph.height() : graph.width()) - (fixedsize * 2 + metrics_.scroll_pos + metrics_.scroll_length));
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
if(width && height)
|
||||
graph.rectangle({ x, y, width, height }, true, {0xDC, 0xDC, 0xDC});
|
||||
r.x_ref() = static_cast<int>(fixedsize);
|
||||
r.w_ref() = metrics_.scroll_pos;
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
r.x_ref() = static_cast<int>(fixedsize + metrics_.scroll_pos + metrics_.scroll_length);
|
||||
r.w_ref() = static_cast<unsigned>((vertical_ ? graph.height() : graph.width()) - (fixedsize * 2 + metrics_.scroll_pos + metrics_.scroll_length));
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
auto result = r.result();
|
||||
if (!result.empty())
|
||||
graph.rectangle(result, true, static_cast<color_rgb>(0xDCDCDC));
|
||||
}
|
||||
|
||||
void drawer::_m_button_frame(graph_reference graph, rectangle r, int state)
|
||||
{
|
||||
if(state)
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
::nana::color clr{0x97, 0x97, 0x97}; //highlight
|
||||
switch(state)
|
||||
{
|
||||
::nana::color clr{0x97, 0x97, 0x97}; //highlight
|
||||
switch(state)
|
||||
{
|
||||
case states::actived:
|
||||
clr.from_rgb(0x86, 0xD5, 0xFD); break;
|
||||
case states::selected:
|
||||
clr.from_rgb(0x3C, 0x7F, 0xB1); break;
|
||||
}
|
||||
|
||||
graph.rectangle(r, false, clr);
|
||||
|
||||
clr = clr.blend(colors::white, 0.5);
|
||||
graph.set_color(clr);
|
||||
|
||||
r.pare_off(2);
|
||||
|
||||
if(vertical_)
|
||||
{
|
||||
unsigned half = r.width / 2;
|
||||
graph.rectangle({ r.x + static_cast<int>(r.width - half), r.y, half, r.height }, true);
|
||||
r.width -= half;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned half = r.height / 2;
|
||||
graph.rectangle({r.x, r.y + static_cast<int>(r.height - half), r.width, half}, true);
|
||||
r.height -= half;
|
||||
}
|
||||
//graph.shadow_rectangle(x, y, width, height, 0xFFFFFF, color_x, !vertical_);
|
||||
graph.gradual_rectangle(r, colors::white, clr, !vertical_);
|
||||
case states::actived:
|
||||
clr.from_rgb(0x86, 0xD5, 0xFD); break;
|
||||
case states::selected:
|
||||
clr.from_rgb(0x3C, 0x7F, 0xB1); break;
|
||||
}
|
||||
|
||||
graph.rectangle(r, false, clr);
|
||||
|
||||
clr = clr.blend(colors::white, 0.5);
|
||||
graph.set_color(clr);
|
||||
|
||||
r.pare_off(2);
|
||||
if(vertical_)
|
||||
{
|
||||
unsigned half = r.width / 2;
|
||||
graph.rectangle({ r.x + static_cast<int>(r.width - half), r.y, half, r.height }, true);
|
||||
r.width -= half;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned half = r.height / 2;
|
||||
graph.rectangle({r.x, r.y + static_cast<int>(r.height - half), r.width, half}, true);
|
||||
r.height -= half;
|
||||
}
|
||||
graph.gradual_rectangle(r, colors::white, clr, !vertical_);
|
||||
}
|
||||
|
||||
bool drawer::_m_check() const
|
||||
@ -271,20 +253,11 @@ namespace nana
|
||||
{
|
||||
if(_m_check())
|
||||
{
|
||||
::nana::rectangle r(graph.size());
|
||||
rectangle_rotator r(vertical_, graph.size());
|
||||
r.x_ref() = static_cast<int>(fixedsize + metrics_.scroll_pos);
|
||||
r.w_ref() = static_cast<unsigned>(metrics_.scroll_length);
|
||||
|
||||
if(vertical_)
|
||||
{
|
||||
r.y = fixedsize + metrics_.scroll_pos;
|
||||
r.height = static_cast<unsigned>(metrics_.scroll_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.x = fixedsize + metrics_.scroll_pos;
|
||||
r.width = static_cast<unsigned>(metrics_.scroll_length);
|
||||
}
|
||||
|
||||
_m_button_frame(graph, r, state);
|
||||
_m_button_frame(graph, r.result(), state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
/*
|
||||
* A text editor implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 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.cpp
|
||||
* @description:
|
||||
*/
|
||||
* A text editor implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 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.cpp
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/widgets/skeletons/textbase_export_interface.hpp>
|
||||
#include <nana/gui/element.hpp>
|
||||
@ -18,6 +18,7 @@
|
||||
#include <numeric>
|
||||
#include <cwctype>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana{ namespace widgets
|
||||
{
|
||||
@ -314,7 +315,13 @@ namespace nana{ namespace widgets
|
||||
if (pos.y > static_cast<unsigned>(textbase.lines()))
|
||||
pos.y = static_cast<unsigned>(textbase.lines());
|
||||
|
||||
pos.x = editor_._m_pixels_by_char(textbase.getline(pos.y), pos.x) + editor_.text_area_.area.x;
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (editor_.mask_char_)
|
||||
mask_str.reset(new nana::string(textbase.getline(pos.y).size(), editor_.mask_char_));
|
||||
|
||||
auto & lnstr = editor_.mask_char_ ? *mask_str : textbase.getline(pos.y);
|
||||
|
||||
pos.x = editor_._m_pixels_by_char(lnstr, pos.x) + editor_.text_area_.area.x;
|
||||
|
||||
int pos_y = static_cast<int>((pos.y - editor_.points_.offset.y) * editor_.line_height() + editor_._m_text_top_base());
|
||||
int pos_x = static_cast<int>(pos.x - editor_.points_.offset.x);
|
||||
@ -327,7 +334,13 @@ namespace nana{ namespace widgets
|
||||
nana::upoint res{ 0, static_cast<unsigned>(_m_textline_from_screen(scrpos.y)) };
|
||||
|
||||
//Convert the screen point to text caret point
|
||||
const string_type& lnstr = editor_.textbase_.getline(res.y);
|
||||
const string_type& real_str = editor_.textbase_.getline(res.y);
|
||||
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (editor_.mask_char_)
|
||||
mask_str.reset(new nana::string(real_str.size(), editor_.mask_char_));
|
||||
|
||||
auto & lnstr = (editor_.mask_char_ ? *mask_str : real_str);
|
||||
if (lnstr.size() > 0)
|
||||
{
|
||||
scrpos.x += (editor_.points_.offset.x - editor_.text_area_.area.x);
|
||||
@ -676,7 +689,7 @@ namespace nana{ namespace widgets
|
||||
}
|
||||
}
|
||||
else
|
||||
editor_.render(API::is_focus_window(editor_.window_));
|
||||
editor_.render(API::is_focus_ready(editor_.window_));
|
||||
}
|
||||
|
||||
void render(const ::nana::color& fgcolor) override
|
||||
@ -737,17 +750,24 @@ namespace nana{ namespace widgets
|
||||
nana::point scrpos;
|
||||
if (0 != pos.x)
|
||||
{
|
||||
nana::string str;
|
||||
for (auto & sec : mtr.line_sections)
|
||||
{
|
||||
std::size_t chsize = sec.end - sec.begin;
|
||||
str.clear();
|
||||
if (editor_.mask_char_)
|
||||
str.append(chsize, editor_.mask_char_);
|
||||
else
|
||||
str.append(sec.begin, sec.end);
|
||||
|
||||
if (pos.x < chsize)
|
||||
{
|
||||
scrpos.x = editor_._m_pixels_by_char(nana::string(sec.begin, sec.end), pos.x);
|
||||
scrpos.x = editor_._m_pixels_by_char(str, pos.x);
|
||||
break;
|
||||
}
|
||||
else if (pos.x == chsize)
|
||||
{
|
||||
scrpos.x = editor_._m_text_extent_size(nana::string(sec.begin, sec.end).data(), sec.end - sec.begin).width;
|
||||
scrpos.x = editor_._m_text_extent_size(str.data(), sec.end - sec.begin).width;
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -773,13 +793,19 @@ namespace nana{ namespace widgets
|
||||
return{ 0, static_cast<unsigned>(primary) };
|
||||
|
||||
//First of all, find the text of secondary.
|
||||
auto str = mtr.line_sections[secondary];
|
||||
auto real_str = mtr.line_sections[secondary];
|
||||
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (editor_.mask_char_)
|
||||
mask_str.reset(new nana::string(real_str.end - real_str.begin, editor_.mask_char_));
|
||||
|
||||
const ::nana::char_t * str = (editor_.mask_char_ ? mask_str->data() : real_str.begin);
|
||||
|
||||
std::vector<unicode_bidi::entity> reordered;
|
||||
unicode_bidi bidi;
|
||||
bidi.linestr(str.begin, str.end - str.begin, reordered);
|
||||
bidi.linestr(str, real_str.end - real_str.begin, reordered);
|
||||
|
||||
nana::upoint res(static_cast<unsigned>(str.begin - mtr.line_sections.front().begin), static_cast<unsigned>(primary));
|
||||
nana::upoint res(static_cast<unsigned>(real_str.begin - mtr.line_sections.front().begin), static_cast<unsigned>(primary));
|
||||
scrpos.x -= editor_.text_area_.area.x;
|
||||
if (scrpos.x < 0)
|
||||
scrpos.x = 0;
|
||||
@ -793,7 +819,7 @@ namespace nana{ namespace widgets
|
||||
std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
|
||||
|
||||
res.x += editor_._m_char_by_pixels(ent.begin, len, pxbuf.get(), str_px, scrpos.x, _m_is_right_text(ent));
|
||||
res.x += static_cast<unsigned>(ent.begin - str.begin);
|
||||
res.x += static_cast<unsigned>(ent.begin - str);
|
||||
return res;
|
||||
}
|
||||
scrpos.x -= str_px;
|
||||
@ -1133,12 +1159,14 @@ namespace nana{ namespace widgets
|
||||
public:
|
||||
void parse(const ::nana::string& text, const keywords* kwptr)
|
||||
{
|
||||
if (text.empty())
|
||||
if ( kwptr->kwbase.empty() || text.empty() )
|
||||
return;
|
||||
|
||||
using index = ::nana::string::size_type;
|
||||
|
||||
std::vector<entity> entities;
|
||||
|
||||
auto test_whole_word = [&text](std::size_t pos, std::size_t len)
|
||||
auto test_whole_word = [&text](index pos, index len)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
@ -1160,53 +1188,48 @@ namespace nana{ namespace widgets
|
||||
::nana::cistring cistr;
|
||||
for (auto & ds : kwptr->kwbase)
|
||||
{
|
||||
std::size_t pos;
|
||||
const ::nana::char_t* begin;
|
||||
const ::nana::char_t* end;
|
||||
if (ds.case_sensitive)
|
||||
{
|
||||
pos = text.find(ds.text);
|
||||
if (pos == text.npos)
|
||||
continue;
|
||||
index pos{0} ;
|
||||
for (index rest{text.size()}; rest >= ds.text.size() ; ++pos, rest = text.size() - pos)
|
||||
{
|
||||
if (ds.case_sensitive)
|
||||
{
|
||||
pos = text.find(ds.text, pos);
|
||||
if (pos == text.npos)
|
||||
break;
|
||||
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cistr.empty())
|
||||
cistr.append(text.data(), text.size());
|
||||
|
||||
begin = text.data() + pos;
|
||||
end = begin + ds.text.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cistr.empty())
|
||||
cistr.append(text.data(), text.size());
|
||||
pos = cistr.find(ds.text.data(), pos);
|
||||
if (pos == cistr.npos)
|
||||
break;
|
||||
|
||||
pos = cistr.find(ds.text.data());
|
||||
if (pos == cistr.npos)
|
||||
continue;
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
|
||||
begin = text.data() + pos;
|
||||
end = begin + ds.text.size();
|
||||
}
|
||||
|
||||
auto ki = kwptr->schemes.find(ds.scheme);
|
||||
if (ki != kwptr->schemes.end() && ki->second)
|
||||
{
|
||||
schemes_.emplace(ds.scheme, ki->second);
|
||||
entities.emplace_back();
|
||||
auto & last = entities.back();
|
||||
last.begin = begin;
|
||||
last.end = end;
|
||||
last.scheme = ki->second.get();
|
||||
}
|
||||
auto ki = kwptr->schemes.find(ds.scheme);
|
||||
if (ki != kwptr->schemes.end() && ki->second)
|
||||
{
|
||||
schemes_.emplace(ds.scheme, ki->second);
|
||||
entities.emplace_back();
|
||||
auto & last = entities.back();
|
||||
last.begin = text.data() + pos;
|
||||
last.end = last.begin + ds.text.size();
|
||||
last.scheme = ki->second.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!entities.empty())
|
||||
@ -1221,7 +1244,7 @@ namespace nana{ namespace widgets
|
||||
while(i != entities.end())
|
||||
{
|
||||
if (previous->end > i->begin)
|
||||
i = entities.erase(i);
|
||||
i = entities.erase(i); // erase overlaping. Left only the first.
|
||||
else
|
||||
++i;
|
||||
}
|
||||
@ -1326,7 +1349,7 @@ namespace nana{ namespace widgets
|
||||
attributes_.acceptive = acceptive;
|
||||
}
|
||||
|
||||
bool text_editor::respone_keyboard(char_type key) //key is a character of ASCII code
|
||||
bool text_editor::respond_char(char_type key) //key is a character of ASCII code
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
@ -1377,6 +1400,24 @@ namespace nana{ namespace widgets
|
||||
return false;
|
||||
}
|
||||
|
||||
bool text_editor::respond_key(char_type key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case keyboard::os_arrow_left: move_left(); break;
|
||||
case keyboard::os_arrow_right: move_right(); break;
|
||||
case keyboard::os_arrow_up: move_ns(true); break;
|
||||
case keyboard::os_arrow_down: move_ns(false); break;
|
||||
case keyboard::os_del:
|
||||
if (this->attr().editable)
|
||||
del();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void text_editor::typeface_changed()
|
||||
{
|
||||
behavior_->pre_calc_lines(width_pixels());
|
||||
@ -1407,7 +1448,7 @@ namespace nana{ namespace widgets
|
||||
move_caret(upoint{});
|
||||
|
||||
_m_scrollbar();
|
||||
render(API::is_focus_window(window_));
|
||||
render(API::is_focus_ready(window_));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1425,7 +1466,7 @@ namespace nana{ namespace widgets
|
||||
|
||||
_m_reset();
|
||||
behavior_->pre_calc_lines(width_pixels());
|
||||
render(API::is_focus_window(window_));
|
||||
render(API::is_focus_ready(window_));
|
||||
_m_scrollbar();
|
||||
return true;
|
||||
}
|
||||
@ -1676,7 +1717,7 @@ namespace nana{ namespace widgets
|
||||
//Set caret position through text coordinate
|
||||
void text_editor::move_caret(const upoint& crtpos)
|
||||
{
|
||||
if (!API::is_focus_window(window_))
|
||||
if (!API::is_focus_ready(window_))
|
||||
return;
|
||||
|
||||
const unsigned line_pixels = line_height();
|
||||
@ -1718,7 +1759,7 @@ namespace nana{ namespace widgets
|
||||
|
||||
void text_editor::show_caret(bool isshow)
|
||||
{
|
||||
if(isshow == false || API::is_focus_window(window_))
|
||||
if(isshow == false || API::is_focus_ready(window_))
|
||||
API::caret_visible(window_, isshow);
|
||||
}
|
||||
|
||||
@ -1883,7 +1924,7 @@ namespace nana{ namespace widgets
|
||||
{
|
||||
behavior_->adjust_caret_into_screen();
|
||||
reset_caret();
|
||||
render(API::is_focus_window(window_));
|
||||
render(API::is_focus_ready(window_));
|
||||
_m_scrollbar();
|
||||
|
||||
points_.xpos = points_.caret.x;
|
||||
@ -2105,25 +2146,6 @@ namespace nana{ namespace widgets
|
||||
|
||||
}
|
||||
|
||||
bool text_editor::move(nana::char_t key)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case keyboard::os_arrow_left: move_left(); break;
|
||||
case keyboard::os_arrow_right: move_right(); break;
|
||||
case keyboard::os_arrow_up: move_ns(true); break;
|
||||
case keyboard::os_arrow_down: move_ns(false); break;
|
||||
case keyboard::os_del:
|
||||
if (this->attr().editable)
|
||||
del();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void text_editor::move_ns(bool to_north)
|
||||
{
|
||||
const bool redraw_required = _m_cancel_select(0);
|
||||
@ -2528,7 +2550,7 @@ namespace nana{ namespace widgets
|
||||
|
||||
//The number of new lines minus one
|
||||
const auto chp_end = text.data() + (begin == text.npos ? text.size() : begin);
|
||||
for (auto chp = text.data() + (pos + 2); chp != chp_end; ++chp)
|
||||
for (auto chp = text.data() + (pos + 1); chp != chp_end; ++chp)
|
||||
if (*chp == '\n')
|
||||
lines.emplace_back(0, 0);
|
||||
|
||||
@ -2764,18 +2786,17 @@ namespace nana{ namespace widgets
|
||||
}
|
||||
}
|
||||
|
||||
void text_editor::_m_draw_string(int top, const ::nana::color& clr, const nana::upoint& str_pos, const nana::string& linestr, bool if_mask) const
|
||||
void text_editor::_m_draw_string(int top, const ::nana::color& clr, const nana::upoint& str_pos, const nana::string& str, bool if_mask) const
|
||||
{
|
||||
::nana::point text_pos{ text_area_.area.x - points_.offset.x, top };
|
||||
const int xend = text_area_.area.x + static_cast<int>(text_area_.area.width);
|
||||
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (if_mask && mask_char_)
|
||||
{
|
||||
nana::string maskstr;
|
||||
maskstr.append(linestr.size(), mask_char_);
|
||||
graph_.string(text_pos, maskstr, clr);
|
||||
return;
|
||||
}
|
||||
mask_str.reset(new nana::string(str.size(), mask_char_));
|
||||
|
||||
|
||||
auto & linestr = (if_mask && mask_char_ ? *mask_str : str);
|
||||
|
||||
unicode_bidi bidi;
|
||||
std::vector<unicode_bidi::entity> reordered;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/element.hpp>
|
||||
#include <nana/gui/timer.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -328,7 +329,7 @@ namespace nana
|
||||
|
||||
void render()
|
||||
{
|
||||
editor_->render(API::is_focus_window(editor_->window_handle()));
|
||||
editor_->render(API::is_focus_ready(editor_->window_handle()));
|
||||
_m_draw_spins(spin_stated_);
|
||||
}
|
||||
|
||||
@ -420,7 +421,7 @@ namespace nana
|
||||
if (!editor_)
|
||||
return;
|
||||
|
||||
if (API::is_focus_window(editor_->window_handle()))
|
||||
if (API::is_focus_ready(editor_->window_handle()))
|
||||
editor_->text(range_->value());
|
||||
else
|
||||
editor_->text(modifier_.prefix + range_->value() + modifier_.suffix);
|
||||
@ -559,7 +560,7 @@ namespace nana
|
||||
|
||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if (impl_->editor()->move(arg.key))
|
||||
if (impl_->editor()->respond_key(arg.key))
|
||||
{
|
||||
impl_->editor()->reset_caret();
|
||||
impl_->draw_spins();
|
||||
@ -569,7 +570,7 @@ namespace nana
|
||||
|
||||
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if (impl_->editor()->respone_keyboard(arg.key))
|
||||
if (impl_->editor()->respond_char(arg.key))
|
||||
{
|
||||
if (!impl_->value(impl_->editor()->text()))
|
||||
impl_->draw_spins();
|
||||
|
||||
@ -83,7 +83,7 @@ namespace drawerbase {
|
||||
|
||||
void drawer::refresh(graph_reference graph)
|
||||
{
|
||||
editor_->render(API::is_focus_window(*widget_));
|
||||
editor_->render(API::is_focus_ready(*widget_));
|
||||
}
|
||||
|
||||
void drawer::focus(graph_reference graph, const arg_focus& arg)
|
||||
@ -136,7 +136,7 @@ namespace drawerbase {
|
||||
|
||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if(editor_->move(arg.key))
|
||||
if(editor_->respond_key(arg.key))
|
||||
{
|
||||
editor_->reset_caret();
|
||||
API::lazy_refresh();
|
||||
@ -145,7 +145,7 @@ namespace drawerbase {
|
||||
|
||||
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if (editor_->respone_keyboard(arg.key))
|
||||
if (editor_->respond_char(arg.key))
|
||||
API::lazy_refresh();
|
||||
}
|
||||
|
||||
@ -314,7 +314,7 @@ namespace drawerbase {
|
||||
internal_scope_guard lock;
|
||||
auto editor = get_drawer_trigger().editor();
|
||||
if (editor->line_wrapped(autl))
|
||||
editor->render(API::is_focus_window(handle()));
|
||||
API::update_window(handle());
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -389,7 +389,7 @@ namespace drawerbase {
|
||||
internal_scope_guard lock;
|
||||
auto editor = get_drawer_trigger().editor();
|
||||
if(editor && editor->select(yes))
|
||||
API::refresh_window(*this);
|
||||
API::update_window(*this);
|
||||
}
|
||||
|
||||
void textbox::copy() const
|
||||
@ -407,7 +407,7 @@ namespace drawerbase {
|
||||
if(editor)
|
||||
{
|
||||
editor->paste();
|
||||
API::refresh_window(*this);
|
||||
API::update_window(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -101,7 +101,7 @@ namespace nana
|
||||
|
||||
bool widget::focused() const
|
||||
{
|
||||
return API::is_focus_window(handle());
|
||||
return (API::focus_window() == handle());
|
||||
}
|
||||
|
||||
void widget::show()
|
||||
|
||||
@ -250,6 +250,11 @@ namespace paint
|
||||
image_ptr_.reset();
|
||||
}
|
||||
|
||||
bool image::alpha() const
|
||||
{
|
||||
return (image_ptr_ ? image_ptr_->alpha_channel() : false);
|
||||
}
|
||||
|
||||
nana::size image::size() const
|
||||
{
|
||||
return (image_ptr_ ? image_ptr_->size() : nana::size());
|
||||
|
||||
@ -12,6 +12,10 @@
|
||||
|
||||
#include <nana/system/dataexch.hpp>
|
||||
#include <nana/traits.hpp>
|
||||
#include <nana/paint/graphics.hpp>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(NANA_X11)
|
||||
@ -33,6 +37,86 @@ namespace nana{ namespace system{
|
||||
_m_set(std::is_same<char, nana::char_t>::value ? format::text : format::unicode, text.c_str(), (text.length() + 1) * sizeof(nana::char_t));
|
||||
}
|
||||
|
||||
bool dataexch::set(const nana::paint::graphics& g)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
size sz = g.size();
|
||||
paint::pixel_buffer pbuffer;
|
||||
rectangle r;
|
||||
r.x = 0;
|
||||
r.y = 0;
|
||||
r.width = sz.width;
|
||||
r.height = sz.height;
|
||||
pbuffer.attach(g.handle(), r);
|
||||
size_t bytes_per_line = pbuffer.bytes_per_line();
|
||||
size_t bitmap_bytes = bytes_per_line * r.height;
|
||||
|
||||
struct {
|
||||
BITMAPINFOHEADER bmiHeader;
|
||||
RGBQUAD bmiColors[256];
|
||||
} bmi = {0};
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
HDC hDC = ::GetDC(NULL);
|
||||
if (::GetDIBits(hDC, (HBITMAP)g.pixmap(), 0, 1, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS) == 0) {
|
||||
assert(false);
|
||||
int err = ::GetLastError();
|
||||
::ReleaseDC(NULL, hDC);
|
||||
return false;
|
||||
}
|
||||
if (!::ReleaseDC(NULL, hDC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t header_size = sizeof(bmi.bmiHeader);
|
||||
|
||||
// Bitmaps are huge, so to avoid unnegligible extra copy, this routine does not use private _m_set method.
|
||||
HGLOBAL h_gmem = ::GlobalAlloc(GHND | GMEM_SHARE, header_size + bitmap_bytes);
|
||||
void * gmem = ::GlobalLock(h_gmem);
|
||||
if (!gmem) {
|
||||
assert(false);
|
||||
goto Label_GlobalFree;
|
||||
}
|
||||
char* p = (char*)gmem;
|
||||
// Fix BITMAPINFOHEADER obtained from GetDIBits WinAPI
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biHeight = ::abs(bmi.bmiHeader.biHeight);
|
||||
memcpy(p, &bmi, header_size);
|
||||
p += header_size;
|
||||
// many programs do not support bottom-up DIB, so reversing row order is needed.
|
||||
for (int y=0; y<bmi.bmiHeader.biHeight; ++y) {
|
||||
memcpy(p, pbuffer.raw_ptr(bmi.bmiHeader.biHeight - 1 - y), bytes_per_line);
|
||||
p += bytes_per_line;
|
||||
}
|
||||
if (!::GlobalUnlock(h_gmem) && GetLastError() != NO_ERROR) {
|
||||
assert(false);
|
||||
goto Label_GlobalFree;
|
||||
}
|
||||
if (!::OpenClipboard(::GetFocus())) {
|
||||
goto Label_GlobalFree;
|
||||
}
|
||||
if (!::EmptyClipboard()) {
|
||||
goto Label_GlobalFree;
|
||||
}
|
||||
if (!::SetClipboardData(CF_DIB, h_gmem)) {
|
||||
goto Label_GlobalFree;
|
||||
}
|
||||
if (!::CloseClipboard()) {
|
||||
// really?
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
Label_GlobalFree:
|
||||
::GlobalFree(h_gmem);
|
||||
return false;
|
||||
|
||||
//#elif defined(NANA_X11)
|
||||
#else
|
||||
throw "not implemented yet.";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dataexch::get(nana::string& str)
|
||||
{
|
||||
std::size_t size;
|
||||
@ -78,8 +162,8 @@ namespace nana{ namespace system{
|
||||
case format::unicode: type = CF_UNICODETEXT; break;
|
||||
case format::pixmap: type = CF_BITMAP; break;
|
||||
}
|
||||
::SetClipboardData(type, g);
|
||||
res = true;
|
||||
HANDLE h = ::SetClipboardData(type, g);
|
||||
res = (h != NULL);
|
||||
}
|
||||
::CloseClipboard();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user