Merge branch 'develop'
This commit is contained in:
commit
df2b97a048
@ -56,7 +56,7 @@ matrix:
|
||||
- llvm-toolchain-precise
|
||||
|
||||
before_install:
|
||||
- git clone --depth=1 --branch=develop https://github.com/qPCR4vir/nana-demo.git ../nana-demo
|
||||
- git clone --depth=1 --branch=hotfix-1.4 https://github.com/qPCR4vir/nana-demo.git ../nana-demo
|
||||
- export PATH="$HOME/bin:$PATH"
|
||||
- mkdir ~/bin
|
||||
- wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.4/cmake-3.4.0-rc3-Linux-x86_64.sh || true
|
||||
|
||||
@ -68,12 +68,26 @@ if(WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
#Global MSVC definitions. You may prefer the hand-tuned sln and projects from the nana repository.
|
||||
if(MSVC)
|
||||
option(WIN32_USE_MP "Set to ON to build nana with the /MP option (Visual Studio 2005 and above)." ON)
|
||||
# ??
|
||||
if(WIN32_USE_MP)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif(WIN32_USE_MP)
|
||||
endif(MSVC)
|
||||
option(MSVC_USE_MP "Set to ON to build nana with the /MP option (Visual Studio 2005 and above)." ON)
|
||||
option(MSVC_USE_STATIC_RUNTIME "Set to ON to build nana with the /MT(d) option." ON)
|
||||
|
||||
# Change the MSVC Compiler flags
|
||||
if(MSVC_USE_MP)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif(MSVC_USE_MP)
|
||||
|
||||
if(MSVC_USE_STATIC_RUNTIME)
|
||||
foreach(flag
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif(MSVC_USE_STATIC_RUNTIME)
|
||||
endif(MSVC)
|
||||
|
||||
if(MINGW)
|
||||
if(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ)
|
||||
@ -251,8 +265,8 @@ foreach(subdir ${NANA_SOURCE_SUBDIRS})
|
||||
# message("Subir: ${subdir}") # message("Files: ${sources}")
|
||||
endforeach(subdir ${NANA_SOURCE_SUBDIRS})
|
||||
|
||||
include_directories(${NANA_INCLUDE_DIR})
|
||||
add_library(${PROJECT_NAME} ${sources} )
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${NANA_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} ${NANA_LINKS})
|
||||
|
||||
# Headers: use INCLUDE_DIRECTORIES
|
||||
@ -290,5 +304,3 @@ message ( "NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT = " ${NANA_CMAKE_BOOST_FILE
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_LIB = " ${NANA_CMAKE_BOOST_FILESYSTEM_LIB})
|
||||
message ( "NANA_CMAKE_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_AUTOMATIC_GUI_TESTING})
|
||||
message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING})
|
||||
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
<Unit filename="../../source/charset.cpp" />
|
||||
<Unit filename="../../source/datetime.cpp" />
|
||||
<Unit filename="../../source/deploy.cpp" />
|
||||
<Unit filename="../../source/detail/platform_spec_posix.cpp" />
|
||||
<Unit filename="../../source/detail/platform_abstraction.cpp" />
|
||||
<Unit filename="../../source/detail/platform_spec_windows.cpp" />
|
||||
<Unit filename="../../source/filesystem/filesystem.cpp" />
|
||||
<Unit filename="../../source/gui/animation.cpp" />
|
||||
@ -96,6 +96,7 @@
|
||||
<Unit filename="../../source/gui/widgets/picture.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/progress.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/scroll.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/skeletons/content_view.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/skeletons/text_editor.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/slider.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/spinbox.cpp" />
|
||||
@ -113,6 +114,7 @@
|
||||
<Unit filename="../../source/paint/image_process_selector.cpp" />
|
||||
<Unit filename="../../source/paint/pixel_buffer.cpp" />
|
||||
<Unit filename="../../source/paint/text_renderer.cpp" />
|
||||
<Unit filename="../../source/stdc++.cpp" />
|
||||
<Unit filename="../../source/system/dataexch.cpp" />
|
||||
<Unit filename="../../source/system/platform.cpp" />
|
||||
<Unit filename="../../source/system/shared_wrapper.cpp" />
|
||||
|
||||
@ -187,6 +187,7 @@
|
||||
<ClCompile Include="..\..\source\charset.cpp" />
|
||||
<ClCompile Include="..\..\source\datetime.cpp" />
|
||||
<ClCompile Include="..\..\source\deploy.cpp" />
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp" />
|
||||
<ClCompile Include="..\..\source\detail\platform_spec_windows.cpp" />
|
||||
<ClCompile Include="..\..\source\filesystem\filesystem.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\animation.cpp" />
|
||||
@ -232,6 +233,7 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
||||
@ -249,6 +251,7 @@
|
||||
<ClCompile Include="..\..\source\paint\image_process_selector.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\pixel_buffer.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\text_renderer.cpp" />
|
||||
<ClCompile Include="..\..\source\stdc++.cpp" />
|
||||
<ClCompile Include="..\..\source\system\dataexch.cpp" />
|
||||
<ClCompile Include="..\..\source\system\platform.cpp" />
|
||||
<ClCompile Include="..\..\source\system\shared_wrapper.cpp" />
|
||||
|
||||
@ -324,6 +324,15 @@
|
||||
<ClCompile Include="..\..\source\gui\detail\bedrock_windows.cpp">
|
||||
<Filter>Source Files\nana\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\stdc++.cpp">
|
||||
<Filter>Source Files\nana</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp">
|
||||
<Filter>Source Files\nana\gui\widgets\skeletons</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp">
|
||||
<Filter>Source Files\nana\detail</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
||||
|
||||
@ -181,6 +181,7 @@
|
||||
<ClCompile Include="..\..\source\charset.cpp" />
|
||||
<ClCompile Include="..\..\source\datetime.cpp" />
|
||||
<ClCompile Include="..\..\source\deploy.cpp" />
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp" />
|
||||
<ClCompile Include="..\..\source\detail\platform_spec_windows.cpp" />
|
||||
<ClCompile Include="..\..\source\filesystem\filesystem.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\animation.cpp" />
|
||||
@ -226,6 +227,7 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
||||
@ -243,6 +245,7 @@
|
||||
<ClCompile Include="..\..\source\paint\image_process_selector.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\pixel_buffer.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\text_renderer.cpp" />
|
||||
<ClCompile Include="..\..\source\stdc++.cpp" />
|
||||
<ClCompile Include="..\..\source\system\dataexch.cpp" />
|
||||
<ClCompile Include="..\..\source\system\platform.cpp" />
|
||||
<ClCompile Include="..\..\source\system\timepiece.cpp" />
|
||||
|
||||
@ -282,5 +282,14 @@
|
||||
<ClCompile Include="..\..\source\gui\detail\bedrock_windows.cpp">
|
||||
<Filter>Source Files\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\stdc++.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp">
|
||||
<Filter>Source Files\gui\widgets\skeletons</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp">
|
||||
<Filter>Source Files\detail</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
28
build/vc2017/nana.sln
Normal file
28
build/vc2017/nana.sln
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26228.4
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{42D0520F-EFA5-4831-84FE-2B9085301C5D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Debug|x64.Build.0 = Debug|x64
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Release|x64.ActiveCfg = Release|x64
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Release|x64.Build.0 = Release|x64
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{42D0520F-EFA5-4831-84FE-2B9085301C5D}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
209
build/vc2017/nana.vcxproj
Normal file
209
build/vc2017/nana.vcxproj
Normal file
@ -0,0 +1,209 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{42D0520F-EFA5-4831-84FE-2B9085301C5D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>nana</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</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 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 Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<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|x64'">
|
||||
<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|x64'">
|
||||
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
|
||||
<OutDir>../bin/</OutDir>
|
||||
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
|
||||
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
|
||||
<OutDir>../bin/</OutDir>
|
||||
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
|
||||
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\any.cpp" />
|
||||
<ClCompile Include="..\..\source\audio\detail\audio_device.cpp" />
|
||||
<ClCompile Include="..\..\source\audio\detail\audio_stream.cpp" />
|
||||
<ClCompile Include="..\..\source\audio\detail\buffer_preparation.cpp" />
|
||||
<ClCompile Include="..\..\source\audio\player.cpp" />
|
||||
<ClCompile Include="..\..\source\basic_types.cpp" />
|
||||
<ClCompile Include="..\..\source\charset.cpp" />
|
||||
<ClCompile Include="..\..\source\datetime.cpp" />
|
||||
<ClCompile Include="..\..\source\deploy.cpp" />
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp" />
|
||||
<ClCompile Include="..\..\source\detail\platform_spec_windows.cpp" />
|
||||
<ClCompile Include="..\..\source\filesystem\filesystem.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\basic_window.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\bedrock_pi.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\bedrock_windows.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\color_schemes.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\drawer.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\element_store.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\events_operation.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\button.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\categorize.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\checkbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\combox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\label.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\menu.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\menubar.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\panel.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\tabbar.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\textbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\toolbar.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\treebox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\widget.cpp" />
|
||||
<ClCompile Include="..\..\source\internationalization.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\detail\image_process_provider.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\detail\native_paint_interface.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\graphics.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\image.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\image_process_selector.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\pixel_buffer.cpp" />
|
||||
<ClCompile Include="..\..\source\paint\text_renderer.cpp" />
|
||||
<ClCompile Include="..\..\source\stdc++.cpp" />
|
||||
<ClCompile Include="..\..\source\system\dataexch.cpp" />
|
||||
<ClCompile Include="..\..\source\system\platform.cpp" />
|
||||
<ClCompile Include="..\..\source\system\shared_wrapper.cpp" />
|
||||
<ClCompile Include="..\..\source\system\timepiece.cpp" />
|
||||
<ClCompile Include="..\..\source\threads\pool.cpp" />
|
||||
<ClCompile Include="..\..\source\unicode_bidi.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
244
build/vc2017/nana.vcxproj.filters
Normal file
244
build/vc2017/nana.vcxproj.filters
Normal file
@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="源文件\audio">
|
||||
<UniqueIdentifier>{81850bad-7436-405a-beb5-357c5e34f039}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\audio\detail">
|
||||
<UniqueIdentifier>{44582b36-4575-4663-ac02-e80417f95d05}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\detail">
|
||||
<UniqueIdentifier>{b7e3cdb7-99ac-473d-86c8-53dddce70480}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\filesystem">
|
||||
<UniqueIdentifier>{02fa693c-edc1-4e04-bf1d-ec3c2a89182a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\gui">
|
||||
<UniqueIdentifier>{cffe7506-b96c-42aa-a747-41b5115d9580}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\gui\detail">
|
||||
<UniqueIdentifier>{b6b2c032-c6a4-4884-8c14-eca4aa69ef0c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\gui\widgets">
|
||||
<UniqueIdentifier>{58f2e0f8-4d63-40db-807d-d7adf71c4ebe}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\gui\widgets\skeletons">
|
||||
<UniqueIdentifier>{f288a25d-3ce8-4c2e-a86f-9aeda44bc557}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\paint">
|
||||
<UniqueIdentifier>{90b2da01-605d-489b-b6c5-2af8d3c2d8a6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\paint\detail">
|
||||
<UniqueIdentifier>{430feed0-e1d9-45cb-8d59-e1a48a04d19f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\system">
|
||||
<UniqueIdentifier>{dcf62634-a658-453b-a58d-f1a96a12a8b8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\threads">
|
||||
<UniqueIdentifier>{c1cdf46a-519f-422a-947f-39e173045414}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\any.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\basic_types.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\charset.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\datetime.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\deploy.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\internationalization.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\stdc++.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\unicode_bidi.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\audio\detail\audio_device.cpp">
|
||||
<Filter>源文件\audio\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\audio\detail\audio_stream.cpp">
|
||||
<Filter>源文件\audio\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\audio\detail\buffer_preparation.cpp">
|
||||
<Filter>源文件\audio\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\audio\player.cpp">
|
||||
<Filter>源文件\audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\detail\platform_spec_windows.cpp">
|
||||
<Filter>源文件\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\filesystem\filesystem.cpp">
|
||||
<Filter>源文件\filesystem</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\basic_window.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\bedrock_pi.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\bedrock_windows.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\color_schemes.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\drawer.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\element_store.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\events_operation.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp">
|
||||
<Filter>源文件\gui\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp">
|
||||
<Filter>源文件\gui\widgets\skeletons</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp">
|
||||
<Filter>源文件\gui\widgets\skeletons</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\button.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\categorize.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\checkbox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\combox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\label.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\menu.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\menubar.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\panel.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\picture.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\progress.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\slider.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\tabbar.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\textbox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\toolbar.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\treebox.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\widget.cpp">
|
||||
<Filter>源文件\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\detail\image_process_provider.cpp">
|
||||
<Filter>源文件\paint\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\detail\native_paint_interface.cpp">
|
||||
<Filter>源文件\paint\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\graphics.cpp">
|
||||
<Filter>源文件\paint</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\image.cpp">
|
||||
<Filter>源文件\paint</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\image_process_selector.cpp">
|
||||
<Filter>源文件\paint</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\pixel_buffer.cpp">
|
||||
<Filter>源文件\paint</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\paint\text_renderer.cpp">
|
||||
<Filter>源文件\paint</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\system\dataexch.cpp">
|
||||
<Filter>源文件\system</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\system\platform.cpp">
|
||||
<Filter>源文件\system</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\system\shared_wrapper.cpp">
|
||||
<Filter>源文件\system</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\system\timepiece.cpp">
|
||||
<Filter>源文件\system</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\threads\pool.cpp">
|
||||
<Filter>源文件\threads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp">
|
||||
<Filter>源文件\detail</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Basic Types definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -84,7 +84,7 @@ namespace nana
|
||||
|
||||
enum class mouse_action
|
||||
{
|
||||
begin, normal = begin, hovered, pressed, end
|
||||
begin, normal = begin, normal_captured, hovered, pressed, end
|
||||
};
|
||||
|
||||
enum class element_state
|
||||
@ -97,12 +97,6 @@ namespace nana
|
||||
disabled
|
||||
};
|
||||
|
||||
typedef unsigned scalar_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long uint32_t;
|
||||
typedef unsigned uint_t;
|
||||
typedef long long long_long_t;
|
||||
|
||||
union pixel_argb_t
|
||||
{
|
||||
struct element_tag
|
||||
@ -304,8 +298,7 @@ namespace nana
|
||||
color(color_rgb);
|
||||
color(color_argb);
|
||||
color(color_rgba);
|
||||
color(unsigned red, unsigned green, unsigned blue);
|
||||
color(unsigned red, unsigned green, unsigned blue, double alpha);
|
||||
color(unsigned red, unsigned green, unsigned blue, double alpha = 1.0);
|
||||
|
||||
/// Initializes the color with a CSS-like rgb string.
|
||||
explicit color(std::string css_rgb);
|
||||
@ -319,10 +312,7 @@ namespace nana
|
||||
/// @param lightness in range of [0, 1]
|
||||
color& from_hsl(double hue, double saturation, double lightness); ///< immutable alpha channel
|
||||
|
||||
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.
|
||||
color blend(const color& bgcolor, double alpha) const;
|
||||
color blend(const color& blending_color, double alpha) const;
|
||||
|
||||
/// Determines whether the color is completely transparent.
|
||||
bool invisible() const;
|
||||
@ -457,8 +447,8 @@ namespace nana
|
||||
|
||||
rectangle& pare_off(int pixels); ///<Pares the specified pixels off the rectangle. It's equal to x += pixels; y + pixels; width -= (pixels << 1); height -= (pixels << 1);
|
||||
|
||||
int right() const;
|
||||
int bottom() const;
|
||||
int right() const noexcept;
|
||||
int bottom() const noexcept;
|
||||
bool is_hit(int x, int y) const;
|
||||
bool is_hit(const point& pos) const;
|
||||
bool empty() const; ///< true if width * height == 0.
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Predefined Symbols for C++
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2016-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file nana/config.hpp
|
||||
* @file nana/c++defines.hpp
|
||||
*
|
||||
* @brief Provide switches to adapt to the target OS, use of external libraries or workarounds compiler errors or lack of std C++ support.
|
||||
*
|
||||
@ -31,13 +31,14 @@
|
||||
* - _SCL_SECURE_NO_WARNNGS, _CRT_SECURE_NO_DEPRECATE (VC)
|
||||
* - STD_CODECVT_NOT_SUPPORTED (VC RC, <codecvt> is a known issue on libstdc++, it works on libc++)
|
||||
* - STD_THREAD_NOT_SUPPORTED (GCC < 4.8.1)
|
||||
* - STD_put_time_NOT_SUPPORTED (GCC < 5)
|
||||
* - STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED (MinGW with GCC < 4.8.1)
|
||||
* - STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED (MinGW with GCC < 4.8.1)
|
||||
* - STD_TO_STRING_NOT_SUPPORTED (MinGW with GCC < 4.8)
|
||||
* - STD_FILESYSTEM_NOT_SUPPORTED (GCC < 5.3) ....
|
||||
* - CXX_NO_INLINE_NAMESPACE (Visual C++ < 2015)
|
||||
* - STD_MAKE_UNIQUE_NOT_SUPPORTED (GCC < 4.9)
|
||||
* - _enable_std_make_unique (GCC < 4.9)
|
||||
* - _enable_std_put_time (GCC < 5)
|
||||
* - _enable_std_clamp (Visual C++ < 2017)
|
||||
*/
|
||||
|
||||
#ifndef NANA_CXX_DEFINES_INCLUDED
|
||||
@ -57,7 +58,7 @@
|
||||
# define CXX_NO_INLINE_NAMESPACE //no support of C++11 inline namespace until Visual C++ 2015
|
||||
# define noexcept //no support of noexcept until Visual C++ 2015
|
||||
|
||||
# define constexpr const //no support of constexpr until Visual C++ 2015 ? const ??
|
||||
# define constexpr //no support of constexpr until Visual C++ 2015 ? const ??
|
||||
# else
|
||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||
# endif
|
||||
@ -102,15 +103,21 @@
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#pragma warning(disable : 4996)
|
||||
|
||||
#if (_MSC_VER == 1900)
|
||||
# if (_MSC_VER >= 1900)
|
||||
// google: break any code that tries to use codecvt<char16_t> or codecvt<char32_t>.
|
||||
// google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support.
|
||||
// google: Those definitions are for codecvt<wchar_t>::id, codecvt<unsigned short>::id and codecvt<char>::id respectively.
|
||||
// However, the codecvt<char16_t>::id and codecvt<char32_t>::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all.
|
||||
// google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources.
|
||||
#define STD_CODECVT_NOT_SUPPORTED
|
||||
#endif // _MSC_VER == 1900
|
||||
# define STD_CODECVT_NOT_SUPPORTED
|
||||
# endif // _MSC_VER == 1900
|
||||
|
||||
# if (_MSC_VER < 1910) //VS2017 RTM
|
||||
# define _enable_std_clamp
|
||||
# endif
|
||||
|
||||
#elif defined(NANA_MINGW)
|
||||
# define STD_THREAD_NOT_SUPPORTED
|
||||
#elif defined(__clang__) //Clang
|
||||
|
||||
#include <iosfwd> //Introduces some implement-specific flags of ISO C++ Library
|
||||
@ -119,13 +126,15 @@
|
||||
#define STD_CODECVT_NOT_SUPPORTED
|
||||
|
||||
#if !defined(__cpp_lib_make_unique) || (__cpp_lib_make_unique != 201304)
|
||||
#ifndef STD_MAKE_UNIQUE_NOT_SUPPORTED
|
||||
#define STD_MAKE_UNIQUE_NOT_SUPPORTED
|
||||
#ifndef _enable_std_make_unique
|
||||
#define _enable_std_make_unique
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
# define _enable_std_clamp
|
||||
|
||||
#elif defined(__GNUC__) //GCC
|
||||
|
||||
#include <iosfwd> //Introduces some implement-specific flags of ISO C++ Library
|
||||
@ -145,9 +154,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if ((__GNUC__ < 5) )
|
||||
# define STD_put_time_NOT_SUPPORTED
|
||||
#endif
|
||||
# if ((__GNUC__ < 5) )
|
||||
# define _enable_std_put_time
|
||||
# endif
|
||||
|
||||
#if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) )
|
||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||
@ -160,7 +169,7 @@
|
||||
#endif
|
||||
|
||||
#if (__GNUC_MINOR__ < 9)
|
||||
#define STD_MAKE_UNIQUE_NOT_SUPPORTED
|
||||
#define _enable_std_make_unique
|
||||
#endif
|
||||
|
||||
#if defined(NANA_MINGW)
|
||||
@ -181,6 +190,8 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
# define _enable_std_clamp
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The Deploy Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,98 +17,11 @@
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
||||
#include <nana/config.hpp>
|
||||
#include <nana/stdc++.hpp>
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <nana/charset.hpp>
|
||||
|
||||
//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.
|
||||
int stoi(const std::string&, std::size_t * pos = nullptr, int base = 10);
|
||||
int stoi(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stof in MinGW.
|
||||
float stof(const std::string&, std::size_t * pos = nullptr);
|
||||
float stof(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stod in MinGW.
|
||||
double stod(const std::string&, std::size_t * pos = nullptr);
|
||||
double stod(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stold in MinGW.
|
||||
long double stold(const std::string&, std::size_t * pos = nullptr);
|
||||
long double stold(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stol in MinGW.
|
||||
long stol(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
long stol(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoll in MinGW.
|
||||
long long stoll(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
long long stoll(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoul in MinGW.
|
||||
unsigned long stoul(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
unsigned long stoul(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoull in MinGW.
|
||||
unsigned long long stoull(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
unsigned long long stoull(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
}
|
||||
#endif //STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED
|
||||
|
||||
#ifdef STD_TO_STRING_NOT_SUPPORTED
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::to_string/std::to_wstring in MinGW.
|
||||
std::string to_string(long double);
|
||||
std::string to_string(double);
|
||||
std::string to_string(unsigned);
|
||||
std::string to_string(int);
|
||||
std::string to_string(long);
|
||||
std::string to_string(unsigned long);
|
||||
std::string to_string(long long);
|
||||
std::string to_string(unsigned long long);
|
||||
std::string to_string(float);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STD_TO_WSTRING_NOT_SUPPORTED
|
||||
namespace std
|
||||
{
|
||||
std::wstring to_wstring(long double);
|
||||
std::wstring to_wstring(double);
|
||||
std::wstring to_wstring(unsigned);
|
||||
std::wstring to_wstring(int);
|
||||
std::wstring to_wstring(long);
|
||||
std::wstring to_wstring(unsigned long);
|
||||
std::wstring to_wstring(long long);
|
||||
std::wstring to_wstring(unsigned long long);
|
||||
std::wstring to_wstring(float);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STD_put_time_NOT_SUPPORTED
|
||||
#include <ctime>
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::put_time in gcc < 5.
|
||||
/* std unspecified return type */
|
||||
//template< class CharT, class RTSTR >// let fail for CharT != char / wchar_t
|
||||
//RTSTR put_time(const std::tm* tmb, const CharT* fmt);
|
||||
|
||||
//template< >
|
||||
std::string put_time/*<char, std::string>*/(const std::tm* tmb, const char* fmt);
|
||||
|
||||
//Defined in header <ctime>
|
||||
// std::size_t strftime(char* str, std::size_t count, const char* format, const std::tm* time);
|
||||
//template<>
|
||||
//std::wstring put_time<wchar_t, std::wstring>(const std::tm* tmb, const wchar_t* fmt);
|
||||
}
|
||||
#endif // STD_put_time_NOT_SUPPORTED
|
||||
#include <stdexcept>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -192,45 +105,5 @@ namespace nana
|
||||
|
||||
#define NANA_RGB(a) (((DWORD)(a) & 0xFF)<<16) | ((DWORD)(a) & 0xFF00) | (((DWORD)(a) & 0xFF0000) >> 16 )
|
||||
|
||||
|
||||
#ifdef STD_MAKE_UNIQUE_NOT_SUPPORTED
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace std {
|
||||
template<class T> struct _Unique_if {
|
||||
typedef unique_ptr<T> _Single_object;
|
||||
};
|
||||
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_unique(Args&&... args) {
|
||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_unique(size_t n) {
|
||||
typedef typename remove_extent<T>::type U;
|
||||
return unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_unique(Args&&...) = delete;
|
||||
}
|
||||
#endif //STD_make_unique_NOT_SUPPORTED
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
#endif //NANA_DEPLOY_HPP
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -23,13 +23,13 @@ namespace filesystem_ext
|
||||
{
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
constexpr auto def_root = "C:";
|
||||
constexpr auto def_rootstr = "C:\\";
|
||||
constexpr auto def_rootname = "Local Drive(C:)";
|
||||
constexpr auto const def_root = "C:";
|
||||
constexpr auto const def_rootstr = "C:\\";
|
||||
constexpr auto const def_rootname = "Local Drive(C:)";
|
||||
#elif defined(NANA_LINUX)
|
||||
constexpr auto def_root = "/";
|
||||
constexpr auto def_rootstr = "/";
|
||||
constexpr auto def_rootname = "Root/";
|
||||
constexpr auto const def_root = "/";
|
||||
constexpr auto const def_rootstr = "/";
|
||||
constexpr auto const def_rootname = "Root/";
|
||||
#endif
|
||||
|
||||
std::experimental::filesystem::path path_user(); ///< extention ?
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Basic Window Widget Definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,6 +17,7 @@
|
||||
#include "drawer.hpp"
|
||||
#include "events_holder.hpp"
|
||||
#include "widget_geometrics.hpp"
|
||||
#include "widget_content_measurer_interface.hpp"
|
||||
#include "widget_notifier_interface.hpp"
|
||||
#include <nana/basic_types.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
@ -85,7 +86,7 @@ namespace detail
|
||||
|
||||
enum class update_state
|
||||
{
|
||||
none, lazy, refresh
|
||||
none, lazy, refreshed, request_refresh
|
||||
};
|
||||
|
||||
struct edge_nimbus_action
|
||||
@ -191,6 +192,7 @@ namespace detail
|
||||
//The following pointers refer to the widget's object.
|
||||
std::shared_ptr<general_events> events_ptr;
|
||||
widget_geometrics* scheme{ nullptr };
|
||||
::nana::dev::widget_content_measurer_interface* content_measurer{ nullptr };
|
||||
}annex;
|
||||
|
||||
struct
|
||||
@ -220,9 +222,6 @@ namespace detail
|
||||
basic_window* focus{nullptr};
|
||||
basic_window* menubar{nullptr};
|
||||
bool ime_enabled{false};
|
||||
#if defined(NANA_WINDOWS)
|
||||
cursor running_cursor{ nana::cursor::arrow };
|
||||
#endif
|
||||
cursor state_cursor{nana::cursor::arrow};
|
||||
basic_window* state_cursor_window{ nullptr };
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Bedrock Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -70,6 +70,9 @@ namespace detail
|
||||
|
||||
element_store& get_element_store() const;
|
||||
void map_through_widgets(core_window_t*, native_drawable_type);
|
||||
|
||||
//Closes the windows which are associated with the specified thread. If the given thread_id is 0, it closes all windows
|
||||
void close_thread_window(unsigned thread_id);
|
||||
public:
|
||||
void event_expose(core_window_t *, bool exposed);
|
||||
void event_move(core_window_t*, int x, int y);
|
||||
@ -92,7 +95,6 @@ namespace detail
|
||||
private:
|
||||
void _m_emit_core(event_code, core_window_t*, bool draw_only, const event_arg&);
|
||||
void _m_event_filter(event_code, core_window_t*, thread_context*);
|
||||
void _m_except_handler();
|
||||
private:
|
||||
static bedrock bedrock_object;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Drawer Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -126,8 +126,7 @@ namespace nana
|
||||
void* draw(std::function<void(paint::graphics&)> &&, bool diehard);
|
||||
void erase(void* diehard);
|
||||
private:
|
||||
void _m_effect_bground(bool before);
|
||||
bool _m_lazy_decleared() const;
|
||||
void _m_effect_bground_subsequent();
|
||||
method_state& _m_mth_state(int pos);
|
||||
|
||||
template<typename Arg, typename Mfptr>
|
||||
@ -140,8 +139,6 @@ namespace nana
|
||||
|
||||
if (realizer && (method_state::not_overrided != mth_state))
|
||||
{
|
||||
_m_effect_bground(true);
|
||||
|
||||
if (method_state::pending == mth_state)
|
||||
{
|
||||
(realizer->*mfptr)(graphics, arg);
|
||||
@ -154,8 +151,7 @@ namespace nana
|
||||
else
|
||||
(realizer->*mfptr)(graphics, arg);
|
||||
|
||||
if (_m_lazy_decleared())
|
||||
_m_effect_bground(false);
|
||||
_m_effect_bground_subsequent();
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
@ -86,7 +86,7 @@ namespace nana{
|
||||
}
|
||||
|
||||
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
|
||||
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
|
||||
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refreshed))
|
||||
{
|
||||
rd_set.emplace_back(r, action.window);
|
||||
action.rendered = true;
|
||||
|
||||
@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Handle Manager Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/detail/handle_manager.hpp
|
||||
*
|
||||
* @description:
|
||||
* this manages all the window handles
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_DETAIL_HANDLE_MANAGER_HPP
|
||||
#define NANA_GUI_DETAIL_HANDLE_MANAGER_HPP
|
||||
|
||||
#include <nana/traits.hpp>
|
||||
#include <nana/config.hpp>
|
||||
#if defined(STD_THREAD_NOT_SUPPORTED)
|
||||
#include <nana/std_mutex.hpp>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <iterator>
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Key, typename Value, std::size_t CacheSize>
|
||||
class cache
|
||||
: noncopyable
|
||||
{
|
||||
public:
|
||||
typedef Key key_type;
|
||||
typedef Value value_type;
|
||||
typedef std::pair<key_type, value_type> pair_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
cache()
|
||||
:addr_(reinterpret_cast<pair_type*>(::operator new(sizeof(pair_type) * CacheSize)))
|
||||
{
|
||||
for(std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
bitmap_[i] = 0;
|
||||
seq_[i] = nana::npos;
|
||||
}
|
||||
}
|
||||
|
||||
~cache()
|
||||
{
|
||||
for(std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
if(bitmap_[i])
|
||||
addr_[i].~pair_type();
|
||||
}
|
||||
|
||||
::operator delete(addr_);
|
||||
}
|
||||
|
||||
bool insert(key_type k, value_type v)
|
||||
{
|
||||
size_type pos = _m_find_key(k);
|
||||
if(pos != nana::npos)
|
||||
{
|
||||
addr_[pos].second = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
//No key exists
|
||||
pos = _m_find_pos();
|
||||
|
||||
if(pos == nana::npos)
|
||||
{ //No room, and remove the last pair
|
||||
pos = seq_[CacheSize - 1];
|
||||
(addr_ + pos)->~pair_type();
|
||||
}
|
||||
|
||||
if(seq_[0] != nana::npos)
|
||||
{//Need to move
|
||||
for(int i = CacheSize - 1; i > 0; --i)
|
||||
seq_[i] = seq_[i - 1];
|
||||
}
|
||||
|
||||
seq_[0] = pos;
|
||||
|
||||
new (addr_ + pos) pair_type(k, v);
|
||||
bitmap_[pos] = 1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type * get(key_type k)
|
||||
{
|
||||
size_type pos = _m_find_key(k);
|
||||
if(pos != nana::npos)
|
||||
return &(addr_[pos].second);
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
size_type _m_find_key(key_type k) const
|
||||
{
|
||||
for(std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
if(bitmap_[i] && (addr_[i].first == k))
|
||||
return i;
|
||||
}
|
||||
return nana::npos;
|
||||
}
|
||||
|
||||
size_type _m_find_pos() const
|
||||
{
|
||||
for(std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
if(bitmap_[i] == 0)
|
||||
return i;
|
||||
}
|
||||
return nana::npos;
|
||||
}
|
||||
private:
|
||||
char bitmap_[CacheSize];
|
||||
size_type seq_[CacheSize];
|
||||
pair_type * addr_;
|
||||
};
|
||||
|
||||
//handle_manager
|
||||
//@brief
|
||||
// handle_manager maintains handles of a type. removing a handle dose not destroy it,
|
||||
// it will be inserted to a trash queue for deleting at a safe time.
|
||||
// For efficiency, this class is not a thread-safe.
|
||||
template<typename HandleType, typename Condition, typename Deleter>
|
||||
class handle_manager
|
||||
: nana::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef HandleType handle_type;
|
||||
typedef Condition cond_type;
|
||||
typedef Deleter deleter_type;
|
||||
typedef std::map<handle_type, unsigned> handle_map_t;
|
||||
typedef std::pair<handle_type, unsigned> holder_pair;
|
||||
|
||||
~handle_manager()
|
||||
{
|
||||
delete_trash(0);
|
||||
}
|
||||
|
||||
void insert(handle_type handle, unsigned tid)
|
||||
{
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
|
||||
holder_[handle] = tid;
|
||||
|
||||
is_queue<std::is_same<cond_type, nana::null_type>::value, std::vector<handle_type> >::insert(handle, queue_);
|
||||
cacher_.insert(handle, true);
|
||||
}
|
||||
|
||||
void operator()(const handle_type handle)
|
||||
{
|
||||
remove(handle);
|
||||
}
|
||||
|
||||
void remove(const handle_type handle)
|
||||
{
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
|
||||
auto i = static_cast<const handle_map_t&>(holder_).find(handle);
|
||||
if(holder_.cend() != i)
|
||||
{
|
||||
is_queue<std::is_same<cond_type, nana::null_type>::value, std::vector<handle_type> >::erase(handle, queue_);
|
||||
cacher_.insert(handle, false);
|
||||
trash_.push_back(*i);
|
||||
holder_.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void delete_trash(unsigned tid)
|
||||
{
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
|
||||
if(trash_.size())
|
||||
{
|
||||
deleter_type del_functor;
|
||||
if(tid == 0)
|
||||
{
|
||||
for(auto & m : trash_)
|
||||
del_functor(m.first);
|
||||
trash_.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto i = trash_.begin(), end = trash_.end(); i != end;)
|
||||
{
|
||||
if(tid == i->second)
|
||||
{
|
||||
del_functor(i->first);
|
||||
i = trash_.erase(i);
|
||||
end = trash_.end();
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle_type last() const
|
||||
{
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if(queue_.size())
|
||||
return queue_.back();
|
||||
return handle_type();
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return holder_.size();
|
||||
}
|
||||
|
||||
handle_type get(unsigned index) const
|
||||
{
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if(index < queue_.size())
|
||||
return queue_[index];
|
||||
return handle_type();
|
||||
}
|
||||
|
||||
bool available(const handle_type handle) const
|
||||
{
|
||||
if (nullptr == handle)
|
||||
return false;
|
||||
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
bool * v = cacher_.get(handle);
|
||||
if(v) return *v;
|
||||
return cacher_.insert(handle, (holder_.count(handle) != 0));
|
||||
}
|
||||
|
||||
void all(std::vector<handle_type> & v) const
|
||||
{
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
std::copy(queue_.cbegin(), queue_.cend(), std::back_inserter(v));
|
||||
}
|
||||
private:
|
||||
|
||||
template<bool IsQueueOperation, typename Container>
|
||||
struct is_queue
|
||||
{
|
||||
public:
|
||||
static void insert(handle_type handle, Container& queue)
|
||||
{
|
||||
if(cond_type::is_queue(handle))
|
||||
queue.push_back(handle);
|
||||
}
|
||||
|
||||
static void erase(handle_type handle, Container& queue)
|
||||
{
|
||||
if(cond_type::is_queue(handle))
|
||||
{
|
||||
for (auto i = queue.begin(); i != queue.end(); ++i)
|
||||
{
|
||||
if (handle == *i)
|
||||
{
|
||||
queue.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct is_queue<true, Container>
|
||||
{
|
||||
public:
|
||||
static void insert(handle_type handle, Container& queue){}
|
||||
static void erase(handle_type handle, Container& queue){}
|
||||
};
|
||||
|
||||
private:
|
||||
mutable std::recursive_mutex mutex_;
|
||||
mutable cache<const handle_type, bool, 5> cacher_;
|
||||
handle_map_t holder_;
|
||||
std::vector<handle_type> queue_;
|
||||
std::vector<holder_pair> trash_;
|
||||
};//end class handle_manager
|
||||
}//end namespace detail
|
||||
}// end namespace nana
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Widget Content Measurer Interface
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/detail/widget_content_measurer_interface.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_WIDGET_CONTENT_MEASURER_INTERFACE_HEADER_INCLUDED
|
||||
#define NANA_WIDGET_CONTENT_MEASURER_INTERFACE_HEADER_INCLUDED
|
||||
|
||||
#include <nana/basic_types.hpp>
|
||||
#include <nana/optional.hpp>
|
||||
#include <nana/paint/graphics.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace dev
|
||||
{
|
||||
/// An interface for measuring content of the widget
|
||||
class widget_content_measurer_interface
|
||||
{
|
||||
public:
|
||||
using graph_reference = paint::graphics&;
|
||||
virtual ~widget_content_measurer_interface() = default;
|
||||
|
||||
/// Measures content
|
||||
/**
|
||||
* @param graph The graphics for the operation.
|
||||
* @param limit_pixels The number of pixels of the limited edge. If this parameter is zero, it is ignored.
|
||||
* @param limit_width True if limits the width, false if limits the height.
|
||||
* @return the size of content.
|
||||
*/
|
||||
virtual optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const = 0;
|
||||
|
||||
/// Returns the extension to the size of widget from content extent
|
||||
/**
|
||||
* @return the width and height of extension to the widget size.
|
||||
*/
|
||||
virtual size extension() const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Window Layout Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -42,10 +42,16 @@ namespace detail
|
||||
core_window_t * window;
|
||||
rectangle r;
|
||||
};
|
||||
public:
|
||||
static void paint(core_window_t*, bool is_redraw, bool is_child_refreshed);
|
||||
|
||||
static bool maproot(core_window_t*, bool have_refreshed, bool is_child_refreshed);
|
||||
enum class paint_operation {
|
||||
none,
|
||||
have_refreshed,
|
||||
try_refresh
|
||||
};
|
||||
public:
|
||||
static void paint(core_window_t*, paint_operation, bool request_refresh_children);
|
||||
|
||||
static bool maproot(core_window_t*, bool have_refreshed, bool request_refresh_children);
|
||||
|
||||
static void paste_children_to_graphics(core_window_t*, nana::paint::graphics& graph);
|
||||
|
||||
@ -68,13 +74,12 @@ namespace detail
|
||||
|
||||
//_m_paste_children
|
||||
//@brief:paste children window to the root graphics directly. just paste the visual rectangle
|
||||
static void _m_paste_children(core_window_t*, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos);
|
||||
static void _m_paste_children(core_window_t*, bool have_refreshed, bool request_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos);
|
||||
|
||||
static void _m_paint_glass_window(core_window_t*, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other);
|
||||
|
||||
//_m_notify_glasses
|
||||
//@brief: Notify the glass windows that are overlapped with the specified vis_rect
|
||||
static void _m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& r_visual);
|
||||
//Notify the windows which have brground to update their background buffer.
|
||||
static void _m_notify_glasses(core_window_t* const sigwd);
|
||||
private:
|
||||
struct data_section
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Window Manager Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
||||
#include "window_layout.hpp"
|
||||
#include "event_code.hpp"
|
||||
#include "inner_fwd.hpp"
|
||||
#include <functional>
|
||||
@ -31,6 +30,7 @@ namespace nana
|
||||
namespace paint
|
||||
{
|
||||
class image;
|
||||
class graphics;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,12 +68,10 @@ namespace detail
|
||||
using mutex_type = revertible_mutex;
|
||||
|
||||
using core_window_t = basic_window;
|
||||
using window_layer = window_layout;
|
||||
|
||||
window_manager();
|
||||
~window_manager();
|
||||
|
||||
static bool is_queue(core_window_t*);
|
||||
std::size_t number_of_core_window() const;
|
||||
mutex_type & internal_lock() const;
|
||||
void all_handles(std::vector<core_window_t*>&) const;
|
||||
@ -103,12 +101,11 @@ namespace detail
|
||||
// Deletes a window whose category type is a root type or a frame type.
|
||||
void destroy_handle(core_window_t*);
|
||||
|
||||
void default_icon(const paint::image& _small_icon, const paint::image& big_icon);
|
||||
void icon(core_window_t*, const paint::image& small_icon, const paint::image& big_icon);
|
||||
|
||||
bool show(core_window_t* wd, bool visible);
|
||||
|
||||
core_window_t* find_window(native_window_type root, int x, int y);
|
||||
core_window_t* find_window(native_window_type root, const point& pos);
|
||||
|
||||
//move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window
|
||||
bool move(core_window_t*, int x, int y, bool passive);
|
||||
@ -124,7 +121,7 @@ namespace detail
|
||||
bool update(core_window_t*, bool redraw, bool force, const rectangle* update_area = nullptr);
|
||||
void refresh_tree(core_window_t*);
|
||||
|
||||
bool do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false);
|
||||
void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false);
|
||||
|
||||
bool get_graphics(core_window_t*, nana::paint::graphics&);
|
||||
bool get_visual_rectangle(core_window_t*, nana::rectangle&);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Filebox
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@ -22,6 +22,11 @@
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace paint
|
||||
{
|
||||
class graphics;
|
||||
}
|
||||
|
||||
class widget;
|
||||
namespace detail
|
||||
{
|
||||
@ -112,7 +117,10 @@ namespace nana
|
||||
void bind(window handle);
|
||||
window window_handle() const;
|
||||
|
||||
void div(const char* s); ///< Divides the attached widget into fields.
|
||||
void splitter_renderer(std::function<void(window, paint::graphics&, mouse_action)> fn);
|
||||
|
||||
void div(const char* s); ///< Divides the attached widget into fields.
|
||||
const std::string& div() const noexcept; ///< Returns div-text that depends on fields status.
|
||||
void modify(const char* field_name, const char* div_text); ///< Modifies a specified field.
|
||||
|
||||
field_reference field(const char* name);///< Returns a field with the specified name.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nana GUI Programming Interface Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -16,6 +16,7 @@
|
||||
#include "effects.hpp"
|
||||
#include "detail/general_events.hpp"
|
||||
#include "detail/color_schemes.hpp"
|
||||
#include "detail/widget_content_measurer_interface.hpp"
|
||||
#include <nana/paint/image.hpp>
|
||||
#include <memory>
|
||||
|
||||
@ -53,6 +54,8 @@ namespace API
|
||||
effects::edge_nimbus effects_edge_nimbus(window);
|
||||
|
||||
void effects_bground(window, const effects::bground_factory_interface&, double fade_rate);
|
||||
void effects_bground(std::initializer_list<window> wdgs, const effects::bground_factory_interface&, double fade_rate);
|
||||
|
||||
bground_mode effects_bground_mode(window);
|
||||
void effects_bground_remove(window);
|
||||
|
||||
@ -73,6 +76,9 @@ namespace API
|
||||
void set_scheme(window, widget_geometrics*);
|
||||
widget_geometrics* get_scheme(window);
|
||||
|
||||
/// Sets a content measurer
|
||||
void set_measurer(window, ::nana::dev::widget_content_measurer_interface*);
|
||||
|
||||
void attach_drawer(widget&, drawer_trigger&);
|
||||
::nana::detail::native_string_type window_caption(window) throw();
|
||||
void window_caption(window, ::nana::detail::native_string_type);
|
||||
@ -92,6 +98,9 @@ namespace API
|
||||
|
||||
void enable_space_click(window, bool enable);
|
||||
|
||||
bool copy_transparent_background(window, paint::graphics&);
|
||||
bool copy_transparent_background(window, const rectangle& src_r, paint::graphics&, const point& dst_pt);
|
||||
|
||||
/// Refreshs a widget surface
|
||||
/*
|
||||
* This function will copy the drawer surface into system window after the event process finished.
|
||||
@ -177,7 +186,7 @@ namespace API
|
||||
template<typename Widget=::nana::widget, typename EnumFunction>
|
||||
void enum_widgets(window wd, bool recursive, EnumFunction && fn)
|
||||
{
|
||||
static_assert(std::is_convertible<Widget, ::nana::widget>::value, "enum_widgets<Widget>: The specified Widget is not a widget type.");
|
||||
static_assert(std::is_convertible<typename std::decay<Widget>::type*, ::nana::widget*>::value, "enum_widgets<Widget>: The specified Widget is not a widget type.");
|
||||
|
||||
detail::enum_widgets_function<Widget, EnumFunction> enum_fn(static_cast<EnumFunction&&>(fn));
|
||||
enum_fn.enum_widgets(wd, recursive);
|
||||
@ -191,6 +200,8 @@ namespace API
|
||||
bool is_destroying(window); ///< Determines whether a window is destroying
|
||||
void enable_dropfiles(window, bool);
|
||||
|
||||
bool is_transparent_background(window);
|
||||
|
||||
/// \brief Retrieves the native window of a Nana.GUI window.
|
||||
///
|
||||
/// The native window type is platform-dependent. Under Microsoft Windows, a conversion can be employed between
|
||||
@ -288,7 +299,7 @@ namespace API
|
||||
* @param window_handle A handle to the window to be refreshed.
|
||||
*/
|
||||
void refresh_window(window window_handle);
|
||||
void refresh_window_tree(window); ///< Refreshs the specified window and all it’s children windows, then display it immediately
|
||||
void refresh_window_tree(window); ///< Refreshes the specified window and all its children windows, then display it immediately
|
||||
void update_window(window); ///< Copies the off-screen buffer to the screen for immediate display.
|
||||
|
||||
void window_caption(window, const std::string& title_utf8);
|
||||
@ -399,6 +410,17 @@ namespace API
|
||||
bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled
|
||||
|
||||
void at_safe_place(window, std::function<void()>);
|
||||
|
||||
/// Returns a widget content extent size
|
||||
/**
|
||||
* @param wd A handle to a window that returns its content extent size.
|
||||
* @param limited_px Specifies the max pixels of width or height. If this parameter is zero, this parameter will be ignored.
|
||||
* @param limit_width Indicates whether the it limits the width or height. If this parameter is *true*, the width is limited.
|
||||
* If the parameter is *false*, the height is limited. This parameter is ignored if limited_px = 0.
|
||||
* @return if optional has a value, the first size indicates the content extent, the second size indicates the size of
|
||||
* widget by the content extent.
|
||||
*/
|
||||
optional<std::pair<::nana::size, ::nana::size>> content_extent(window wd, unsigned limited_px, bool limit_width);
|
||||
}//end namespace API
|
||||
|
||||
}//end namespace nana
|
||||
|
||||
@ -62,7 +62,7 @@ namespace nana
|
||||
_m_hold_factory(new factory<TooltipWindow>);
|
||||
}
|
||||
|
||||
tooltip(){}
|
||||
tooltip() = default;
|
||||
tooltip(window w, const ::std::string &tip){set(w,tip);}
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Button Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -25,6 +25,7 @@ namespace nana{
|
||||
/// Draw the button
|
||||
class trigger: public drawer_trigger
|
||||
{
|
||||
class measurer;
|
||||
public:
|
||||
trigger();
|
||||
~trigger();
|
||||
@ -58,6 +59,8 @@ namespace nana{
|
||||
|
||||
element::cite_bground cite_{"button"};
|
||||
|
||||
std::unique_ptr<measurer> measurer_;
|
||||
|
||||
struct attr_tag
|
||||
{
|
||||
element_state e_state;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Categorize Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -68,7 +68,7 @@ namespace nana
|
||||
void key_press(graph_reference, const arg_keyboard&) override;
|
||||
void key_char(graph_reference, const arg_keyboard&) override;
|
||||
private:
|
||||
drawer_impl * drawer_;
|
||||
drawer_impl * const drawer_;
|
||||
};
|
||||
|
||||
class item_proxy
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Tree Container class implementation
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -58,6 +58,31 @@ namespace detail
|
||||
t = t_next;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_ancestor_of(const tree_node* child) const
|
||||
{
|
||||
while (child)
|
||||
{
|
||||
if (child->owner == this)
|
||||
return true;
|
||||
|
||||
child = child->owner;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
tree_node * front() const
|
||||
{
|
||||
if (this->owner && (this != this->owner->child))
|
||||
{
|
||||
auto i = this->owner->child;
|
||||
while (i->next != this)
|
||||
i = i->next;
|
||||
|
||||
return i;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename UserData>
|
||||
@ -76,12 +101,17 @@ namespace detail
|
||||
|
||||
~tree_cont()
|
||||
{
|
||||
clear();
|
||||
clear(&root_);
|
||||
}
|
||||
|
||||
void clear()
|
||||
void clear(node_type* node)
|
||||
{
|
||||
remove(root_.child);
|
||||
while (node->child)
|
||||
{
|
||||
//If there is a sibling of child, the root_.child
|
||||
//will be assigned with the sibling.
|
||||
remove(node->child);
|
||||
}
|
||||
}
|
||||
|
||||
bool verify(const node_type* node) const
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Label Control Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -31,11 +31,11 @@ namespace nana
|
||||
class trigger: public drawer_trigger
|
||||
{
|
||||
public:
|
||||
struct impl_t;
|
||||
struct implement;
|
||||
|
||||
trigger();
|
||||
~trigger();
|
||||
impl_t * impl() const;
|
||||
implement * impl() const;
|
||||
private:
|
||||
void attached(widget_reference, graph_reference) override;
|
||||
void refresh(graph_reference) override;
|
||||
@ -43,7 +43,7 @@ namespace nana
|
||||
void mouse_leave(graph_reference, const arg_mouse&) override;
|
||||
void click(graph_reference, const arg_click&) override;
|
||||
private:
|
||||
impl_t * impl_;
|
||||
implement * impl_;
|
||||
};
|
||||
|
||||
}//end namespace label
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A List Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -14,6 +14,7 @@
|
||||
* leobackes(pr#86,pr#97)
|
||||
* Benjamin Navarro(pr#81)
|
||||
* besh81(pr#130)
|
||||
* dankan1890(pr#158)
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGETS_LISTBOX_HPP
|
||||
@ -38,6 +39,9 @@ namespace nana
|
||||
{
|
||||
namespace listbox
|
||||
{
|
||||
using size_type = std::size_t;
|
||||
using native_string_type = ::nana::detail::native_string_type;
|
||||
|
||||
/// An interface of column operations
|
||||
class column_interface
|
||||
{
|
||||
@ -61,6 +65,22 @@ namespace nana
|
||||
*/
|
||||
virtual void width(unsigned minimum, unsigned maximum) = 0;
|
||||
|
||||
/// Returns the position of the column
|
||||
/**
|
||||
* @param disp_order Indicates whether the display position or absolute position to be returned
|
||||
* @return the position of the column.
|
||||
*/
|
||||
virtual size_type position(bool disp_order) const noexcept = 0;
|
||||
|
||||
/// Returns the caption of column
|
||||
virtual std::string text() const noexcept = 0;
|
||||
|
||||
/// Sets the caption of column
|
||||
/**
|
||||
* @param text_utf8 A UTF-8 string for the caption.
|
||||
*/
|
||||
virtual void text(std::string text_utf8) = 0;
|
||||
|
||||
/// Sets alignment of column text
|
||||
/**
|
||||
* @param align Alignment
|
||||
@ -92,7 +112,7 @@ namespace nana
|
||||
struct intern
|
||||
{
|
||||
public:
|
||||
virtual ~intern() = default;
|
||||
virtual ~intern() noexcept = default;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -101,7 +121,7 @@ namespace nana
|
||||
{
|
||||
const T * ptr;
|
||||
|
||||
real_pointer(const T* p)
|
||||
real_pointer(const T* p) noexcept
|
||||
: ptr(p)
|
||||
{}
|
||||
};
|
||||
@ -118,13 +138,13 @@ namespace nana
|
||||
{
|
||||
}
|
||||
|
||||
~const_virtual_pointer()
|
||||
~const_virtual_pointer() noexcept
|
||||
{
|
||||
delete intern_;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
const typename std::remove_const<Type>::type *get() const
|
||||
const typename std::remove_const<Type>::type *get() const noexcept
|
||||
{
|
||||
using value_type = typename std::remove_const<Type>::type;
|
||||
auto target = dynamic_cast<real_pointer<value_type>*>(intern_);
|
||||
@ -141,8 +161,8 @@ namespace nana
|
||||
::nana::color bgcolor;
|
||||
::nana::color fgcolor;
|
||||
|
||||
format() = default;
|
||||
format(const ::nana::color& bgcolor, const ::nana::color& fgcolor);
|
||||
format() noexcept = default;
|
||||
format(const ::nana::color& bgcolor, const ::nana::color& fgcolor) noexcept;
|
||||
};
|
||||
|
||||
using format_ptr = ::std::unique_ptr<format>;
|
||||
@ -152,13 +172,12 @@ namespace nana
|
||||
|
||||
cell() = default;
|
||||
cell(const cell&);
|
||||
cell(cell&&);
|
||||
cell(::std::string);
|
||||
cell(cell&&) noexcept;
|
||||
cell(::std::string) noexcept;
|
||||
cell(::std::string, const format&);
|
||||
cell(::std::string, const ::nana::color& bgcolor, const ::nana::color& fgcolor);
|
||||
|
||||
cell& operator=(const cell&);
|
||||
cell& operator=(cell&&);
|
||||
cell& operator=(cell&&) noexcept;
|
||||
};
|
||||
|
||||
class container_interface
|
||||
@ -167,7 +186,7 @@ namespace nana
|
||||
public:
|
||||
virtual ~container_interface() = default;
|
||||
|
||||
virtual void clear() = 0;
|
||||
virtual void clear() noexcept = 0;
|
||||
virtual void erase(std::size_t pos) = 0;
|
||||
|
||||
virtual std::size_t size() const = 0;
|
||||
@ -219,7 +238,7 @@ namespace nana
|
||||
translator_({ vtrans, ctrans })
|
||||
{}
|
||||
private:
|
||||
void clear() override
|
||||
void clear() noexcept override
|
||||
{
|
||||
container_.clear();
|
||||
}
|
||||
@ -308,7 +327,7 @@ namespace nana
|
||||
|
||||
}
|
||||
private:
|
||||
void clear() override
|
||||
void clear() noexcept override
|
||||
{
|
||||
container_.clear();
|
||||
}
|
||||
@ -462,8 +481,8 @@ namespace nana
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
|
||||
virtual container_interface* container() = 0;
|
||||
virtual const container_interface* container() const = 0;
|
||||
virtual container_interface* container() noexcept = 0;
|
||||
virtual const container_interface* container() const noexcept = 0;
|
||||
};
|
||||
|
||||
class model_guard
|
||||
@ -568,12 +587,12 @@ namespace nana
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
container_interface* container() override
|
||||
container_interface* container() noexcept override
|
||||
{
|
||||
return &container_;
|
||||
}
|
||||
|
||||
const container_interface* container() const override
|
||||
const container_interface* container() const noexcept override
|
||||
{
|
||||
return &container_;
|
||||
}
|
||||
@ -610,12 +629,12 @@ namespace nana
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
container_interface* container() override
|
||||
container_interface* container() noexcept override
|
||||
{
|
||||
return container_ptr_.get();
|
||||
}
|
||||
|
||||
const container_interface* container() const override
|
||||
const container_interface* container() const noexcept override
|
||||
{
|
||||
return container_ptr_.get();
|
||||
}
|
||||
@ -624,53 +643,52 @@ namespace nana
|
||||
std::unique_ptr<container_interface> container_ptr_;
|
||||
};
|
||||
|
||||
using size_type = std::size_t;
|
||||
using native_string_type = ::nana::detail::native_string_type;
|
||||
|
||||
/// usefull for both absolute and display (sorted) positions
|
||||
struct index_pair
|
||||
{
|
||||
constexpr static const size_type npos = ::nana::npos;
|
||||
|
||||
size_type cat; //The pos of category
|
||||
size_type item; //the pos of item in a category.
|
||||
|
||||
explicit index_pair(size_type cat_pos = 0, size_type item_pos = 0)
|
||||
: cat(cat_pos),
|
||||
item(item_pos)
|
||||
explicit index_pair(size_type cat_pos = 0, size_type item_pos = 0) noexcept
|
||||
: cat(cat_pos), item(item_pos)
|
||||
{}
|
||||
|
||||
bool empty() const
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return (npos == cat);
|
||||
}
|
||||
|
||||
void set_both(size_type n)
|
||||
void set_both(size_type n) noexcept
|
||||
{
|
||||
cat = item = n;
|
||||
}
|
||||
|
||||
bool is_category() const
|
||||
bool is_category() const noexcept
|
||||
{
|
||||
return (npos != cat && npos == item);
|
||||
}
|
||||
|
||||
bool is_item() const
|
||||
{
|
||||
return (npos != cat && npos != item);
|
||||
}
|
||||
|
||||
bool operator==(const index_pair& r) const
|
||||
bool operator==(const index_pair& r) const noexcept
|
||||
{
|
||||
return (r.cat == cat && r.item == item);
|
||||
}
|
||||
|
||||
bool operator!=(const index_pair& r) const
|
||||
bool operator!=(const index_pair& r) const noexcept
|
||||
{
|
||||
return !this->operator==(r);
|
||||
}
|
||||
|
||||
bool operator>(const index_pair& r) const
|
||||
bool operator<(const index_pair& r) const noexcept
|
||||
{
|
||||
return (cat > r.cat) || (cat == r.cat && item > r.item);
|
||||
return (cat < r.cat) || ((cat == r.cat) && (r.item != npos) && ((item == npos) || (item < r.item)));
|
||||
}
|
||||
|
||||
bool operator>(const index_pair& r) const noexcept
|
||||
{
|
||||
return (cat > r.cat) || ((cat == r.cat) && (item != npos) && ((r.item == npos) || (item > r.item)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -693,7 +711,7 @@ namespace nana
|
||||
class oresolver
|
||||
{
|
||||
public:
|
||||
oresolver(essence*);
|
||||
oresolver(essence*) noexcept;
|
||||
oresolver& operator<<(bool);
|
||||
oresolver& operator<<(short);
|
||||
oresolver& operator<<(unsigned short);
|
||||
@ -715,9 +733,9 @@ namespace nana
|
||||
oresolver& operator<<(cell);
|
||||
oresolver& operator<<(std::nullptr_t);
|
||||
|
||||
std::vector<cell> && move_cells();
|
||||
std::vector<cell> && move_cells() noexcept;
|
||||
|
||||
::nana::listbox& listbox();
|
||||
::nana::listbox& listbox() noexcept;
|
||||
private:
|
||||
essence* const ess_;
|
||||
std::vector<cell> cells_;
|
||||
@ -726,7 +744,7 @@ namespace nana
|
||||
class iresolver
|
||||
{
|
||||
public:
|
||||
iresolver(std::vector<cell>);
|
||||
iresolver(std::vector<cell>) noexcept;
|
||||
|
||||
iresolver& operator>>(bool&);
|
||||
iresolver& operator>>(short&);
|
||||
@ -744,7 +762,7 @@ namespace nana
|
||||
iresolver& operator>>(std::string& text_utf8);
|
||||
iresolver& operator>>(std::wstring&);
|
||||
iresolver& operator>>(cell&);
|
||||
iresolver& operator>>(std::nullptr_t);
|
||||
iresolver& operator>>(std::nullptr_t) noexcept;
|
||||
private:
|
||||
std::vector<cell> cells_;
|
||||
std::size_t pos_{0};
|
||||
@ -761,9 +779,7 @@ namespace nana
|
||||
public:
|
||||
trigger();
|
||||
~trigger();
|
||||
essence& ess() const;
|
||||
private:
|
||||
void _m_draw_border();
|
||||
essence& ess() const noexcept;
|
||||
private:
|
||||
void attached(widget_reference, graph_reference) override;
|
||||
void detached() override;
|
||||
@ -773,7 +789,6 @@ namespace nana
|
||||
void mouse_leave(graph_reference, const arg_mouse&) override;
|
||||
void mouse_down(graph_reference, const arg_mouse&) override;
|
||||
void mouse_up(graph_reference, const arg_mouse&) override;
|
||||
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
||||
void dbl_click(graph_reference, const arg_mouse&) override;
|
||||
void resized(graph_reference, const arg_resized&) override;
|
||||
void key_press(graph_reference, const arg_keyboard&) override;
|
||||
@ -790,8 +805,7 @@ namespace nana
|
||||
: public std::iterator<std::input_iterator_tag, item_proxy>
|
||||
{
|
||||
public:
|
||||
item_proxy(essence*);
|
||||
item_proxy(essence*, const index_pair&);
|
||||
item_proxy(essence*, const index_pair& = index_pair{npos, npos});
|
||||
|
||||
/// 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 *, const index_pair &relative) ;
|
||||
@ -800,12 +814,31 @@ namespace nana
|
||||
/// 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;
|
||||
/// Determines whether the item is displayed on the screen
|
||||
bool displayed() const;
|
||||
|
||||
item_proxy & check(bool ck);
|
||||
bool empty() const noexcept;
|
||||
|
||||
/// Checks/unchecks the item
|
||||
/**
|
||||
* @param chk Indicates whether to check or uncheck the item
|
||||
* @param scroll_view Indicates whether to scroll the view to the item. It is ignored if the item is displayed.
|
||||
* @return the reference of *this.
|
||||
*/
|
||||
item_proxy & check(bool chk, bool scroll_view = false);
|
||||
|
||||
/// Determines whether the item is checked
|
||||
bool checked() const;
|
||||
|
||||
item_proxy & select(bool);
|
||||
/// Selects/unselects the item
|
||||
/**
|
||||
* @param sel Indicates whether to select or unselect the item
|
||||
* @param scroll_view Indicates whether to scroll the view to the item. It is ignored if the item is displayed.
|
||||
* @return the reference of *this.
|
||||
*/
|
||||
item_proxy & select(bool sel, bool scroll_view = false);
|
||||
|
||||
/// Determines whether he item is selected
|
||||
bool selected() const;
|
||||
|
||||
item_proxy & bgcolor(const nana::color&);
|
||||
@ -814,14 +847,22 @@ namespace nana
|
||||
item_proxy& fgcolor(const nana::color&);
|
||||
nana::color fgcolor() const;
|
||||
|
||||
index_pair pos() const;
|
||||
index_pair pos() const noexcept;
|
||||
|
||||
size_type columns() const;
|
||||
size_type columns() const noexcept;
|
||||
|
||||
item_proxy& text(size_type col, cell);
|
||||
item_proxy& text(size_type col, std::string);
|
||||
item_proxy& text(size_type col, const std::wstring&);
|
||||
std::string text(size_type col) const;
|
||||
/// Converts a position of column between display position and absolute position
|
||||
/**
|
||||
* @param col The display position or absolute position.
|
||||
* @param disp_order Indicates whether the col is a display position or absolute position. If this parameter is true, the col is display position
|
||||
* @return absolute position if disp_order is false, display position otherwise.
|
||||
*/
|
||||
size_type column_cast(size_type col, bool disp_order) const;
|
||||
|
||||
item_proxy& text(size_type abs_col, cell);
|
||||
item_proxy& text(size_type abs_col, std::string);
|
||||
item_proxy& text(size_type abs_col, const std::wstring&);
|
||||
std::string text(size_type abs_col) const;
|
||||
|
||||
void icon(const nana::paint::image&);
|
||||
|
||||
@ -922,7 +963,7 @@ namespace nana
|
||||
bool operator!=(const item_proxy&) const;
|
||||
|
||||
//Undocumented method
|
||||
essence * _m_ess() const;
|
||||
essence * _m_ess() const noexcept;
|
||||
private:
|
||||
std::vector<cell> _m_cells() const;
|
||||
nana::any * _m_value(bool alloc_if_empty);
|
||||
@ -942,9 +983,9 @@ namespace nana
|
||||
template<typename Value> using value_translator = typename container_translator<Value>::value_translator;
|
||||
template<typename Value> using cell_translator = typename container_translator<Value>::cell_translator;
|
||||
|
||||
cat_proxy() = default;
|
||||
cat_proxy(essence*, size_type pos);
|
||||
cat_proxy(essence*, category_t*);
|
||||
cat_proxy() noexcept = default;
|
||||
cat_proxy(essence*, size_type pos) noexcept;
|
||||
cat_proxy(essence*, category_t*) noexcept;
|
||||
|
||||
/// Append an item at abs end of the category, set_value determines whether assign T object to the value of item.
|
||||
template<typename T>
|
||||
@ -1022,12 +1063,14 @@ namespace nana
|
||||
item_proxy at(size_type pos_abs) const;
|
||||
item_proxy back() const;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// 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;
|
||||
/// Converts the index between absolute position and display position
|
||||
/**
|
||||
* @param from The index to be converted
|
||||
* @param from_display_order If this parameter is true, the method converts a display position to an absolute position.
|
||||
* If the parameter is false, the method converts an absolute position to a display position.
|
||||
* @return a display position or an absolute position that are depending on from_display_order.
|
||||
*/
|
||||
size_type index_cast(size_type from, bool from_display_order) const;
|
||||
|
||||
/// this cat position
|
||||
size_type position() const;
|
||||
@ -1066,8 +1109,8 @@ namespace nana
|
||||
private:
|
||||
void _m_append(std::vector<cell> && cells);
|
||||
void _m_try_append_model(const const_virtual_pointer&);
|
||||
void _m_cat_by_pos();
|
||||
void _m_update();
|
||||
void _m_cat_by_pos() noexcept;
|
||||
void _m_update() noexcept;
|
||||
void _m_reset_model(model_interface*);
|
||||
private:
|
||||
essence* ess_{nullptr};
|
||||
@ -1130,9 +1173,13 @@ namespace nana
|
||||
: public widget_geometrics
|
||||
{
|
||||
color_proxy header_bgcolor{static_cast<color_rgb>(0xf1f2f4)};
|
||||
color_proxy header_fgcolor{ colors::black };
|
||||
color_proxy header_grabbed{ static_cast<color_rgb>(0x8BD6F6)};
|
||||
color_proxy header_floated{ static_cast<color_rgb>(0xBABBBC)};
|
||||
color_proxy item_selected{ static_cast<color_rgb>(0xD5EFFC) };
|
||||
color_proxy item_selected{ static_cast<color_rgb>(0xCCE8FF) };
|
||||
color_proxy item_highlighted{ static_cast<color_rgb>(0xE5F3FF) };
|
||||
|
||||
color_proxy selection_box{ static_cast<color_rgb>(0x3399FF) }; ///< Color of selection box border.
|
||||
|
||||
/// The max column width which is generated by fit_content is allowed. It is ignored when it is 0, or a max value is passed to fit_content.
|
||||
unsigned max_fit_content{ 0 };
|
||||
@ -1142,9 +1189,7 @@ namespace nana
|
||||
unsigned suspension_width { 8 }; ///< def= . the trigger will set this to the width if ("...")
|
||||
unsigned text_margin { 5 }; ///< def= 5. Additional or extended with added (before) to the text width to determine the cell width. cell_w = text_w + ext_w +1
|
||||
unsigned header_height { 25 }; ///< def=25 . header height header_size
|
||||
unsigned text_height { 14 }; ///< the trigger will set this to the height of the text font
|
||||
unsigned item_height_ex { 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex
|
||||
unsigned item_height { 24 }; ///< def=24 . the trigger will set this TO item_height = text_height + item_height_ex
|
||||
unsigned header_splitter_area_before{ 2 }; ///< def=2. But 4 is better... IMO
|
||||
unsigned header_splitter_area_after { 3 }; ///< def=3. But 4 is better...
|
||||
|
||||
@ -1324,7 +1369,7 @@ the nana::detail::basic_window member pointer scheme
|
||||
bool assoc_ordered(bool);
|
||||
|
||||
|
||||
void auto_draw(bool); ///< Set state: Redraw automatically after an operation
|
||||
void auto_draw(bool) noexcept; ///< Set state: Redraw automatically after an operation
|
||||
|
||||
template<typename Function>
|
||||
void avoid_drawing(Function fn)
|
||||
@ -1353,26 +1398,28 @@ the nana::detail::basic_window member pointer scheme
|
||||
/// Access a column at specified position
|
||||
/**
|
||||
* @param pos Position of column
|
||||
* @param disp_order Indicates whether the pos is display position or absolute position.
|
||||
* @return Reference to the requested column
|
||||
* @except std::out_of_range if !(pos < columns())
|
||||
*/
|
||||
column_interface & column_at(size_type pos);
|
||||
column_interface & column_at(size_type pos, bool disp_order = false);
|
||||
|
||||
/// Access a column at specified position
|
||||
/**
|
||||
* @param pos Position of column
|
||||
* @param disp_order Indicates whether the pos is display position or absolute position.
|
||||
* @return Constant reference to the requested column
|
||||
* @except std::out_of_range if !(pos < columns())
|
||||
*/
|
||||
const column_interface & column_at(size_type pos) const;
|
||||
const column_interface & column_at(size_type pos, bool disp_order = false) const;
|
||||
|
||||
/// Returns the number of columns
|
||||
size_type column_size() const;
|
||||
|
||||
cat_proxy append(std::string); ///< Appends a new category to the end
|
||||
cat_proxy append(std::wstring); ///< Appends a new category to the end
|
||||
void append(std::initializer_list<std::string>); ///< Appends categories to the end
|
||||
void append(std::initializer_list<std::wstring>); ///< Appends categories to the end
|
||||
cat_proxy append(std::string category); ///< Appends a new category to the end
|
||||
cat_proxy append(std::wstring category); ///< Appends a new category to the end
|
||||
void append(std::initializer_list<std::string> categories); ///< Appends categories to the end
|
||||
void append(std::initializer_list<std::wstring> categories); ///< Appends categories to the end
|
||||
|
||||
cat_proxy insert(cat_proxy, ::std::string);
|
||||
cat_proxy insert(cat_proxy, ::std::wstring);
|
||||
@ -1392,18 +1439,19 @@ the nana::detail::basic_window member pointer scheme
|
||||
void insert_item(const index_pair& abs_pos, const ::std::wstring& text);
|
||||
|
||||
/// Returns an index of item which contains the specified point.
|
||||
index_pair cast(const point & pos) const;
|
||||
index_pair cast(const point & screen_pos) const;
|
||||
|
||||
/// Returns the column which contains the specified point.
|
||||
size_type column_from_pos(const point & pos);
|
||||
/// Returns the absolute position of column which contains the specified point.
|
||||
size_type column_from_pos(const point & pos) const;
|
||||
|
||||
void checkable(bool);
|
||||
index_pairs checked() const; ///<Returns the items which are checked.
|
||||
|
||||
void clear(size_type cat); ///<Removes all the items from the specified category
|
||||
void clear(); ///<Removes all the items from all categories
|
||||
void erase(size_type cat); ///<Erases a category
|
||||
void erase(); ///<Erases all categories.
|
||||
void clear(size_type cat); ///<Removes all the items from the specified category
|
||||
void clear(); ///<Removes all the items from all categories
|
||||
void erase(size_type cat); ///<Erases a category
|
||||
void erase(); ///<Erases all categories.
|
||||
void erase(index_pairs indexes); ///<Erases specified items.
|
||||
item_proxy erase(item_proxy);
|
||||
|
||||
bool sortable() const;
|
||||
@ -1435,9 +1483,9 @@ the nana::detail::basic_window member pointer scheme
|
||||
export_options& def_export_options();
|
||||
private:
|
||||
drawerbase::listbox::essence & _m_ess() const;
|
||||
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const;
|
||||
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const override;
|
||||
drawerbase::listbox::category_t* _m_assoc(std::shared_ptr<nana::detail::key_interface>, bool create_if_not_exists);
|
||||
void _m_erase_key(nana::detail::key_interface*);
|
||||
void _m_erase_key(nana::detail::key_interface*) noexcept;
|
||||
};
|
||||
}//end namespace nana
|
||||
|
||||
|
||||
@ -1,22 +1,20 @@
|
||||
/**
|
||||
* A Menu implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/menu.hpp
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGETS_MENU_HPP
|
||||
#define NANA_GUI_WIDGETS_MENU_HPP
|
||||
#include "widget.hpp"
|
||||
#include <vector>
|
||||
#include <nana/gui/timer.hpp>
|
||||
#include <nana/pat/cloneable.hpp>
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
||||
namespace nana
|
||||
@ -50,6 +48,8 @@ namespace nana
|
||||
item_proxy& checked(bool);
|
||||
bool checked() const;
|
||||
|
||||
std::string text() const;
|
||||
|
||||
std::size_t index() const;
|
||||
private:
|
||||
std::size_t index_;
|
||||
@ -71,25 +71,12 @@ namespace nana
|
||||
|
||||
menu_type *sub_menu{nullptr};
|
||||
std::string text;
|
||||
event_fn_t functor;
|
||||
event_fn_t event_handler;
|
||||
checks style{checks::none};
|
||||
paint::image image;
|
||||
mutable wchar_t hotkey{0};
|
||||
};
|
||||
|
||||
struct menu_type
|
||||
{
|
||||
typedef std::vector<menu_item_type> item_container;
|
||||
typedef item_container::iterator iterator;
|
||||
typedef item_container::const_iterator const_iterator;
|
||||
|
||||
std::vector<menu_type*> owner;
|
||||
std::vector<menu_item_type> items;
|
||||
unsigned max_pixels;
|
||||
unsigned item_pixels;
|
||||
nana::point gaps;
|
||||
};
|
||||
|
||||
class renderer_interface
|
||||
{
|
||||
public:
|
||||
@ -138,12 +125,24 @@ namespace nana
|
||||
~menu();
|
||||
|
||||
/// Appends an item to the menu.
|
||||
item_proxy append(const std::string& text, const event_fn_t& callback= event_fn_t());
|
||||
item_proxy append(std::string text_utf8, const event_fn_t& handler = {});
|
||||
void append_splitter();
|
||||
|
||||
/// Inserts new item at specified position
|
||||
/**
|
||||
* It will invalidate the existing item proxies from the specified position.
|
||||
* @param pos The position where new item to be inserted
|
||||
* @param text_utf8 The title of item
|
||||
* @param handler The event handler for the item.
|
||||
* @return the item proxy to the new inserted item.
|
||||
*/
|
||||
item_proxy insert(std::size_t pos, std::string text_utf8, const event_fn_t& handler = {});
|
||||
|
||||
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 pos, const paint::image& icon);
|
||||
void text(std::size_t pos, std::string text_utf8);
|
||||
void check_style(std::size_t pos, checks);
|
||||
void checked(std::size_t pos, bool);
|
||||
bool checked(std::size_t pos) const;
|
||||
@ -156,7 +155,7 @@ namespace nana
|
||||
void popup(window owner, int x, int y); ///< Popup the menu at the owner window.
|
||||
void popup_await(window owner, int x, int y);
|
||||
void answerer(std::size_t index, const event_fn_t&); ///< Modify answerer of the specified item.
|
||||
void destroy_answer(const std::function<void()>&); ///< Sets an answerer for the callback while the menu window is closing.
|
||||
void destroy_answer(std::function<void()>); ///< Sets an answerer for the callback while the menu window is closing.
|
||||
void gaps(const nana::point&); ///< Sets the gap between a menu and its sub menus.(\See Note4)
|
||||
void goto_next(bool forward); ///< Moves the focus to the next or previous item.
|
||||
bool goto_submen();///< Popup the submenu of the current item if it has a sub menu. Returns true if succeeds.
|
||||
@ -175,7 +174,7 @@ namespace nana
|
||||
const pat::cloneable<renderer_interface>& renderer() const;
|
||||
|
||||
private:
|
||||
void _m_popup(window, int x, int y, bool called_by_menubar);
|
||||
void _m_popup(window, const point& position, bool called_by_menubar);
|
||||
private:
|
||||
implement * impl_;
|
||||
};
|
||||
|
||||
@ -24,6 +24,16 @@ namespace nana
|
||||
{
|
||||
using native_string_type = ::nana::detail::native_string_type;
|
||||
|
||||
struct scheme
|
||||
: public widget_geometrics
|
||||
{
|
||||
color_proxy text_fgcolor{ colors::black };
|
||||
color_proxy body_highlight{ static_cast<color_rgb>(0xc0ddfc) };
|
||||
color_proxy body_selected{ colors::white };
|
||||
color_proxy border_selected{ colors::dark_border };
|
||||
color_proxy border_highlight{ colors::highlight };
|
||||
};
|
||||
|
||||
class item_renderer
|
||||
{
|
||||
public:
|
||||
@ -33,13 +43,16 @@ namespace nana
|
||||
};
|
||||
|
||||
using graph_reference = paint::graphics&;
|
||||
using scheme = ::nana::drawerbase::menubar::scheme;
|
||||
|
||||
item_renderer(window, graph_reference);
|
||||
virtual void background(const point&, const ::nana::size&, state);
|
||||
virtual void caption(const point&, const native_string_type&);
|
||||
scheme *scheme_ptr() const { return scheme_ptr_; };
|
||||
private:
|
||||
window handle_;
|
||||
graph_reference graph_;
|
||||
scheme *scheme_ptr_;
|
||||
};
|
||||
|
||||
class trigger
|
||||
@ -72,7 +85,7 @@ namespace nana
|
||||
bool _m_track_mouse(const ::nana::point&);
|
||||
private:
|
||||
widget *widget_;
|
||||
nana::paint::graphics *graph_;
|
||||
paint::graphics *graph_;
|
||||
|
||||
itembase* items_;
|
||||
|
||||
@ -104,7 +117,7 @@ namespace nana
|
||||
///
|
||||
/// The widget sets as shortkey the character behind the first of & in the text, for the item. e.g. "File(&F)" or "&File".
|
||||
class menubar
|
||||
: public widget_object<category::widget_tag, drawerbase::menubar::trigger>
|
||||
: public widget_object<category::widget_tag, drawerbase::menubar::trigger, ::nana::general_events, drawerbase::menubar::scheme>
|
||||
{
|
||||
public:
|
||||
menubar() = default; ///< The default constructor delay creation.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Panel Implementation
|
||||
* Nana C++ Library(http://www.nanaro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -57,7 +57,7 @@ namespace nana
|
||||
|
||||
bool transparent() const
|
||||
{
|
||||
return (bground_mode::basic == API::effects_bground_mode(*this));
|
||||
return API::is_transparent_background(*this);
|
||||
}
|
||||
|
||||
void transparent(bool tr)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Picture Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@ -122,7 +122,9 @@ namespace nana
|
||||
|
||||
void value(size_type s)
|
||||
{
|
||||
if (s + metrics_.range > metrics_.peak)
|
||||
if (metrics_.range > metrics_.peak)
|
||||
s = 0;
|
||||
else if (s + metrics_.range > metrics_.peak)
|
||||
s = metrics_.peak - metrics_.range;
|
||||
|
||||
if (graph_ && (metrics_.value != s))
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A text editor implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -19,7 +19,6 @@
|
||||
#include "text_editor_part.hpp"
|
||||
#include <nana/unicode_bidi.hpp>
|
||||
|
||||
//#include <nana/paint/graphics.hpp>
|
||||
#include <nana/gui/detail/general_events.hpp>
|
||||
|
||||
#include <functional>
|
||||
@ -56,6 +55,8 @@ namespace nana{ namespace widgets
|
||||
class keyword_parser;
|
||||
class helper_pencil;
|
||||
|
||||
struct text_section;
|
||||
|
||||
text_editor(const text_editor&) = delete;
|
||||
text_editor& operator=(const text_editor&) = delete;
|
||||
|
||||
@ -89,6 +90,8 @@ namespace nana{ namespace widgets
|
||||
void set_keyword(const ::std::wstring& kw, const std::string& name, bool case_sensitive, bool whole_word_matched);
|
||||
void erase_keyword(const ::std::wstring& kw);
|
||||
|
||||
colored_area_access_interface& colored_area();
|
||||
|
||||
void set_accept(std::function<bool(char_type)>);
|
||||
void set_accept(accepts);
|
||||
bool respond_char(const arg_keyboard& arg);
|
||||
@ -99,14 +102,10 @@ namespace nana{ namespace widgets
|
||||
void indent(bool, std::function<std::string()> generator);
|
||||
void set_event(event_interface*);
|
||||
|
||||
/// Determine whether the text_editor is line wrapped.
|
||||
bool line_wrapped() const;
|
||||
|
||||
/// Set the text_editor whether it is line wrapped, it returns false if the state is not changed.
|
||||
bool line_wrapped(bool);
|
||||
|
||||
bool load(const char*);
|
||||
|
||||
void text_align(::nana::align alignment);
|
||||
|
||||
/// Sets the text area.
|
||||
/// @return true if the area is changed with the new value.
|
||||
bool text_area(const nana::rectangle&);
|
||||
@ -116,7 +115,12 @@ namespace nana{ namespace widgets
|
||||
|
||||
bool tip_string(::std::string&&);
|
||||
|
||||
const attributes & attr() const;
|
||||
/// Returns the reference of listbox attributes
|
||||
const attributes & attr() const noexcept;
|
||||
|
||||
/// Set the text_editor whether it is line wrapped, it returns false if the state is not changed.
|
||||
bool line_wrapped(bool);
|
||||
|
||||
bool multi_lines(bool);
|
||||
|
||||
/// Enables/disables the editability of text_editor
|
||||
@ -134,9 +138,10 @@ namespace nana{ namespace widgets
|
||||
std::size_t undo_max_steps() const;
|
||||
|
||||
renderers& customized_renderers();
|
||||
void clear_undo(); ///< same with undo_max_steps(0)
|
||||
|
||||
unsigned line_height() const;
|
||||
unsigned screen_lines() const;
|
||||
unsigned screen_lines(bool completed_line = false) const;
|
||||
|
||||
bool getline(std::size_t pos, ::std::wstring&) const;
|
||||
void text(std::wstring, bool end_caret);
|
||||
@ -148,17 +153,18 @@ namespace nana{ namespace widgets
|
||||
* @param reset indicates whether to reset the text position by the pos. If this parameter is true, the text position is set by pos. If the parameter is false, it only moves the UI caret to the specified position.
|
||||
*/
|
||||
bool move_caret(const upoint& pos, bool reset = false);
|
||||
void move_caret_end();
|
||||
void move_caret_end(bool update);
|
||||
void reset_caret_pixels() const;
|
||||
void reset_caret();
|
||||
void reset_caret(bool stay_in_view = false);
|
||||
void show_caret(bool isshow);
|
||||
|
||||
bool selected() const;
|
||||
bool get_selected_points(nana::upoint&, nana::upoint&) const;
|
||||
|
||||
bool select(bool);
|
||||
bool get_select_points(nana::upoint&, nana::upoint&) const;
|
||||
|
||||
/// Sets the end position of a selected string.
|
||||
void set_end_caret();
|
||||
void set_end_caret(bool stay_in_view);
|
||||
|
||||
bool hit_text_area(const point&) const;
|
||||
bool hit_select_area(nana::upoint pos, bool ignore_when_select_all) const;
|
||||
@ -192,7 +198,7 @@ namespace nana{ namespace widgets
|
||||
void move_ns(bool to_north); //Moves up and down
|
||||
void move_left();
|
||||
void move_right();
|
||||
const upoint& mouse_caret(const point& screen_pos);
|
||||
const upoint& mouse_caret(const point& screen_pos, bool stay_in_view);
|
||||
const upoint& caret() const;
|
||||
point caret_screen_pos() const;
|
||||
bool scroll(bool upwards, bool vertical);
|
||||
@ -200,21 +206,29 @@ namespace nana{ namespace widgets
|
||||
bool focus_changed(const arg_focus&);
|
||||
bool mouse_enter(bool entering);
|
||||
bool mouse_move(bool left_button, const point& screen_pos);
|
||||
bool mouse_pressed(const arg_mouse& arg);
|
||||
void mouse_pressed(const arg_mouse& arg);
|
||||
|
||||
skeletons::textbase<char_type>& textbase();
|
||||
const skeletons::textbase<char_type>& textbase() const;
|
||||
|
||||
bool try_refresh();
|
||||
private:
|
||||
nana::color _m_draw_colored_area(paint::graphics& graph, const std::pair<std::size_t,std::size_t>& row, bool whole_line);
|
||||
std::vector<upoint> _m_render_text(const ::nana::color& text_color);
|
||||
void _m_pre_calc_lines(std::size_t line_off, std::size_t lines);
|
||||
|
||||
::nana::point _m_caret_to_screen(::nana::upoint pos) const;
|
||||
::nana::upoint _m_screen_to_caret(::nana::point pos) const;
|
||||
|
||||
bool _m_pos_from_secondary(std::size_t textline, const nana::upoint& secondary, unsigned & pos);
|
||||
bool _m_pos_secondary(const nana::upoint& charpos, nana::upoint& secondary_pos) const;
|
||||
bool _m_move_caret_ns(bool to_north);
|
||||
void _m_update_line(std::size_t pos, std::size_t secondary_count_before);
|
||||
|
||||
bool _m_accepts(char_type) const;
|
||||
::nana::color _m_bgcolor() const;
|
||||
bool _m_scroll_text(bool vertical);
|
||||
void _m_scrollbar();
|
||||
|
||||
::nana::rectangle _m_text_area() const;
|
||||
|
||||
void _m_get_scrollbar_size();
|
||||
void _m_reset_content_size(bool calc_lines = false);
|
||||
void _m_reset();
|
||||
::nana::upoint _m_put(::std::wstring);
|
||||
::nana::upoint _m_erase_select();
|
||||
@ -231,23 +245,25 @@ namespace nana{ namespace widgets
|
||||
bool _m_move_select(bool record_undo);
|
||||
|
||||
int _m_text_top_base() const;
|
||||
int _m_text_topline() const;
|
||||
|
||||
/// Returns the logical position that text starts of a specified line in x-axis
|
||||
int _m_text_x(const text_section&) const;
|
||||
|
||||
void _m_draw_parse_string(const keyword_parser&, bool rtl, ::nana::point pos, const ::nana::color& fgcolor, const wchar_t*, std::size_t len) const;
|
||||
//_m_draw_string
|
||||
//@brief: Draw a line of string
|
||||
void _m_draw_string(int top, const ::nana::color&, const nana::upoint& str_pos, const ::std::wstring&, bool if_mask) const;
|
||||
void _m_draw_string(int top, const ::nana::color&, const nana::upoint& str_pos, const text_section&, bool if_mask) const;
|
||||
//_m_update_caret_line
|
||||
//@brief: redraw whole line specified by caret pos.
|
||||
//@return: true if caret overs the border
|
||||
bool _m_update_caret_line(std::size_t secondary_before);
|
||||
|
||||
void _m_offset_y(int y);
|
||||
|
||||
unsigned _m_char_by_pixels(const unicode_bidi::entity&, unsigned pos);
|
||||
|
||||
unsigned _m_char_by_pixels(const unicode_bidi::entity&, unsigned pos) const;
|
||||
unsigned _m_pixels_by_char(const ::std::wstring&, ::std::size_t pos) const;
|
||||
void _m_handle_move_key(const arg_keyboard& arg);
|
||||
|
||||
unsigned _m_width_px(bool exclude_vs) const;
|
||||
void _m_draw_border();
|
||||
private:
|
||||
struct implementation;
|
||||
@ -264,6 +280,8 @@ namespace nana{ namespace widgets
|
||||
{
|
||||
::std::string tip_string;
|
||||
|
||||
::nana::align alignment{ ::nana::align::left };
|
||||
|
||||
bool line_wrapped{false};
|
||||
bool multi_lines{true};
|
||||
bool editable{true};
|
||||
@ -275,27 +293,24 @@ namespace nana{ namespace widgets
|
||||
{
|
||||
nana::rectangle area;
|
||||
|
||||
bool captured;
|
||||
unsigned tab_space;
|
||||
unsigned scroll_pixels;
|
||||
unsigned vscroll;
|
||||
unsigned hscroll;
|
||||
bool captured{ false };
|
||||
unsigned tab_space{ 4 };
|
||||
}text_area_;
|
||||
|
||||
struct selection
|
||||
{
|
||||
enum class mode{ no_selected, mouse_selected, method_selected, move_selected };
|
||||
enum class mode{ no_selected, mouse_selected, method_selected, move_selected, move_selected_take_effect };
|
||||
|
||||
bool ignore_press{ false };
|
||||
bool move_to_end{ false };
|
||||
mode mode_selection{ mode::no_selected };
|
||||
text_focus_behavior behavior{text_focus_behavior::none};
|
||||
|
||||
text_focus_behavior behavior;
|
||||
bool move_to_end;
|
||||
mode mode_selection;
|
||||
bool ignore_press;
|
||||
nana::upoint a, b;
|
||||
}select_;
|
||||
|
||||
struct coordinate
|
||||
{
|
||||
nana::point offset; //x stands for pixels, y for lines
|
||||
nana::upoint caret; //position of caret by text, it specifies the position of a new character
|
||||
nana::upoint shift_begin_caret;
|
||||
unsigned xpos{0}; //This data is used for move up/down
|
||||
|
||||
@ -26,7 +26,8 @@ namespace nana
|
||||
struct text_editor_scheme
|
||||
: public ::nana::widget_geometrics
|
||||
{
|
||||
color_proxy selection{static_cast<color_rgb>(0x3399FF)};
|
||||
color_proxy selection{ static_cast<color_rgb>(0x3399FF) };
|
||||
color_proxy selection_unfocused{ static_cast<color_rgb>(0xF0F0F0) };
|
||||
color_proxy selection_text{colors::white};
|
||||
|
||||
parameters::mouse_wheel mouse_wheel; ///< The number of lines/characters to scroll when the vertical/horizontal mouse wheel is moved.
|
||||
@ -39,6 +40,29 @@ namespace nana
|
||||
|
||||
virtual void text_exposed(const std::vector<upoint>&) = 0;
|
||||
};
|
||||
|
||||
struct colored_area_type
|
||||
{
|
||||
const ::std::size_t begin; ///< The begin line position
|
||||
::std::size_t count; ///< The number of lines
|
||||
|
||||
::nana::color bgcolor;
|
||||
::nana::color fgcolor;
|
||||
};
|
||||
|
||||
class colored_area_access_interface
|
||||
{
|
||||
public:
|
||||
using colored_area_type = skeletons::colored_area_type;
|
||||
|
||||
virtual ~colored_area_access_interface();
|
||||
|
||||
virtual std::shared_ptr<colored_area_type> get(std::size_t line_pos) = 0;
|
||||
virtual bool clear() = 0;
|
||||
virtual bool remove(std::size_t line_pos) = 0;
|
||||
virtual std::size_t size() const = 0;
|
||||
virtual std::shared_ptr<colored_area_type> at(std::size_t index) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,7 +435,7 @@ namespace nana{ namespace widgets{ namespace skeletons
|
||||
};
|
||||
|
||||
::std::string font;
|
||||
std::size_t font_size;
|
||||
double font_size;
|
||||
bool bold;
|
||||
bool bold_empty; //bold should be ignored if bold_empty is true
|
||||
aligns::t text_align;
|
||||
@ -859,7 +859,7 @@ namespace nana{ namespace widgets{ namespace skeletons
|
||||
//Create a default fblock.
|
||||
fblock * fbp = new fblock;
|
||||
|
||||
fbp->font_size = 0xFFFFFFFF;
|
||||
fbp->font_size = -1;
|
||||
fbp->bold = false;
|
||||
fbp->bold_empty = true;
|
||||
fbp->text_align = fblock::aligns::baseline;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Spin box widget
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -56,6 +56,7 @@ namespace nana
|
||||
private:
|
||||
//Overrides drawer_trigger
|
||||
void attached(widget_reference, graph_reference) override;
|
||||
void detached() override;
|
||||
void refresh(graph_reference) override;
|
||||
|
||||
void focus(graph_reference, const arg_focus&) override;
|
||||
@ -95,8 +96,11 @@ namespace nana
|
||||
void range(double begin, double last, double step);
|
||||
|
||||
/// Sets the string spin values.
|
||||
void range(std::initializer_list<std::string> values_utf8);
|
||||
void range(std::initializer_list<std::wstring> values);
|
||||
void range(std::vector<std::string> values_utf8);
|
||||
|
||||
std::vector<std::string> range_string() const;
|
||||
std::pair<int, int> range_int() const;
|
||||
std::pair<double, double> range_double() const;
|
||||
|
||||
/// Gets the spined value
|
||||
::std::string value() const;
|
||||
|
||||
@ -248,7 +248,7 @@ namespace nana
|
||||
API::refresh_window(this->handle());
|
||||
}
|
||||
|
||||
pat::cloneable<item_renderer>& renderer() const
|
||||
const pat::cloneable<item_renderer>& renderer() const
|
||||
{
|
||||
return this->get_drawer_trigger().ext_renderer();
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Textbox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -100,9 +100,12 @@ namespace nana
|
||||
:public widget_object<category::widget_tag, drawerbase::textbox::drawer, drawerbase::textbox::textbox_events, ::nana::widgets::skeletons::text_editor_scheme>
|
||||
{
|
||||
public:
|
||||
using text_focus_behavior = widgets::skeletons::text_focus_behavior;
|
||||
using colored_area_type = widgets::skeletons::colored_area_type;
|
||||
using colored_area_access_interface = widgets::skeletons::colored_area_access_interface;
|
||||
|
||||
using text_focus_behavior = widgets::skeletons::text_focus_behavior;
|
||||
using text_positions = std::vector<upoint>;
|
||||
|
||||
/// The default constructor without creating the widget.
|
||||
textbox();
|
||||
|
||||
@ -134,6 +137,8 @@ namespace nana
|
||||
void store(std::string file);
|
||||
void store(std::string file, nana::unicode encoding);
|
||||
|
||||
colored_area_access_interface* colored_area_access();
|
||||
|
||||
/// Enables/disables the textbox to indent a line. Idents a new line when it is created by pressing enter.
|
||||
/// @param generator generates text for identing a line. If it is empty, textbox indents the line according to last line.
|
||||
textbox& indention(bool, std::function<std::string()> generator = {});
|
||||
@ -162,6 +167,9 @@ namespace nana
|
||||
/// Read the text from a specified line. It returns true for success.
|
||||
bool getline(std::size_t pos, std::string&) const;
|
||||
|
||||
/// Read the text from a specified line with a set offset. It returns true for success.
|
||||
bool getline(std::size_t line_index,std::size_t offset,std::string& text) const;
|
||||
|
||||
/// Gets the caret position
|
||||
/// Returns true if the caret is in the area of display, false otherwise.
|
||||
bool caret_pos(point& pos, bool text_coordinate) const;
|
||||
@ -196,6 +204,7 @@ namespace nana
|
||||
|
||||
/// Returns true if some text is selected.
|
||||
bool selected() const;
|
||||
bool get_selected_points(nana::upoint &a, nana::upoint &b) const;
|
||||
|
||||
/// Selects/unselects all text.
|
||||
void select(bool);
|
||||
@ -215,12 +224,17 @@ namespace nana
|
||||
textbox& from(int);
|
||||
textbox& from(double);
|
||||
|
||||
void clear_undo();
|
||||
|
||||
void set_highlight(const std::string& name, const ::nana::color& fgcolor, const ::nana::color& bgcolor);
|
||||
void erase_highlight(const std::string& name);
|
||||
void set_keywords(const std::string& name, bool case_sensitive, bool whole_word_match, std::initializer_list<std::wstring> kw_list);
|
||||
void set_keywords(const std::string& name, bool case_sensitive, bool whole_word_match, std::initializer_list<std::string> kw_list_utf8);
|
||||
void erase_keyword(const std::string& kw);
|
||||
|
||||
/// Sets the text alignment
|
||||
textbox& text_align(::nana::align alignment);
|
||||
|
||||
/// Returns the text position of each line that currently displays on screen.
|
||||
text_positions text_position() const;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Tree Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -37,7 +37,7 @@ namespace nana
|
||||
{
|
||||
enum class component
|
||||
{
|
||||
begin, expender = begin, crook, icon, text, bground, end
|
||||
begin, expander = begin, crook, icon, text, bground, end
|
||||
};
|
||||
|
||||
struct node_image_tag
|
||||
@ -73,8 +73,8 @@ namespace nana
|
||||
typedef compset_interface::comp_attribute_t comp_attribute_t;
|
||||
|
||||
virtual ~renderer_interface() = default;
|
||||
virtual void set_color(const nana::color& bgcolor, const nana::color& fgcolor) = 0;
|
||||
|
||||
virtual void begin_paint(::nana::widget&) = 0;
|
||||
virtual void bground(graph_reference, const compset_interface *) const = 0;
|
||||
virtual void expander(graph_reference, const compset_interface *) const = 0;
|
||||
virtual void crook(graph_reference, const compset_interface *) const = 0;
|
||||
@ -110,45 +110,30 @@ namespace nana
|
||||
|
||||
struct pseudo_node_type{};
|
||||
|
||||
typedef widgets::detail::tree_cont<treebox_node_type> tree_cont_type;
|
||||
typedef tree_cont_type::node_type node_type;
|
||||
using tree_cont_type = widgets::detail::tree_cont<treebox_node_type>;
|
||||
using node_type = tree_cont_type::node_type;
|
||||
|
||||
trigger();
|
||||
~trigger();
|
||||
|
||||
implement * impl() const;
|
||||
|
||||
void auto_draw(bool);
|
||||
void checkable(bool);
|
||||
bool checkable() const;
|
||||
void check(node_type*, checkstate);
|
||||
bool draw();
|
||||
|
||||
const tree_cont_type & tree() const;
|
||||
tree_cont_type & tree();
|
||||
|
||||
void renderer(::nana::pat::cloneable<renderer_interface>&&);
|
||||
const ::nana::pat::cloneable<renderer_interface>& renderer() const;
|
||||
void placer(::nana::pat::cloneable<compset_placer_interface>&&);
|
||||
const ::nana::pat::cloneable<compset_placer_interface>& placer() const;
|
||||
|
||||
nana::any & value(node_type*) const;
|
||||
node_type* insert(node_type*, const std::string& key, std::string&&);
|
||||
node_type* insert(const std::string& path, std::string&&);
|
||||
|
||||
bool verify(const void*) const;
|
||||
bool verify_kinship(node_type* parent, node_type* child) const;
|
||||
|
||||
void remove(node_type*);
|
||||
node_type * selected() const;
|
||||
void selected(node_type*);
|
||||
void set_expand(node_type*, bool);
|
||||
void set_expand(const ::std::string& path, bool);
|
||||
|
||||
node_image_tag& icon(const ::std::string&) const;
|
||||
void icon_erase(const ::std::string&);
|
||||
void node_icon(node_type*, const ::std::string& id);
|
||||
|
||||
unsigned node_width(const node_type*) const;
|
||||
|
||||
bool rename(node_type*, const char* key, const char* name);
|
||||
@ -206,6 +191,9 @@ namespace nana
|
||||
/// Set the check state, and it returns itself.
|
||||
item_proxy& check(bool);
|
||||
|
||||
/// Clears the child nodes
|
||||
item_proxy& clear();
|
||||
|
||||
/// Return true when the node is expanded \todo change to expanded ??
|
||||
bool expanded() const;
|
||||
|
||||
@ -421,6 +409,9 @@ namespace nana
|
||||
|
||||
bool checkable() const; ///< Determinte whether the checkboxs are enabled.
|
||||
|
||||
/// Clears the contents
|
||||
void clear();
|
||||
|
||||
/// \brief Creates an icon scheme with the specified name.
|
||||
///
|
||||
/// The icon scheme includes 3 images for node states.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* The fundamental widget class implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -64,7 +64,7 @@ namespace nana
|
||||
template<typename ...Args>
|
||||
void i18n(std::string msgid, Args&&... args)
|
||||
{
|
||||
_m_caption(nana::internationalization().get(msgid, std::forward<Args>(args)...));
|
||||
_m_caption(::nana::to_nstring(::nana::internationalization().get(msgid, std::forward<Args>(args)...)));
|
||||
}
|
||||
|
||||
void i18n(i18n_eval);
|
||||
@ -247,7 +247,6 @@ namespace nana
|
||||
{
|
||||
widget_base::_m_notify_destroy();
|
||||
events_ = std::make_shared<Events>();
|
||||
API::dev::set_events(handle_, events_);
|
||||
}
|
||||
private:
|
||||
DrawerTrigger trigger_;
|
||||
@ -312,7 +311,6 @@ namespace nana
|
||||
{
|
||||
widget_base::_m_notify_destroy();
|
||||
events_ = std::make_shared<Events>();
|
||||
API::dev::set_events(handle_, events_);
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<Events> events_;
|
||||
@ -451,7 +449,6 @@ namespace nana
|
||||
{
|
||||
widget_base::_m_notify_destroy();
|
||||
events_ = std::make_shared<Events>();
|
||||
API::dev::set_events(handle_, events_);
|
||||
}
|
||||
private:
|
||||
DrawerTrigger trigger_;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Nana GUI Library Definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -59,6 +59,8 @@ namespace nana
|
||||
template<typename Form, bool IsVisible = true>
|
||||
using form_loader = detail::form_loader<Form, IsVisible>;
|
||||
|
||||
#ifdef NANA_AUTOMATIC_GUI_TESTING
|
||||
|
||||
/// @brief Take control of the GUI and optionaly automaticaly tests it.
|
||||
///
|
||||
/// @detail It transfers to nana the program flow control, which begin pumping messages
|
||||
@ -77,6 +79,9 @@ namespace nana
|
||||
|
||||
/// in seconds
|
||||
void Wait(unsigned wait = 0);
|
||||
#else
|
||||
void exec();
|
||||
#endif
|
||||
|
||||
|
||||
}//end namespace nana
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <nana/deploy.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -23,6 +24,9 @@ namespace nana
|
||||
{
|
||||
friend class i18n_eval;
|
||||
public:
|
||||
/// Sets a handler to handle a msgid which hasn't been translated.
|
||||
static void set_missing(std::function<void(const std::string& msgid_utf8)> handler);
|
||||
|
||||
void load(const std::string& file);
|
||||
void load_utf8(const std::string& file);
|
||||
|
||||
@ -32,9 +36,8 @@ namespace nana
|
||||
std::vector<std::string> arg_strs;
|
||||
_m_fetch_args(arg_strs, std::forward<Args>(args)...);
|
||||
|
||||
::std::string msgstr;
|
||||
if (_m_get(msgid_utf8, msgstr))
|
||||
_m_replace_args(msgstr, &arg_strs);
|
||||
auto msgstr = _m_get(std::move(msgid_utf8));
|
||||
_m_replace_args(msgstr, &arg_strs);
|
||||
return msgstr;
|
||||
}
|
||||
|
||||
@ -47,16 +50,24 @@ namespace nana
|
||||
return get(msgid_utf8, std::forward<Args>(args)...);
|
||||
}
|
||||
private:
|
||||
bool _m_get(std::string& msgid, ::std::string& msgstr) const;
|
||||
std::string _m_get(std::string&& msgid) const;
|
||||
void _m_replace_args(::std::string& str, std::vector<::std::string> * arg_strs) const;
|
||||
|
||||
void _m_fetch_args(std::vector<std::string>&) const //Termination of _m_fetch_args
|
||||
{}
|
||||
void _m_fetch_args(std::vector<std::string>&) const; //Termination of _m_fetch_args
|
||||
|
||||
void _m_fetch_args(std::vector<std::string>& v, const char* arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, const std::string& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::string& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::string&& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, const wchar_t* arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, const std::wstring& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::wstring& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::wstring&& arg) const;
|
||||
|
||||
template<typename Arg>
|
||||
void _m_fetch_args(std::vector<std::string>& v, Arg&& arg) const
|
||||
{
|
||||
std::wstringstream ss;
|
||||
std::stringstream ss;
|
||||
ss << arg;
|
||||
v.emplace_back(ss.str());
|
||||
}
|
||||
@ -89,6 +100,34 @@ namespace nana
|
||||
_m_fetch_args(v, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
void _m_fetch_args(std::vector<std::string>& v, const wchar_t* arg, Args&&... args) const
|
||||
{
|
||||
v.emplace_back(to_utf8(arg));
|
||||
_m_fetch_args(v, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
void _m_fetch_args(std::vector<std::string>& v, const std::wstring& arg, Args&&... args) const
|
||||
{
|
||||
v.emplace_back(to_utf8(arg));
|
||||
_m_fetch_args(v, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::wstring& arg, Args&&... args) const
|
||||
{
|
||||
v.emplace_back(to_utf8(arg));
|
||||
_m_fetch_args(v, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::wstring&& arg, Args&&... args) const
|
||||
{
|
||||
v.emplace_back(to_utf8(arg));
|
||||
_m_fetch_args(v, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Arg, typename ...Args>
|
||||
void _m_fetch_args(std::vector<std::string>& v, Arg&& arg, Args&&... args) const
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Key Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -21,12 +21,12 @@ namespace nana
|
||||
public:
|
||||
virtual ~key_interface(){}
|
||||
|
||||
virtual bool same_type(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 )) ]
|
||||
virtual bool same_type(const key_interface*) const noexcept = 0;
|
||||
virtual bool compare(const key_interface*) const noexcept = 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 [call it equal_by_less()?]
|
||||
inline bool pred_equal(const key_interface * left, const key_interface* right)
|
||||
inline bool pred_equal(const key_interface * left, const key_interface* right) noexcept
|
||||
{
|
||||
return (left->same_type(right) && (left->compare(right) == false) && (right->compare(left) == false));
|
||||
}
|
||||
@ -104,12 +104,12 @@ namespace nana
|
||||
}
|
||||
public:
|
||||
//implement key_interface methods
|
||||
bool same_type(const key_interface * p) const override
|
||||
bool same_type(const key_interface * p) const noexcept override
|
||||
{
|
||||
return (nullptr != dynamic_cast<const key*>(p));
|
||||
}
|
||||
|
||||
bool compare(const key_interface* p) const override
|
||||
bool compare(const key_interface* p) const noexcept override
|
||||
{
|
||||
auto rhs = dynamic_cast<const key*>(p);
|
||||
return rhs && compare_(key_object_, rhs->key_object_);
|
||||
|
||||
364
include/nana/optional.hpp
Normal file
364
include/nana/optional.hpp
Normal file
@ -0,0 +1,364 @@
|
||||
/**
|
||||
* Optional
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2017 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/optional.hpp
|
||||
*
|
||||
* @brief An implementation of experimental library optional of C++ standard(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html)
|
||||
*/
|
||||
|
||||
#ifndef NANA_STD_OPTIONAL_HEADER_INCLUDED
|
||||
#define NANA_STD_OPTIONAL_HEADER_INCLUDED
|
||||
|
||||
#include <stdexcept>
|
||||
#include <nana/c++defines.hpp>
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
class storage
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
storage() = default;
|
||||
|
||||
template<typename U>
|
||||
storage(U&& value)
|
||||
: initialized_{ true }
|
||||
{
|
||||
::new (data_) value_type(std::forward<U>(value));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
storage(const U& value)
|
||||
: initialized_{ true }
|
||||
{
|
||||
::new (data_) value_type(value);
|
||||
}
|
||||
|
||||
storage(const storage& other)
|
||||
: initialized_{ other.initialized_ }
|
||||
{
|
||||
if (other.initialized_)
|
||||
::new (data_) value_type(*other.ptr());
|
||||
}
|
||||
|
||||
storage(storage&& other)
|
||||
: initialized_{ other.initialized_ }
|
||||
{
|
||||
if (other.initialized_)
|
||||
::new (data_) value_type(std::move(*other.ptr()));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
storage(const storage<U>& other)
|
||||
: initialized_{ other.initialized_ }
|
||||
{
|
||||
if (other.initialized_)
|
||||
::new (data_) value_type(*other.ptr());
|
||||
}
|
||||
|
||||
~storage()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
bool initialized() const noexcept
|
||||
{
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
void set_initialized()
|
||||
{
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if (initialized_)
|
||||
{
|
||||
ptr()->~T();
|
||||
initialized_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void assign(U&& value)
|
||||
{
|
||||
if (initialized_)
|
||||
*ptr() = std::forward<U>(value);
|
||||
else
|
||||
{
|
||||
::new (data_) value_type(std::forward<U>(value));
|
||||
initialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void assign(const storage& other)
|
||||
{
|
||||
if (!other.initialized_)
|
||||
{
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (initialized_)
|
||||
*ptr() = *other.ptr();
|
||||
else
|
||||
{
|
||||
::new (data_) value_type(*other.ptr());
|
||||
initialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void assign(storage&& other)
|
||||
{
|
||||
if (!other.initialized_)
|
||||
{
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (initialized_)
|
||||
*ptr() = std::move(*other.ptr());
|
||||
else
|
||||
{
|
||||
::new (data_) value_type(std::move(*other.ptr()));
|
||||
initialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
const T* ptr() const
|
||||
{
|
||||
return reinterpret_cast<const T*>(data_);
|
||||
}
|
||||
|
||||
T* ptr()
|
||||
{
|
||||
return reinterpret_cast<T*>(data_);
|
||||
}
|
||||
private:
|
||||
bool initialized_{ false };
|
||||
char data_[sizeof(value_type)];
|
||||
};
|
||||
}//end namespace detail
|
||||
|
||||
class bad_optional_access
|
||||
: public std::logic_error
|
||||
{
|
||||
public:
|
||||
bad_optional_access()
|
||||
: std::logic_error("Attempted to access the value of an uninitialized optional object.")
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class optional
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
constexpr optional() = default;
|
||||
constexpr optional(std::nullptr_t) {}
|
||||
|
||||
optional(const optional& other)
|
||||
: storage_(other.storage_)
|
||||
{}
|
||||
|
||||
optional(optional&& other)
|
||||
: storage_(std::move(other.storage_))
|
||||
{}
|
||||
|
||||
constexpr optional(const value_type& value)
|
||||
: storage_(value)
|
||||
{}
|
||||
|
||||
constexpr optional(value_type&& value)
|
||||
: storage_(std::move(value))
|
||||
{}
|
||||
|
||||
optional& operator=(std::nullptr_t)
|
||||
{
|
||||
storage_.destroy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
optional& operator=(const optional& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
storage_.assign(other.storage_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
optional& operator=(optional&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
storage_.assign(std::move(other.storage_));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
optional& operator=(U&& value)
|
||||
{
|
||||
storage_.assign(std::forward<U>(value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Value access
|
||||
//constexpr
|
||||
value_type* operator->()
|
||||
{
|
||||
return storage_.ptr();
|
||||
}
|
||||
constexpr const value_type* operator->() const
|
||||
{
|
||||
return storage_.ptr();
|
||||
}
|
||||
|
||||
//constexpr
|
||||
value_type& operator*()
|
||||
{
|
||||
return *storage_.ptr();
|
||||
}
|
||||
|
||||
constexpr const value_type& operator*() const
|
||||
{
|
||||
return *storage_.ptr();
|
||||
}
|
||||
|
||||
/*
|
||||
//constexpr
|
||||
value_type&& operator*() &&
|
||||
{
|
||||
return std::move(*storage_.ptr());
|
||||
}
|
||||
|
||||
//constexpr
|
||||
const value_type&& operator*() const &&
|
||||
{
|
||||
return std::move(*storage_.ptr());
|
||||
}
|
||||
*/
|
||||
|
||||
//Condition
|
||||
constexpr explicit operator bool() const
|
||||
{
|
||||
return storage_.initialized();
|
||||
}
|
||||
|
||||
constexpr bool has_value() const
|
||||
{
|
||||
return storage_.initialized();
|
||||
}
|
||||
|
||||
//constexpr
|
||||
value_type& value()
|
||||
{
|
||||
if (!storage_.initialized())
|
||||
throw bad_optional_access{};
|
||||
|
||||
return *storage_.ptr();
|
||||
}
|
||||
|
||||
constexpr const value_type& value() const
|
||||
{
|
||||
if (!storage_.initialized())
|
||||
throw bad_optional_access{};
|
||||
|
||||
return *storage_.ptr();
|
||||
}
|
||||
/*
|
||||
//constexpr
|
||||
value_type&& value()
|
||||
{
|
||||
if (!storage_.initialized())
|
||||
throw bad_optional_access{};
|
||||
|
||||
return std::move(*storage_.ptr());
|
||||
}
|
||||
|
||||
constexpr const value_type&& value() const
|
||||
{
|
||||
if (!storage_.initialized())
|
||||
throw bad_optional_access{};
|
||||
|
||||
return std::move(*storage_.ptr());
|
||||
}
|
||||
*/
|
||||
|
||||
template<typename U>
|
||||
constexpr T value_or(U&& default_value) const
|
||||
{
|
||||
return (has_value() ? **this : static_cast<T>(std::forward<U>(default_value)));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
//constexpr
|
||||
T value_or(U&& default_value)
|
||||
{
|
||||
return (has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(default_value)));
|
||||
}
|
||||
|
||||
//Modifiers
|
||||
void swap(optional& other)
|
||||
{
|
||||
if (has_value() && other.has_value())
|
||||
{
|
||||
std::swap(**this, *other);
|
||||
return;
|
||||
}
|
||||
else if (has_value())
|
||||
{
|
||||
other.emplace(std::move(***this));
|
||||
storage_.destroy();
|
||||
}
|
||||
else if (other.has_value())
|
||||
{
|
||||
this->emplace(std::move(*other));
|
||||
other.storage_.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
storage_.destroy();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void emplace(Args&&... args)
|
||||
{
|
||||
storage_.destroy();
|
||||
::new (storage_.ptr()) T(std::forward<Args>(args)...);
|
||||
|
||||
storage_.set_initialized();
|
||||
}
|
||||
|
||||
template<typename U, typename... Args>
|
||||
void emplace(std::initializer_list<U> il, Args&& ... args)
|
||||
{
|
||||
storage_.destroy();
|
||||
::new (storage_.ptr()) T(il, std::forward<Args>(args)...);
|
||||
|
||||
storage_.set_initialized();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
detail::storage<T> storage_;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -14,7 +14,7 @@ namespace nana{ namespace paint{
|
||||
{
|
||||
image_impl_interface& operator=(const image_impl_interface& rhs);
|
||||
public:
|
||||
typedef nana::paint::graphics& graph_reference;
|
||||
using graph_reference = nana::paint::graphics&;
|
||||
virtual ~image_impl_interface() = 0; //The destructor is defined in ../image.cpp
|
||||
virtual bool open(const std::experimental::filesystem::path& file) = 0;
|
||||
virtual bool open(const void* data, std::size_t bytes) = 0; // reads image from memory
|
||||
|
||||
@ -426,7 +426,7 @@ namespace detail
|
||||
|
||||
unsigned char * fade_table = nullptr;
|
||||
std::unique_ptr<unsigned char[]> autoptr;
|
||||
nana::pixel_argb_t rgb_imd;
|
||||
nana::pixel_argb_t rgb_imd = {};
|
||||
if(fade_rate != 0.0)
|
||||
{
|
||||
autoptr = detail::alloc_fade_table(1 - fade_rate);
|
||||
|
||||
@ -25,12 +25,12 @@ namespace detail
|
||||
void free_fade_table(const unsigned char*);
|
||||
|
||||
//color = bgcolor * fade_rate + fgcolor * (1 - fade_rate);
|
||||
//nana::pixel_color_t fade_color(nana::pixel_color_t bgcolor, nana::pixel_color_t fgcolor, double fade_rate); //deprecated
|
||||
nana::pixel_color_t fade_color(nana::pixel_color_t bgcolor, nana::pixel_color_t fgcolor, const unsigned char* const fade_table);
|
||||
nana::pixel_color_t fade_color_intermedia(pixel_color_t fgcolor, const unsigned char* fade_table);
|
||||
nana::pixel_color_t fade_color_by_intermedia(pixel_color_t bgcolor, nana::pixel_color_t fgcolor_intermedia, const unsigned char* const fade_table);
|
||||
|
||||
void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t, double fade_rate);
|
||||
//dw color = dw color * fade_rate + bdcolor * (1 - fade_rate)
|
||||
void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t bdcolor, double fade_rate);
|
||||
|
||||
nana::size raw_text_extent_size(drawable_type, const wchar_t*, std::size_t len);
|
||||
nana::size text_extent_size(drawable_type, const wchar_t*, std::size_t len);
|
||||
|
||||
29
include/nana/paint/detail/ptdefs.hpp
Normal file
29
include/nana/paint/detail/ptdefs.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef NANA_PAINT_PTDEFS_INCLUDED
|
||||
#define NANA_PAINT_PTDEFS_INCLUDED
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct native_font_signature;
|
||||
|
||||
|
||||
struct font_style
|
||||
{
|
||||
unsigned weight{ 400 }; //normal
|
||||
bool italic{ false };
|
||||
bool underline{ false };
|
||||
bool strike_out{ false };
|
||||
|
||||
font_style() = default;
|
||||
font_style(unsigned weight, bool italic = false, bool underline = false, bool strike_out = false);
|
||||
};
|
||||
}//end namespace detail
|
||||
|
||||
namespace paint
|
||||
{
|
||||
using native_font_type = ::nana::detail::native_font_signature*;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Paint Graphics Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,40 +17,42 @@
|
||||
|
||||
#include "../basic_types.hpp"
|
||||
#include "../gui/basis.hpp"
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
#include "detail/ptdefs.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace paint
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct native_font_signature;
|
||||
}// end namespace detail
|
||||
|
||||
typedef detail::native_font_signature* native_font_type;
|
||||
|
||||
class font
|
||||
{
|
||||
friend class graphics;
|
||||
public:
|
||||
using path_type = ::std::experimental::filesystem::path;
|
||||
|
||||
using font_style = ::nana::detail::font_style;
|
||||
|
||||
font();
|
||||
font(drawable_type);
|
||||
font(const font&);
|
||||
font(const ::std::string& name, unsigned size, bool bold = false, bool italic = false, bool underline = false, bool strike_out = false);
|
||||
|
||||
font(const ::std::string& name, double size_pt, const font_style& fs = {});
|
||||
font(double size_pt, const path_type& truetype, const font_style& ft = {});
|
||||
|
||||
~font();
|
||||
bool empty() const;
|
||||
void make(const ::std::string& name, unsigned size, bool bold = false, bool italic = false, bool underline = false, bool strike_out = false);
|
||||
void make_raw(const ::std::string& name, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out);
|
||||
|
||||
void set_default() const;
|
||||
::std::string name() const;
|
||||
unsigned size() const;
|
||||
double size() const;
|
||||
bool bold() const;
|
||||
unsigned height() const;
|
||||
unsigned weight() const;
|
||||
bool italic() const;
|
||||
native_font_type handle() const;
|
||||
void release();
|
||||
bool strikeout() const;
|
||||
bool underline() const;
|
||||
|
||||
font& operator=(const font&);
|
||||
bool operator==(const font&) const;
|
||||
@ -116,7 +118,7 @@ namespace nana
|
||||
void bitblt(const ::nana::rectangle& r_dst, const graphics& src, const point& p_src);///< Transfers the color data corresponding to r_dst from the src graphics at point p_src to this graphics.
|
||||
|
||||
void blend(const ::nana::rectangle& r, const ::nana::color&, double fade_rate);
|
||||
void blend(const ::nana::rectangle& s_r, graphics& dst, const point& d_pos, double fade_rate) const;///< blends with the dst object.
|
||||
void blend(const ::nana::rectangle& blend_r, const graphics& blend_graph, const point& blend_graph_point, double fade_rate);///< blends with the blend_graph.
|
||||
|
||||
void blur(const ::nana::rectangle& r, std::size_t radius); ///< Blur process.
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ namespace nana
|
||||
{
|
||||
std::unique_ptr<Interface> create() override
|
||||
{
|
||||
constexpr auto Size = std::tuple_size<decltype(args_)>::value;
|
||||
constexpr auto const Size = std::tuple_size<decltype(args_)>::value;
|
||||
return std::unique_ptr<Interface>{ _m_new(make_pack<Size>{}) };
|
||||
}
|
||||
|
||||
|
||||
156
include/nana/stdc++.hpp
Normal file
156
include/nana/stdc++.hpp
Normal file
@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Standard Library for C++11/14/17
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2017 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/stdc++.hpp
|
||||
*
|
||||
* @brief Implement the lack support of standard library.
|
||||
*/
|
||||
|
||||
#include "c++defines.hpp"
|
||||
|
||||
//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.
|
||||
int stoi(const std::string&, std::size_t * pos = nullptr, int base = 10);
|
||||
int stoi(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stof in MinGW.
|
||||
float stof(const std::string&, std::size_t * pos = nullptr);
|
||||
float stof(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stod in MinGW.
|
||||
double stod(const std::string&, std::size_t * pos = nullptr);
|
||||
double stod(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stold in MinGW.
|
||||
long double stold(const std::string&, std::size_t * pos = nullptr);
|
||||
long double stold(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stol in MinGW.
|
||||
long stol(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
long stol(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoll in MinGW.
|
||||
long long stoll(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
long long stoll(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoul in MinGW.
|
||||
unsigned long stoul(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
unsigned long stoul(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoull in MinGW.
|
||||
unsigned long long stoull(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
unsigned long long stoull(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
}
|
||||
#endif //STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED
|
||||
|
||||
#ifdef STD_TO_STRING_NOT_SUPPORTED
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::to_string/std::to_wstring in MinGW.
|
||||
std::string to_string(long double);
|
||||
std::string to_string(double);
|
||||
std::string to_string(unsigned);
|
||||
std::string to_string(int);
|
||||
std::string to_string(long);
|
||||
std::string to_string(unsigned long);
|
||||
std::string to_string(long long);
|
||||
std::string to_string(unsigned long long);
|
||||
std::string to_string(float);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STD_TO_WSTRING_NOT_SUPPORTED
|
||||
namespace std
|
||||
{
|
||||
std::wstring to_wstring(long double);
|
||||
std::wstring to_wstring(double);
|
||||
std::wstring to_wstring(unsigned);
|
||||
std::wstring to_wstring(int);
|
||||
std::wstring to_wstring(long);
|
||||
std::wstring to_wstring(unsigned long);
|
||||
std::wstring to_wstring(long long);
|
||||
std::wstring to_wstring(unsigned long long);
|
||||
std::wstring to_wstring(float);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _enable_std_make_unique
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace std {
|
||||
template<class T> struct _Unique_if {
|
||||
typedef unique_ptr<T> _Single_object;
|
||||
};
|
||||
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_unique(Args&&... args) {
|
||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_unique(size_t n) {
|
||||
typedef typename remove_extent<T>::type U;
|
||||
return unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_unique(Args&&...) = delete;
|
||||
}
|
||||
#endif //_enable_std_make_unique
|
||||
|
||||
#ifdef _enable_std_put_time
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::put_time in gcc < 5.
|
||||
/* std unspecified return type */
|
||||
//template< class CharT, class RTSTR >// let fail for CharT != char / wchar_t
|
||||
//RTSTR put_time(const std::tm* tmb, const CharT* fmt);
|
||||
|
||||
//template< >
|
||||
std::string put_time/*<char, std::string>*/(const std::tm* tmb, const char* fmt);
|
||||
|
||||
//Defined in header <ctime>
|
||||
// std::size_t strftime(char* str, std::size_t count, const char* format, const std::tm* time);
|
||||
//template<>
|
||||
//std::wstring put_time<wchar_t, std::wstring>(const std::tm* tmb, const wchar_t* fmt);
|
||||
}
|
||||
#endif // _enable_std_put_time
|
||||
|
||||
#if defined(_enable_std_clamp)
|
||||
namespace std
|
||||
{
|
||||
//<algorithm> since C++17
|
||||
template<typename T>
|
||||
constexpr const T& clamp(const T& v, const T& lo, const T& hi)
|
||||
{
|
||||
return (v < lo ? lo : (hi < v ? hi : v));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Data Exchanger Implementation
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#ifndef NANA_SYSTEM_DATAEXCH_HPP
|
||||
#define NANA_SYSTEM_DATAEXCH_HPP
|
||||
#include <nana/basic_types.hpp>
|
||||
#include <nana/gui/basis.hpp>
|
||||
|
||||
namespace nana{
|
||||
|
||||
@ -31,15 +31,17 @@ namespace system{
|
||||
text, pixmap
|
||||
};
|
||||
|
||||
void set(const std::string & text_utf8);
|
||||
void set(const std::wstring& text);
|
||||
void set(const std::string & text_utf8, native_window_type owner = nullptr);
|
||||
void set(const std::wstring& text, native_window_type owner = nullptr);
|
||||
|
||||
bool set(const nana::paint::graphics& g);
|
||||
bool set(const nana::paint::graphics& g, native_window_type owner = nullptr);
|
||||
|
||||
void get(std::string& text_utf8);
|
||||
void get(std::wstring& text);
|
||||
|
||||
std::wstring wget();
|
||||
private:
|
||||
bool _m_set(format, const void* buf, std::size_t size);
|
||||
bool _m_set(format, const void* buf, std::size_t size, native_window_type);
|
||||
void* _m_get(format, size_t& size);
|
||||
};
|
||||
|
||||
|
||||
@ -54,11 +54,17 @@ namespace threads
|
||||
|
||||
struct task_signal;
|
||||
class impl;
|
||||
|
||||
pool(const pool&) = delete;
|
||||
pool& operator=(const pool&) = delete;
|
||||
public:
|
||||
pool(); ///< Creates a group of threads.
|
||||
pool(pool&&);
|
||||
pool(std::size_t thread_number); ///< Creates a number of threads specifed by thread_number.
|
||||
~pool(); ///< waits for the all running tasks till they are finished and skips all the queued tasks.
|
||||
|
||||
pool& operator=(pool&&);
|
||||
|
||||
template<typename Function>
|
||||
void push(const Function& f)
|
||||
{
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
|
||||
|
||||
#define STRING2(x) #x
|
||||
#define STRING2(...) #__VA_ARGS__
|
||||
#define STRING(x) STRING2(x)
|
||||
#define SHOW_VALUE(x) " " #x " = " STRING2(x)
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
#pragma message ( SHOW_VALUE(USE_github_com_meganz_mingw_std_threads) )
|
||||
#pragma message ( SHOW_VALUE(NANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) )
|
||||
#pragma message ( SHOW_VALUE(STD_THREAD_NOT_SUPPORTED) )
|
||||
#pragma message ( SHOW_VALUE(STD_put_time_NOT_SUPPORTED) )
|
||||
#pragma message ( SHOW_VALUE(_enable_std_put_time) )
|
||||
#pragma message ( SHOW_VALUE(STD_MAKE_UNIQUE_NOT_SUPPORTED) )
|
||||
|
||||
#pragma message ( SHOW_VALUE(STD_FILESYSTEM_NOT_SUPPORTED) )
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Basic Types definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -53,11 +53,6 @@ namespace nana
|
||||
a_((static_cast<int>(rgba) & 0xFF) / 255.0)
|
||||
{}
|
||||
|
||||
color::color(unsigned red, unsigned green, unsigned blue)
|
||||
: r_(red), g_(green), b_(blue), a_(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
color::color(unsigned red, unsigned green, unsigned blue, double alpha)
|
||||
: r_(red), g_(green), b_(blue), a_(alpha)
|
||||
{
|
||||
@ -426,47 +421,12 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
color color::blend(const color& bgcolor, bool ignore_bgcolor_alpha) const
|
||||
{
|
||||
if (a_ < 1.0)
|
||||
{
|
||||
color result;
|
||||
if (0.0 < a_)
|
||||
{
|
||||
if (ignore_bgcolor_alpha || (1.0 == bgcolor.b_))
|
||||
{
|
||||
result.r_ = r_ * a_ + bgcolor.r_ * (1.0 - a_);
|
||||
result.g_ = g_ * a_ + bgcolor.g_ * (1.0 - a_);
|
||||
result.b_ = b_ * a_ + bgcolor.b_ * (1.0 - a_);
|
||||
result.a_ = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.r_ = r_ * a_ + bgcolor.r_ * bgcolor.a_ * (1.0 - a_);
|
||||
result.g_ = g_ * a_ + bgcolor.g_ * bgcolor.a_ * (1.0 - a_);
|
||||
result.b_ = b_ * a_ + bgcolor.b_ * bgcolor.a_ * (1.0 - a_);
|
||||
result.a_ = a_ + (bgcolor.a_ * (1.0 - a_));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.r_ = bgcolor.r_;
|
||||
result.g_ = bgcolor.g_;
|
||||
result.b_ = bgcolor.b_;
|
||||
result.a_ = (ignore_bgcolor_alpha ? 1.0 : bgcolor.a_);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
color color::blend(const color& bgcolor, double alpha) const
|
||||
{
|
||||
color result;
|
||||
result.r_ = r_ * alpha + bgcolor.r_ * (1.0 - alpha);
|
||||
result.g_ = g_ * alpha + bgcolor.g_ * (1.0 - alpha);
|
||||
result.b_ = b_ * alpha + bgcolor.b_ * (1.0 - alpha);
|
||||
result.r_ = r_ * (1.0 - alpha) + bgcolor.r_ * alpha;
|
||||
result.g_ = g_ * (1.0 - alpha) + bgcolor.g_ * alpha;
|
||||
result.b_ = b_ * (1.0 - alpha) + bgcolor.b_ * alpha;
|
||||
result.a_ = 1.0;
|
||||
return result;
|
||||
}
|
||||
@ -649,12 +609,12 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
int rectangle::right() const
|
||||
int rectangle::right() const noexcept
|
||||
{
|
||||
return x + static_cast<int>(width);
|
||||
}
|
||||
|
||||
int rectangle::bottom() const
|
||||
int rectangle::bottom() const noexcept
|
||||
{
|
||||
return y + static_cast<int>(height);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The Deploy Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -21,463 +21,9 @@
|
||||
#include <windows.h>
|
||||
#elif defined(NANA_LINUX) || defined(NANA_MACOS)
|
||||
#include <string.h>
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "detail/platform_spec_selector.hpp"
|
||||
#endif
|
||||
|
||||
//Implement workarounds for GCC/MinGW which version is below 4.8.2
|
||||
#if defined(STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED)
|
||||
#include <sstream>
|
||||
namespace std
|
||||
{
|
||||
int stoi(const std::string& str, std::size_t * pos, int base)
|
||||
{
|
||||
auto sptr = str.c_str();
|
||||
char *end;
|
||||
errno = 0;
|
||||
auto result = std::strtol(sptr, &end, base);
|
||||
|
||||
if (sptr == end)
|
||||
throw std::invalid_argument("invalid stoi argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoi argument out of range");
|
||||
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - sptr);
|
||||
return ((int)result);
|
||||
}
|
||||
|
||||
int stoi(const std::wstring& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto sptr = str.data();
|
||||
wchar_t *end;
|
||||
errno = 0;
|
||||
auto result = std::wcstol(sptr, &end, base);
|
||||
|
||||
if (sptr == end)
|
||||
throw std::invalid_argument("invalid stoi argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoi argument out of range");
|
||||
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - sptr);
|
||||
return ((int)result);
|
||||
}
|
||||
using ::strtof;
|
||||
using ::strtold;
|
||||
using ::wcstold;
|
||||
using ::strtoll;
|
||||
using ::wcstoll;
|
||||
using ::strtoull;
|
||||
using ::wcstoull;
|
||||
|
||||
float stof(const std::string& str, std::size_t * pos)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char *end;
|
||||
auto result = std::strtof(ptr, &end);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stof argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
float stof(const std::wstring& str, std::size_t* pos)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t *end;
|
||||
auto result = std::wcstof(ptr, &end);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stof argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
double stod(const std::string& str, std::size_t * pos)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char *end;
|
||||
auto result = std::strtod(ptr, &end);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stod argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
double stod(const std::wstring& str, std::size_t* pos)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t *end;
|
||||
auto result = std::wcstod(ptr, &end);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stod argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
long double stold(const std::string& str, std::size_t * pos)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char *end;
|
||||
auto result = std::strtold(ptr, &end);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stold argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
long double stold(const std::wstring& str, std::size_t* pos)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t *end;
|
||||
auto result = std::wcstold(ptr, &end);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stold argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
long stol(const std::string& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char *end;
|
||||
auto result = std::strtol(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stol argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
long stol(const std::wstring& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t *end;
|
||||
auto result = std::wcstol(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stol argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
//Workaround for no implemenation of std::stoll in MinGW.
|
||||
long long stoll(const std::string& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char* end;
|
||||
auto result = std::strtoll(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoll argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
long long stoll(const std::wstring& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t* end;
|
||||
auto result = std::wcstoll(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoll argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long long stoull(const std::string& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char* end;
|
||||
auto result = std::strtoull(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoull argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long long stoull(const std::wstring& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t* end;
|
||||
auto result = std::wcstoull(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoull argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
//Workaround for no implemenation of std::stoul in MinGW.
|
||||
unsigned long stoul(const std::string& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
char* end;
|
||||
auto result = std::strtoul(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoul argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long stoul(const std::wstring& str, std::size_t* pos, int base)
|
||||
{
|
||||
auto *ptr = str.data();
|
||||
errno = 0;
|
||||
wchar_t* end;
|
||||
auto result = std::wcstoul(ptr, &end, base);
|
||||
|
||||
if (ptr == end)
|
||||
throw std::invalid_argument("invalid stod argument");
|
||||
if (errno == ERANGE)
|
||||
throw std::out_of_range("stoul argument out of range");
|
||||
if (pos)
|
||||
*pos = (std::size_t)(end - ptr);
|
||||
return result;
|
||||
}
|
||||
}//end namespace std
|
||||
#endif //STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED
|
||||
|
||||
#ifdef STD_TO_STRING_NOT_SUPPORTED
|
||||
#include <sstream>
|
||||
namespace std
|
||||
{
|
||||
std::string to_string(double v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(long double v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(unsigned v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(int v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(long v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(unsigned long v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(long long v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(unsigned long long v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(float v)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
#endif // STD_TO_STRING_NOT_SUPPORTED
|
||||
|
||||
#ifdef STD_TO_WSTRING_NOT_SUPPORTED
|
||||
#include <sstream>
|
||||
namespace std
|
||||
{
|
||||
std::wstring to_wstring(double v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(long double v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(unsigned v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(int v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(long v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(unsigned long v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(long long v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(unsigned long long v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring to_wstring(float v)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//#ifdef STD_put_time_NOT_SUPPORTED
|
||||
#include <ctime>
|
||||
#include <cwchar>
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::put_time in gcc < 5.
|
||||
/* std unspecified return type */
|
||||
//template< class CharT, class RTSTR >// let fail for CharT != char / wchar_t
|
||||
//RTSTR put_time(const std::tm* tmb, const CharT* fmt);
|
||||
|
||||
//template< >
|
||||
std::string put_time/*<char, std::string>*/(const std::tm* tmb, const char* fmt)
|
||||
{
|
||||
std::size_t sz = 200;
|
||||
std::string str(sz, '\0');
|
||||
sz = std::strftime(&str[0], str.size() - 1, fmt, tmb);
|
||||
str.resize(sz);
|
||||
return str;
|
||||
}
|
||||
//Defined in header <ctime>
|
||||
// std::size_t strftime(char* str, std::size_t count, const char* format, const std::tm* time);
|
||||
//template<>
|
||||
//std::wstring put_time<wchar_t, std::wstring>(const std::tm* tmb, const wchar_t* fmt)
|
||||
//{
|
||||
// unsigned sz = 200;
|
||||
// std::wstring str(sz, L'\0');
|
||||
// sz = std::wcsftime(&str[0], str.size() - 1, fmt, tmb);
|
||||
// str.resize(sz);
|
||||
// return str;
|
||||
//}
|
||||
// http://en.cppreference.com/w/cpp/chrono/c/wcsftime
|
||||
// Defined in header <cwchar>
|
||||
// std::size_t wcsftime(wchar_t* str, std::size_t count, const wchar_t* format, const std::tm* time);
|
||||
// Converts the date and time information from a given calendar time time to a null - terminated
|
||||
// wide character string str according to format string format.Up to count bytes are written.
|
||||
// Parameters
|
||||
// str - pointer to the first element of the wchar_t array for output
|
||||
// count - maximum number of wide characters to write
|
||||
// format - pointer to a null - terminated wide character string specifying the format of conversion.
|
||||
|
||||
}
|
||||
//#endif // STD_put_time_NOT_SUPPORTED
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -523,12 +69,12 @@ namespace nana
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void utf8_Error::emit()
|
||||
{
|
||||
if (use_throw)
|
||||
throw utf8_Error(*this);
|
||||
std::cerr << what();
|
||||
}
|
||||
void utf8_Error::emit()
|
||||
{
|
||||
if (use_throw)
|
||||
throw utf8_Error(*this);
|
||||
std::cerr << what();
|
||||
}
|
||||
|
||||
//bool utf8_Error::use_throw{true};
|
||||
bool utf8_Error::use_throw{ false };
|
||||
@ -536,25 +82,18 @@ namespace nana
|
||||
|
||||
void throw_not_utf8(const std::string& text)
|
||||
{
|
||||
if (!is_utf8(text.c_str(), text.length()))
|
||||
return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit();
|
||||
throw_not_utf8(text.c_str(), text.size());
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text)
|
||||
{
|
||||
throw_not_utf8(text, std::strlen(text));
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text, std::size_t len)
|
||||
{
|
||||
if (!is_utf8(text, len))
|
||||
return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len) ).emit();
|
||||
|
||||
//throw std::invalid_argument("The text is not encoded in UTF8");
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text)
|
||||
{
|
||||
if (!is_utf8(text, std::strlen(text)))
|
||||
return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit();
|
||||
|
||||
//throw std::invalid_argument("The text is not encoded in UTF8");
|
||||
|
||||
}
|
||||
|
||||
std::string recode_to_utf8(std::string no_utf8)
|
||||
@ -587,8 +126,6 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::string& to_utf8(const std::string& str)
|
||||
{
|
||||
return str;
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#include "../platform_abstraction_types.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
|
||||
@ -87,31 +89,16 @@ namespace detail
|
||||
};
|
||||
};
|
||||
|
||||
struct font_tag
|
||||
{
|
||||
native_string_type name;
|
||||
unsigned height;
|
||||
unsigned weight;
|
||||
bool italic;
|
||||
bool underline;
|
||||
bool strikeout;
|
||||
HFONT handle;
|
||||
|
||||
struct deleter
|
||||
{
|
||||
void operator()(const font_tag*) const;
|
||||
};
|
||||
};
|
||||
|
||||
struct drawable_impl_type
|
||||
{
|
||||
typedef std::shared_ptr<font_tag> font_ptr_t;
|
||||
using font_type = ::std::shared_ptr<font_interface>;
|
||||
|
||||
HDC context;
|
||||
HBITMAP pixmap;
|
||||
pixel_argb_t* pixbuf_ptr{nullptr};
|
||||
std::size_t bytes_per_line{0};
|
||||
font_ptr_t font;
|
||||
|
||||
font_type font;
|
||||
|
||||
struct pen_spec
|
||||
{
|
||||
@ -179,7 +166,6 @@ namespace detail
|
||||
platform_spec(platform_spec&&) = delete;
|
||||
platform_spec& operator=(platform_spec&&) = delete;
|
||||
public:
|
||||
typedef drawable_impl_type::font_ptr_t font_ptr_t;
|
||||
typedef ::nana::event_code event_code;
|
||||
typedef ::nana::native_window_type native_window_type;
|
||||
|
||||
@ -200,12 +186,6 @@ namespace detail
|
||||
|
||||
~platform_spec();
|
||||
|
||||
const font_ptr_t& default_native_font() const;
|
||||
void default_native_font(const font_ptr_t&);
|
||||
unsigned font_size_to_height(unsigned) const;
|
||||
unsigned font_height_to_size(unsigned) const;
|
||||
font_ptr_t make_native_font(const char* name, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out);
|
||||
|
||||
static platform_spec& instance();
|
||||
|
||||
void keep_window_icon(native_window_type, const paint::image&sml_icon, const paint::image& big_icon);
|
||||
408
source/detail/platform_abstraction.cpp
Normal file
408
source/detail/platform_abstraction.cpp
Normal file
@ -0,0 +1,408 @@
|
||||
#include "platform_abstraction.hpp"
|
||||
#include <nana/deploy.hpp>
|
||||
#include "../paint/truetype.hpp"
|
||||
|
||||
#ifdef NANA_WINDOWS
|
||||
# include <windows.h>
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* VersionHelpers.h -- This module defines helper functions to *
|
||||
* promote version check with proper *
|
||||
* comparisons. *
|
||||
* *
|
||||
* Copyright (c) Microsoft Corp. All rights reserved. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#include <specstrings.h> // for _In_, etc.
|
||||
|
||||
#if !defined(__midl) && !defined(SORTPP_PASS)
|
||||
|
||||
#if (NTDDI_VERSION >= NTDDI_WINXP)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define VERSIONHELPERAPI inline bool
|
||||
|
||||
#else // __cplusplus
|
||||
|
||||
#define VERSIONHELPERAPI FORCEINLINE BOOL
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0 };
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
|
||||
osvi.dwMajorVersion = wMajorVersion;
|
||||
osvi.dwMinorVersion = wMinorVersion;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPOrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP3OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaOrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaSP1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaSP2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows7OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows7SP1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
|
||||
}
|
||||
|
||||
#ifndef _WIN32_WINNT_WIN8 // (0x0602)
|
||||
#define _WIN32_WINNT_WIN8 (0x0602)
|
||||
#endif // _WIN32_WINNT_WIN8(0x0602)
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows8OrGreater()
|
||||
{
|
||||
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
|
||||
}
|
||||
|
||||
#ifndef _WIN32_WINNT_WINBLUE // (0x0602)
|
||||
#define _WIN32_WINNT_WINBLUE (0x0602)
|
||||
#endif // _WIN32_WINNT_WINBLUE (0x0602)
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows8Point1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsServer()
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0, 0, VER_NT_WORKSTATION };
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
|
||||
|
||||
return !VerifyVersionInfoW(&osvi, VER_PRODUCT_TYPE, dwlConditionMask);
|
||||
}
|
||||
|
||||
#endif // NTDDI_VERSION
|
||||
|
||||
#endif // defined(__midl)
|
||||
#else
|
||||
# include "posix/platform_spec.hpp"
|
||||
# include <fontconfig/fontconfig.h>
|
||||
# if defined(NANA_USE_XFT)
|
||||
# include <X11/Xft/Xft.h>
|
||||
# include <iconv.h>
|
||||
# include <fstream>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace nana
|
||||
{
|
||||
|
||||
class internal_font
|
||||
: public font_interface
|
||||
{
|
||||
public:
|
||||
using path_type = std::experimental::filesystem::path;
|
||||
|
||||
internal_font(const path_type& ttf, const std::string& font_family, double font_size, const font_style& fs, native_font_type native_font):
|
||||
ttf_(ttf),
|
||||
family_(font_family),
|
||||
size_(font_size),
|
||||
style_(fs),
|
||||
native_handle_(native_font)
|
||||
{}
|
||||
|
||||
~internal_font()
|
||||
{
|
||||
#ifdef NANA_WINDOWS
|
||||
::DeleteObject(reinterpret_cast<HFONT>(native_handle_));
|
||||
#elif defined(NANA_X11)
|
||||
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
||||
# ifdef NANA_USE_XFT
|
||||
::XftFontClose(disp, reinterpret_cast<XftFont*>(native_handle_));
|
||||
# else
|
||||
::XFreeFontSet(disp, reinterpret_cast<XFontSet>(native_handle_));
|
||||
# endif
|
||||
#endif
|
||||
if (!ttf_.empty())
|
||||
platform_abstraction::font_resource(false, ttf_);
|
||||
}
|
||||
public:
|
||||
const std::string& family() const override
|
||||
{
|
||||
return family_;
|
||||
}
|
||||
|
||||
double size() const override
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
const font_style & style() const override
|
||||
{
|
||||
return style_;
|
||||
}
|
||||
|
||||
native_font_type native_handle() const override
|
||||
{
|
||||
return native_handle_;
|
||||
}
|
||||
private:
|
||||
path_type const ttf_;
|
||||
std::string const family_;
|
||||
double const size_;
|
||||
font_style const style_;
|
||||
native_font_type const native_handle_;
|
||||
};
|
||||
|
||||
struct platform_runtime
|
||||
{
|
||||
std::shared_ptr<font_interface> font;
|
||||
|
||||
#ifdef NANA_X11
|
||||
std::map<std::string, std::size_t> fontconfig_counts;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace data
|
||||
{
|
||||
static platform_runtime* storage;
|
||||
}
|
||||
}
|
||||
|
||||
static platform_runtime& platform_storage()
|
||||
{
|
||||
if (nullptr == data::storage)
|
||||
throw std::runtime_error("platform_abstraction is empty");
|
||||
|
||||
return *data::storage;
|
||||
}
|
||||
|
||||
void platform_abstraction::initialize()
|
||||
{
|
||||
if (nullptr == data::storage)
|
||||
data::storage = new platform_runtime;
|
||||
}
|
||||
|
||||
void platform_abstraction::shutdown()
|
||||
{
|
||||
auto & r = platform_storage();
|
||||
|
||||
if (r.font.use_count() > 1)
|
||||
throw std::runtime_error("platform_abstraction is disallowed to shutdown");
|
||||
|
||||
r.font.reset();
|
||||
|
||||
delete data::storage;
|
||||
data::storage = nullptr;
|
||||
}
|
||||
|
||||
::std::shared_ptr<platform_abstraction::font> platform_abstraction::default_font(const ::std::shared_ptr<font>& new_font)
|
||||
{
|
||||
auto & r = platform_storage();
|
||||
if (new_font)
|
||||
{
|
||||
auto f = r.font;
|
||||
if (new_font != r.font)
|
||||
r.font = new_font;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
if (!r.font)
|
||||
r.font = make_font({}, 0, {});
|
||||
|
||||
return r.font;
|
||||
}
|
||||
|
||||
static std::shared_ptr<platform_abstraction::font> font_factory(::std::string font_family, double size_pt, const platform_abstraction::font::font_style& fs, internal_font::path_type ttf)
|
||||
{
|
||||
using native_font_type = platform_abstraction::font::native_font_type;
|
||||
#ifdef NANA_WINDOWS
|
||||
std::wstring wfont_family = to_nstring(font_family);
|
||||
|
||||
//Make sure the length of font family less than LF_FACESIZE which is defined by Windows
|
||||
if (wfont_family.length() + 1 > LF_FACESIZE)
|
||||
wfont_family.clear();
|
||||
|
||||
//Translate pt to px
|
||||
auto hDC = ::GetDC(nullptr);
|
||||
auto font_height = -static_cast<LONG>(size_pt * ::GetDeviceCaps(hDC, LOGPIXELSY) / 72);
|
||||
::ReleaseDC(nullptr, hDC);
|
||||
|
||||
if (wfont_family.empty() || (0 == font_height))
|
||||
{
|
||||
//Create default font object.
|
||||
NONCLIENTMETRICS metrics = {};
|
||||
metrics.cbSize = sizeof metrics;
|
||||
#if(WINVER >= 0x0600)
|
||||
#if defined(NANA_MINGW)
|
||||
OSVERSIONINFO osvi = {};
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
::GetVersionEx(&osvi);
|
||||
if (osvi.dwMajorVersion < 6)
|
||||
metrics.cbSize -= sizeof(metrics.iPaddedBorderWidth);
|
||||
#else
|
||||
if (!IsWindowsVistaOrGreater())
|
||||
metrics.cbSize -= sizeof(metrics.iPaddedBorderWidth);
|
||||
#endif
|
||||
#endif
|
||||
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof metrics, &metrics, 0);
|
||||
|
||||
if (wfont_family.empty())
|
||||
{
|
||||
wfont_family = metrics.lfMessageFont.lfFaceName;
|
||||
font_family = to_utf8(wfont_family);
|
||||
}
|
||||
|
||||
if (0 == font_height)
|
||||
font_height = metrics.lfMessageFont.lfHeight;
|
||||
}
|
||||
|
||||
|
||||
::LOGFONT lf{};
|
||||
|
||||
std::wcscpy(lf.lfFaceName, wfont_family.c_str());
|
||||
lf.lfHeight = font_height;
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
lf.lfWeight = fs.weight;
|
||||
lf.lfQuality = PROOF_QUALITY;
|
||||
lf.lfPitchAndFamily = FIXED_PITCH;
|
||||
lf.lfItalic = fs.italic;
|
||||
lf.lfUnderline = fs.underline;
|
||||
lf.lfStrikeOut = fs.strike_out;
|
||||
|
||||
auto fd = ::CreateFontIndirect(&lf);
|
||||
#elif defined(NANA_X11)
|
||||
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
||||
# ifdef NANA_USE_XFT
|
||||
if(font_family.empty())
|
||||
font_family = '*';
|
||||
|
||||
std::string pat_str = font_family + '-' + std::to_string(size_pt ? size_pt : 10);
|
||||
auto pat = ::XftNameParse(pat_str.c_str());
|
||||
XftResult res;
|
||||
auto match_pat = ::XftFontMatch(disp, ::XDefaultScreen(disp), pat, &res);
|
||||
|
||||
::XftFont* fd = nullptr;
|
||||
if (match_pat)
|
||||
fd = ::XftFontOpenPattern(disp, match_pat);
|
||||
# else
|
||||
std::string pat_str;
|
||||
if (font_family.empty())
|
||||
pat_str = "-misc-fixed-*";
|
||||
else
|
||||
pat_str = "-misc-fixed-" + font_family;
|
||||
|
||||
char ** missing_list;
|
||||
int missing_count;
|
||||
char * defstr;
|
||||
XFontSet fd = ::XCreateFontSet(display_, const_cast<char*>(pat_str.c_str()), &missing_list, &missing_count, &defstr);
|
||||
# endif
|
||||
#endif
|
||||
if (fd)
|
||||
return std::make_shared<internal_font>(std::move(ttf), std::move(font_family), size_pt, fs, reinterpret_cast<native_font_type>(fd));
|
||||
return{};
|
||||
}
|
||||
|
||||
::std::shared_ptr<platform_abstraction::font> platform_abstraction::make_font(const std::string& font_family, double size_pt, const font::font_style& fs)
|
||||
{
|
||||
return font_factory(font_family, size_pt, fs, {});
|
||||
}
|
||||
|
||||
::std::shared_ptr<platform_abstraction::font> platform_abstraction::make_font_from_ttf(const path_type& ttf, double size_pt, const font::font_style& fs)
|
||||
{
|
||||
::nana::spec::truetype truetype{ ttf };
|
||||
if (truetype.font_family().empty())
|
||||
return nullptr;
|
||||
|
||||
font_resource(true, ttf);
|
||||
|
||||
return font_factory(truetype.font_family(), size_pt, fs, ttf);
|
||||
}
|
||||
|
||||
void platform_abstraction::font_resource(bool try_add, const path_type& ttf)
|
||||
{
|
||||
#ifdef NANA_WINDOWS
|
||||
if (try_add)
|
||||
::AddFontResourceEx(ttf.wstring().c_str(), FR_PRIVATE, nullptr);
|
||||
else
|
||||
::RemoveFontResourceEx(ttf.wstring().c_str(), FR_PRIVATE, nullptr);
|
||||
#else
|
||||
auto & fc = platform_storage().fontconfig_counts;
|
||||
if(try_add)
|
||||
{
|
||||
if(1 == ++(fc[ttf.string()]))
|
||||
{
|
||||
::FcConfigAppFontAddFile(nullptr, reinterpret_cast<const FcChar8*>(ttf.string().c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto i = fc.find(ttf.string());
|
||||
if(i != fc.end())
|
||||
{
|
||||
if(0 == --(i->second))
|
||||
fc.erase(i);
|
||||
|
||||
if(0 == fc.size())
|
||||
::FcConfigAppFontClear(nullptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
43
source/detail/platform_abstraction.hpp
Normal file
43
source/detail/platform_abstraction.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Platform Abstraction
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/detail/platform_spec.hpp
|
||||
*
|
||||
* The platform_abstraction provides some functions and types for the abstract
|
||||
* system platform.
|
||||
*/
|
||||
#ifndef NANA_DETAIL_PLATFORM_ABSTRACTION_HEADER_INCLUDED
|
||||
#define NANA_DETAIL_PLATFORM_ABSTRACTION_HEADER_INCLUDED
|
||||
|
||||
#include "platform_abstraction_types.hpp"
|
||||
#include <memory>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
|
||||
|
||||
class platform_abstraction
|
||||
{
|
||||
public:
|
||||
using font = font_interface;
|
||||
|
||||
using path_type = ::std::experimental::filesystem::path;
|
||||
|
||||
static void initialize();
|
||||
/// Shutdown before destruction of platform_spec
|
||||
static void shutdown();
|
||||
static ::std::shared_ptr<font> default_font(const ::std::shared_ptr<font>&);
|
||||
static ::std::shared_ptr<font> make_font(const ::std::string& font_family, double size_pt, const font::font_style& fs);
|
||||
static ::std::shared_ptr<font> make_font_from_ttf(const path_type& ttf, double size_pt, const font::font_style& fs);
|
||||
static void font_resource(bool try_add, const path_type& ttf);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
29
source/detail/platform_abstraction_types.hpp
Normal file
29
source/detail/platform_abstraction_types.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef NANA_DETAIL_PLATFORM_ABSTRACTION_TYPES_HEADER_INCLUDED
|
||||
#define NANA_DETAIL_PLATFORM_ABSTRACTION_TYPES_HEADER_INCLUDED
|
||||
#include <nana/config.hpp>
|
||||
#include <nana/paint/detail/ptdefs.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef NANA_X11
|
||||
# define NANA_USE_XFT
|
||||
#endif
|
||||
|
||||
namespace nana
|
||||
{
|
||||
class font_interface
|
||||
{
|
||||
public:
|
||||
using font_style = detail::font_style;
|
||||
using native_font_type = paint::native_font_type;
|
||||
|
||||
virtual ~font_interface() = default;
|
||||
|
||||
virtual const std::string& family() const = 0;
|
||||
virtual double size() const = 0;
|
||||
virtual const font_style & style() const = 0;
|
||||
virtual native_font_type native_handle() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Platform Specification Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Nana Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -14,7 +14,8 @@
|
||||
* http://standards.freedesktop.org/clipboards-spec/clipboards-0.1.txt
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "platform_spec_selector.hpp"
|
||||
#include "platform_abstraction.hpp"
|
||||
#if defined(NANA_POSIX) && defined(NANA_X11)
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
@ -33,7 +34,7 @@
|
||||
#include <errno.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "x11/msg_dispatcher.hpp"
|
||||
#include "posix/msg_dispatcher.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -451,24 +452,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
class font_deleter
|
||||
{
|
||||
public:
|
||||
void operator()(const font_tag* fp) const
|
||||
{
|
||||
if(fp && fp->handle)
|
||||
{
|
||||
platform_scope_guard psg;
|
||||
#if defined(NANA_USE_XFT)
|
||||
::XftFontClose(nana::detail::platform_spec::instance().open_display(), fp->handle);
|
||||
#else
|
||||
::XFreeFontSet(nana::detail::platform_spec::instance().open_display(), fp->handle);
|
||||
#endif
|
||||
}
|
||||
delete fp;
|
||||
}
|
||||
};//end class font_deleter
|
||||
|
||||
platform_scope_guard::platform_scope_guard()
|
||||
{
|
||||
platform_spec::instance().lock_xlib();
|
||||
@ -561,9 +544,9 @@ namespace detail
|
||||
atombase_.xdnd_typelist = ::XInternAtom(display_, "XdndTypeList", False);
|
||||
atombase_.xdnd_finished = ::XInternAtom(display_, "XdndFinished", False);
|
||||
|
||||
//Create default font object.
|
||||
def_font_ptr_ = make_native_font(nullptr, font_size_to_height(10), 400, false, false, false);
|
||||
msg_dispatcher_ = new msg_dispatcher(display_);
|
||||
|
||||
platform_abstraction::initialize();
|
||||
}
|
||||
|
||||
platform_spec::~platform_spec()
|
||||
@ -572,75 +555,11 @@ namespace detail
|
||||
|
||||
//The font should be destroyed before closing display,
|
||||
//otherwise it crashs
|
||||
def_font_ptr_.reset();
|
||||
platform_abstraction::shutdown();
|
||||
|
||||
close_display();
|
||||
}
|
||||
|
||||
const platform_spec::font_ptr_t& platform_spec::default_native_font() const
|
||||
{
|
||||
return def_font_ptr_;
|
||||
}
|
||||
|
||||
void platform_spec::default_native_font(const font_ptr_t& fp)
|
||||
{
|
||||
def_font_ptr_ = fp;
|
||||
}
|
||||
|
||||
unsigned platform_spec::font_size_to_height(unsigned size) const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned platform_spec::font_height_to_size(unsigned height) const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
platform_spec::font_ptr_t platform_spec::make_native_font(const char* name, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out)
|
||||
{
|
||||
font_ptr_t ref;
|
||||
#if 1 //Xft
|
||||
if(0 == name || *name == 0)
|
||||
name = "*";
|
||||
|
||||
XftFont* handle = 0;
|
||||
std::stringstream ss;
|
||||
ss<<name<<"-"<<(height ? height : 10);
|
||||
XftPattern * pat = ::XftNameParse(ss.str().c_str());
|
||||
XftResult res;
|
||||
XftPattern * match_pat = ::XftFontMatch(display_, ::XDefaultScreen(display_), pat, &res);
|
||||
if(match_pat)
|
||||
handle = ::XftFontOpenPattern(display_, match_pat);
|
||||
#else
|
||||
std::string basestr;
|
||||
if(0 == name || *name == 0)
|
||||
{
|
||||
basestr = "-misc-fixed-*";
|
||||
}
|
||||
else
|
||||
basestr = "-misc-fixed-*";
|
||||
|
||||
char ** missing_list;
|
||||
int missing_count;
|
||||
char * defstr;
|
||||
XFontSet handle = ::XCreateFontSet(display_, const_cast<char*>(basestr.c_str()), &missing_list, &missing_count, &defstr);
|
||||
#endif
|
||||
if(handle)
|
||||
{
|
||||
font_tag * impl = new font_tag;
|
||||
impl->name = name;
|
||||
impl->height = height;
|
||||
impl->weight = weight;
|
||||
impl->italic = italic;
|
||||
impl->underline = underline;
|
||||
impl->strikeout = strike_out;
|
||||
impl->handle = handle;
|
||||
return font_ptr_t(impl, font_deleter());
|
||||
}
|
||||
return font_ptr_t();
|
||||
}
|
||||
|
||||
Display* platform_spec::open_display()
|
||||
{
|
||||
return display_;
|
||||
@ -1131,6 +1050,7 @@ namespace detail
|
||||
void platform_spec::write_selection(native_window_type owner, Atom type, const void * buf, size_t bufsize)
|
||||
{
|
||||
platform_scope_guard psg;
|
||||
::XSetSelectionOwner(display_, XA_PRIMARY, reinterpret_cast<Window>(owner), CurrentTime);
|
||||
::XSetSelectionOwner(display_, atombase_.clipboard, reinterpret_cast<Window>(owner), CurrentTime);
|
||||
::XFlush(display_);
|
||||
if(XA_STRING == type || atombase_.utf8_string == type)
|
||||
@ -1162,8 +1082,16 @@ namespace detail
|
||||
// 2 = msg_dispatcher should ignore the msg, because the XEvent is processed by _m_msg_filter
|
||||
int platform_spec::_m_msg_filter(XEvent& evt, msg_packet_tag& msg)
|
||||
{
|
||||
auto & bedrock = detail::bedrock::instance();
|
||||
|
||||
platform_spec & self = instance();
|
||||
if(SelectionNotify == evt.type)
|
||||
if(KeyPress == evt.type || KeyRelease == evt.type)
|
||||
{
|
||||
auto menu_wd = bedrock.get_menu(reinterpret_cast<native_window_type>(evt.xkey.window), true);
|
||||
if(menu_wd)
|
||||
evt.xkey.window = reinterpret_cast<Window>(menu_wd);
|
||||
}
|
||||
else if(SelectionNotify == evt.type)
|
||||
{
|
||||
if(evt.xselection.property)
|
||||
{
|
||||
@ -1196,7 +1124,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.selection_.items.erase(self.selection_.items.begin());
|
||||
|
||||
std::lock_guard<decltype(im->cond_mutex)> lock(im->cond_mutex);
|
||||
@ -1372,9 +1299,8 @@ namespace detail
|
||||
{
|
||||
Window child;
|
||||
::XTranslateCoordinates(self.display_, self.root_window(), evt.xclient.window, x, y, &self.xdnd_.pos.x, &self.xdnd_.pos.y, &child);
|
||||
typedef detail::bedrock bedrock;
|
||||
|
||||
auto wd = bedrock::instance().wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos.x, self.xdnd_.pos.y);
|
||||
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos);
|
||||
if(wd && wd->flags.dropable)
|
||||
{
|
||||
accepted = true;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include <nana/config.hpp>
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <nana/detail/win32/platform_spec.hpp>
|
||||
#include "mswin/platform_spec.hpp"
|
||||
#elif defined(NANA_LINUX) || defined(NANA_MACOS)
|
||||
#include <nana/detail/linux_X11/platform_spec.hpp>
|
||||
#include "posix/platform_spec.hpp"
|
||||
#endif
|
||||
@ -12,15 +12,18 @@
|
||||
* @brief basis classes and data structures required by nana
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "platform_spec_selector.hpp"
|
||||
#include "platform_abstraction.hpp"
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/******************************************************************
|
||||
@ -310,15 +313,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
//struct font_tag::deleter
|
||||
void font_tag::deleter::operator()(const font_tag* tag) const
|
||||
{
|
||||
if(tag && tag->handle)
|
||||
::DeleteObject(tag->handle);
|
||||
delete tag;
|
||||
}
|
||||
//end struct font_tag::deleter
|
||||
|
||||
//class platform_spec
|
||||
platform_spec::co_initializer::co_initializer()
|
||||
: ole32_(::LoadLibrary(L"OLE32.DLL"))
|
||||
@ -354,104 +348,21 @@ namespace detail
|
||||
|
||||
struct platform_spec::implementation
|
||||
{
|
||||
font_ptr_t def_font_ptr;
|
||||
std::map<native_window_type, window_icons> iconbase;
|
||||
};
|
||||
|
||||
platform_spec::platform_spec()
|
||||
: impl_{ new implementation}
|
||||
{
|
||||
//Create default font object.
|
||||
NONCLIENTMETRICS metrics = {};
|
||||
metrics.cbSize = sizeof metrics;
|
||||
#if(WINVER >= 0x0600)
|
||||
#if defined(NANA_MINGW)
|
||||
OSVERSIONINFO osvi = {};
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
::GetVersionEx(&osvi);
|
||||
if (osvi.dwMajorVersion < 6)
|
||||
metrics.cbSize -= sizeof(metrics.iPaddedBorderWidth);
|
||||
#else
|
||||
if(!IsWindowsVistaOrGreater())
|
||||
metrics.cbSize -= sizeof(metrics.iPaddedBorderWidth);
|
||||
#endif
|
||||
#endif
|
||||
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof metrics, &metrics, 0);
|
||||
impl_->def_font_ptr = make_native_font(to_utf8(metrics.lfMessageFont.lfFaceName).c_str(), font_size_to_height(9), 400, false, false, false);
|
||||
platform_abstraction::initialize();
|
||||
}
|
||||
|
||||
platform_spec::~platform_spec()
|
||||
{
|
||||
platform_abstraction::shutdown();
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
const platform_spec::font_ptr_t& platform_spec::default_native_font() const
|
||||
{
|
||||
return impl_->def_font_ptr;
|
||||
}
|
||||
|
||||
void platform_spec::default_native_font(const font_ptr_t& fp)
|
||||
{
|
||||
impl_->def_font_ptr = fp;
|
||||
}
|
||||
|
||||
unsigned platform_spec::font_size_to_height(unsigned size) const
|
||||
{
|
||||
HDC hdc = ::GetDC(0);
|
||||
size = ::MulDiv(int(size), ::GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
||||
::ReleaseDC(0, hdc);
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned platform_spec::font_height_to_size(unsigned height) const
|
||||
{
|
||||
HDC hdc = ::GetDC(0);
|
||||
unsigned pixels = ::GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
::ReleaseDC(0, hdc);
|
||||
|
||||
height = static_cast<unsigned>(static_cast<long long>(72) * height / pixels);
|
||||
return height;
|
||||
}
|
||||
|
||||
platform_spec::font_ptr_t platform_spec::make_native_font(const char* name, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out)
|
||||
{
|
||||
::LOGFONT logfont;
|
||||
memset(&logfont, 0, sizeof logfont);
|
||||
|
||||
if (name && *name)
|
||||
std::wcscpy(logfont.lfFaceName, to_wstring(name).c_str());
|
||||
else
|
||||
std::wcscpy(logfont.lfFaceName, impl_->def_font_ptr->name.c_str());
|
||||
|
||||
logfont.lfCharSet = DEFAULT_CHARSET;
|
||||
HDC hdc = ::GetDC(0);
|
||||
logfont.lfHeight = -static_cast<int>(height);
|
||||
::ReleaseDC(0, hdc);
|
||||
|
||||
logfont.lfWidth = 0;
|
||||
logfont.lfWeight = weight;
|
||||
logfont.lfQuality = PROOF_QUALITY;
|
||||
logfont.lfPitchAndFamily = FIXED_PITCH;
|
||||
logfont.lfItalic = italic;
|
||||
logfont.lfUnderline = underline;
|
||||
logfont.lfStrikeOut = strike_out;
|
||||
HFONT result = ::CreateFontIndirect(&logfont);
|
||||
|
||||
if(result)
|
||||
{
|
||||
font_tag * impl = new font_tag;
|
||||
impl->name = logfont.lfFaceName;
|
||||
impl->height = height;
|
||||
impl->weight = weight;
|
||||
impl->italic = italic;
|
||||
impl->underline = underline;
|
||||
impl->strikeout = strike_out;
|
||||
impl->handle = result;
|
||||
return std::shared_ptr<font_tag>(impl, font_tag::deleter());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
platform_spec& platform_spec::instance()
|
||||
{
|
||||
static platform_spec object;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Message Dispatcher Implementation
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
#ifndef NANA_DETAIL_MSG_DISPATCHER_HPP
|
||||
#define NANA_DETAIL_MSG_DISPATCHER_HPP
|
||||
#include <nana/detail/linux_X11/msg_packet.hpp>
|
||||
#include "msg_packet.hpp"
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <list>
|
||||
#include <set>
|
||||
@ -51,13 +51,22 @@ namespace detail
|
||||
typedef std::list<msg_packet_tag> msg_queue_type;
|
||||
|
||||
msg_dispatcher(Display* disp)
|
||||
: display_(disp), is_work_(false)
|
||||
: display_(disp)
|
||||
{
|
||||
proc_.event_proc = 0;
|
||||
proc_.timer_proc = 0;
|
||||
proc_.filter_proc = 0;
|
||||
}
|
||||
|
||||
~msg_dispatcher()
|
||||
{
|
||||
if(thrd_ && thrd_->joinable())
|
||||
{
|
||||
is_work_ = false;
|
||||
thrd_->join();
|
||||
}
|
||||
}
|
||||
|
||||
void set(timer_proc_type timer_proc, event_proc_type event_proc, event_filter_type filter)
|
||||
{
|
||||
proc_.timer_proc = timer_proc;
|
||||
@ -329,7 +338,7 @@ namespace detail
|
||||
|
||||
private:
|
||||
Display * display_;
|
||||
volatile bool is_work_;
|
||||
volatile bool is_work_{ false };
|
||||
std::unique_ptr<std::thread> thrd_;
|
||||
|
||||
struct table_tag
|
||||
@ -36,8 +36,8 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "msg_packet.hpp"
|
||||
#include "../platform_abstraction_types.hpp"
|
||||
|
||||
#define NANA_USE_XFT
|
||||
#if defined(NANA_USE_XFT)
|
||||
#include <X11/Xft/Xft.h>
|
||||
#include <iconv.h>
|
||||
@ -49,6 +49,7 @@ namespace nana
|
||||
namespace detail
|
||||
{
|
||||
class msg_dispatcher;
|
||||
|
||||
#if defined(NANA_USE_XFT)
|
||||
class conf
|
||||
{
|
||||
@ -74,28 +75,14 @@ namespace detail
|
||||
};
|
||||
#endif
|
||||
|
||||
struct font_tag
|
||||
{
|
||||
std::string name;
|
||||
unsigned height;
|
||||
unsigned weight;
|
||||
bool italic;
|
||||
bool underline;
|
||||
bool strikeout;
|
||||
#if defined(NANA_USE_XFT)
|
||||
XftFont * handle;
|
||||
#else
|
||||
XFontSet handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct drawable_impl_type
|
||||
{
|
||||
typedef std::shared_ptr<font_tag> font_ptr_t;
|
||||
using font_type = ::std::shared_ptr<font_interface>;
|
||||
|
||||
Pixmap pixmap;
|
||||
GC context;
|
||||
font_ptr_t font;
|
||||
|
||||
font_type font;
|
||||
|
||||
nana::point line_begin_pos;
|
||||
|
||||
@ -105,6 +92,7 @@ namespace detail
|
||||
unsigned tab_pixels;
|
||||
unsigned whitespace_pixels;
|
||||
}string;
|
||||
|
||||
#if defined(NANA_USE_XFT)
|
||||
XftDraw * xftdraw{nullptr};
|
||||
XftColor xft_fgcolor;
|
||||
@ -199,7 +187,6 @@ namespace detail
|
||||
public:
|
||||
int error_code;
|
||||
public:
|
||||
typedef drawable_impl_type::font_ptr_t font_ptr_t;
|
||||
typedef void (*timer_proc_type)(unsigned tid);
|
||||
typedef void (*event_proc_type)(Display*, msg_packet_tag&);
|
||||
typedef ::nana::event_code event_code;
|
||||
@ -211,12 +198,6 @@ namespace detail
|
||||
platform_spec();
|
||||
~platform_spec();
|
||||
|
||||
const font_ptr_t& default_native_font() const;
|
||||
void default_native_font(const font_ptr_t&);
|
||||
unsigned font_size_to_height(unsigned) const;
|
||||
unsigned font_height_to_size(unsigned) const;
|
||||
font_ptr_t make_native_font(const char* name, unsigned height, unsigned weight, bool italic, bool underline, bool strick_out);
|
||||
|
||||
Display* open_display();
|
||||
void close_display();
|
||||
|
||||
@ -277,7 +258,7 @@ namespace detail
|
||||
Display* display_;
|
||||
Colormap colormap_;
|
||||
atombase_tag atombase_;
|
||||
font_ptr_t def_font_ptr_;
|
||||
|
||||
XKeyEvent key_state_;
|
||||
int (*def_X11_error_handler_)(Display*, XErrorEvent*);
|
||||
Window grab_;
|
||||
@ -845,7 +845,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast<GetFileSizeEx_fptr_t>(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx"));
|
||||
if (get_file_size_ex)
|
||||
{
|
||||
HANDLE handle = ::CreateFile(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
HANDLE handle = ::CreateFile(p.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (INVALID_HANDLE_VALUE != handle)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
|
||||
@ -323,7 +323,7 @@ namespace nana
|
||||
{
|
||||
for (auto wd = this; wd; wd = wd->parent)
|
||||
{
|
||||
if (basic_window::update_state::refresh == wd->other.upd_state)
|
||||
if (basic_window::update_state::refreshed == wd->other.upd_state)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Bedrock Platform-Independent Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -10,7 +10,7 @@
|
||||
* @file: nana/gui/detail/bedrock_pi.cpp
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#include <nana/gui/detail/bedrock_pi_data.hpp>
|
||||
#include <nana/gui/detail/event_code.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
@ -119,6 +119,27 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::close_thread_window(unsigned thread_id)
|
||||
{
|
||||
std::vector<core_window_t*> v;
|
||||
wd_manager().all_handles(v);
|
||||
|
||||
std::vector<native_window_type> roots;
|
||||
native_window_type root = nullptr;
|
||||
for (auto wd : v)
|
||||
{
|
||||
if (((0 == thread_id) || (wd->thread_id == thread_id)) && (wd->root != root))
|
||||
{
|
||||
root = wd->root;
|
||||
if (roots.cend() == std::find(roots.cbegin(), roots.cend(), root))
|
||||
roots.emplace_back(root);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i : roots)
|
||||
native_interface::close_window(i);
|
||||
}
|
||||
|
||||
void bedrock::event_expose(core_window_t * wd, bool exposed)
|
||||
{
|
||||
if (nullptr == wd) return;
|
||||
@ -237,7 +258,7 @@ namespace nana
|
||||
return;
|
||||
|
||||
native_interface::calc_window_point(native_handle, pos);
|
||||
if (wd != wd_manager().find_window(native_handle, pos.x, pos.y))
|
||||
if (wd != wd_manager().find_window(native_handle, pos))
|
||||
return;
|
||||
|
||||
set_cursor(wd, wd->predef_cursor, thrd);
|
||||
@ -585,29 +606,5 @@ namespace nana
|
||||
throw std::runtime_error("Invalid event code");
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::_m_except_handler()
|
||||
{
|
||||
std::vector<core_window_t*> v;
|
||||
wd_manager().all_handles(v);
|
||||
if (v.size())
|
||||
{
|
||||
std::vector<native_window_type> roots;
|
||||
native_window_type root = nullptr;
|
||||
unsigned tid = nana::system::this_thread_id();
|
||||
for (auto wd : v)
|
||||
{
|
||||
if ((wd->thread_id == tid) && (wd->root != root))
|
||||
{
|
||||
root = wd->root;
|
||||
if (roots.cend() == std::find(roots.cbegin(), roots.cend(), root))
|
||||
roots.emplace_back(root);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i : roots)
|
||||
native_interface::close_window(i);
|
||||
}
|
||||
}
|
||||
}//end namespace detail
|
||||
}//end namespace nana
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Bedrock Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -10,7 +10,7 @@
|
||||
* @file: nana/gui/detail/linux_X11/bedrock.cpp
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#if defined(NANA_POSIX) && defined(NANA_X11)
|
||||
#include <nana/gui/detail/bedrock_pi_data.hpp>
|
||||
#include <nana/gui/detail/event_code.hpp>
|
||||
@ -237,7 +237,7 @@ namespace detail
|
||||
if(wd_manager().available(wd) == false)
|
||||
return false;
|
||||
|
||||
core_window_t * prev_wd;
|
||||
core_window_t * prev_wd = nullptr;
|
||||
if(thrd)
|
||||
{
|
||||
prev_wd = thrd->event_window;
|
||||
@ -376,7 +376,7 @@ namespace detail
|
||||
switch(msg.kind)
|
||||
{
|
||||
case nana::detail::msg_packet_tag::kind_mouse_drop:
|
||||
msgwd = brock.wd_manager().find_window(native_window, msg.u.mouse_drop.x, msg.u.mouse_drop.y);
|
||||
msgwd = brock.wd_manager().find_window(native_window, {msg.u.mouse_drop.x, msg.u.mouse_drop.y});
|
||||
if(msgwd)
|
||||
{
|
||||
arg_dropfiles arg;
|
||||
@ -511,7 +511,7 @@ namespace detail
|
||||
if(pressed_wd_space)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, xevent.xcrossing.x, xevent.xcrossing.y);
|
||||
msgwnd = wd_manager.find_window(native_window, {xevent.xcrossing.x, xevent.xcrossing.y});
|
||||
if(msgwnd)
|
||||
{
|
||||
if (mouse_action::pressed != msgwnd->flags.action)
|
||||
@ -568,8 +568,11 @@ namespace detail
|
||||
if(xevent.xbutton.button == Button4 || xevent.xbutton.button == Button5)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y);
|
||||
if(nullptr == msgwnd) break;
|
||||
msgwnd = wd_manager.find_window(native_window, {xevent.xbutton.x, xevent.xbutton.y});
|
||||
|
||||
pressed_wd = nullptr;
|
||||
if(nullptr == msgwnd)
|
||||
break;
|
||||
|
||||
if ((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.erase_menu(true);
|
||||
@ -578,7 +581,9 @@ namespace detail
|
||||
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
bool dbl_click = (last_mouse_down_window == msgwnd) && (xevent.xbutton.time - last_mouse_down_time <= 400);
|
||||
pressed_wd = msgwnd;
|
||||
|
||||
const bool dbl_click = (last_mouse_down_window == msgwnd) && (xevent.xbutton.time - last_mouse_down_time <= 400);
|
||||
last_mouse_down_time = xevent.xbutton.time;
|
||||
last_mouse_down_window = msgwnd;
|
||||
|
||||
@ -597,28 +602,31 @@ namespace detail
|
||||
auto retain = msgwnd->annex.events_ptr;
|
||||
context.event_window = msgwnd;
|
||||
|
||||
pressed_wd = nullptr;
|
||||
|
||||
msgwnd->set_action(mouse_action::pressed);
|
||||
arg_mouse arg;
|
||||
assign_arg(arg, msgwnd, ButtonPress, xevent);
|
||||
arg.evt_code = dbl_click ? event_code::dbl_click : event_code::mouse_down;
|
||||
if(brock.emit(arg.evt_code, msgwnd, arg, true, &context))
|
||||
if (brock.emit(arg.evt_code, msgwnd, arg, true, &context))
|
||||
{
|
||||
if (wd_manager.available(msgwnd))
|
||||
//If a root window is created during the mouse_down event, Nana.GUI will ignore the mouse_up event.
|
||||
if (msgwnd->root != native_interface::get_focus_window())
|
||||
{
|
||||
pressed_wd = msgwnd;
|
||||
//If a root window is created during the mouse_down event, Nana.GUI will ignore the mouse_up event.
|
||||
if (msgwnd->root != native_interface::get_focus_window())
|
||||
auto pos = native_interface::cursor_position();
|
||||
auto rootwd = native_interface::find_window(pos.x, pos.y);
|
||||
native_interface::calc_window_point(rootwd, pos);
|
||||
if(msgwnd != wd_manager.find_window(rootwd, pos))
|
||||
{
|
||||
//call the drawer mouse up event for restoring the surface graphics
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
|
||||
arg.evt_code = event_code::mouse_up;
|
||||
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
|
||||
wd_manager.do_lazy_refresh(msgwnd, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
pressed_wd = nullptr;
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
@ -626,7 +634,7 @@ namespace detail
|
||||
if(pressed_wd_space)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y);
|
||||
msgwnd = wd_manager.find_window(native_window, {xevent.xbutton.x, xevent.xbutton.y});
|
||||
if(nullptr == msgwnd)
|
||||
break;
|
||||
|
||||
@ -746,7 +754,7 @@ namespace detail
|
||||
if(pressed_wd_space)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, xevent.xmotion.x, xevent.xmotion.y);
|
||||
msgwnd = wd_manager.find_window(native_window, {xevent.xmotion.x, xevent.xmotion.y});
|
||||
if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd))
|
||||
{
|
||||
brock.event_msleave(hovered_wd);
|
||||
@ -768,7 +776,7 @@ namespace detail
|
||||
if(prev_captured_inside)
|
||||
{
|
||||
evt_code = event_code::mouse_leave;
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
msgwnd->set_action(mouse_action::normal_captured);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1146,7 +1154,7 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::pump_event(window modal_window, bool /*is_modal*/)
|
||||
void bedrock::pump_event(window condition_wd, bool is_modal)
|
||||
{
|
||||
thread_context * context = open_thread_context();
|
||||
if(0 == context->window_count)
|
||||
@ -1157,13 +1165,15 @@ namespace detail
|
||||
}
|
||||
|
||||
++(context->event_pump_ref_count);
|
||||
wd_manager().internal_lock().revert();
|
||||
|
||||
native_window_type owner_native = 0;
|
||||
auto & lock = wd_manager().internal_lock();
|
||||
lock.revert();
|
||||
|
||||
native_window_type owner_native{};
|
||||
core_window_t * owner = 0;
|
||||
if(modal_window)
|
||||
if(condition_wd && is_modal)
|
||||
{
|
||||
native_window_type modal = reinterpret_cast<core_window_t*>(modal_window)->root;
|
||||
native_window_type modal = reinterpret_cast<core_window_t*>(condition_wd)->root;
|
||||
owner_native = native_interface::get_owner_window(modal);
|
||||
if(owner_native)
|
||||
{
|
||||
@ -1174,7 +1184,7 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
nana::detail::platform_spec::instance().msg_dispatch(modal_window ? reinterpret_cast<core_window_t*>(modal_window)->root : 0);
|
||||
nana::detail::platform_spec::instance().msg_dispatch(condition_wd ? reinterpret_cast<core_window_t*>(condition_wd)->root : 0);
|
||||
|
||||
if(owner_native)
|
||||
{
|
||||
@ -1183,10 +1193,19 @@ namespace detail
|
||||
native_interface::enable_window(owner_native, true);
|
||||
}
|
||||
|
||||
wd_manager().internal_lock().forward();
|
||||
//Before exit of pump_event, it should call the remove_trash_handle.
|
||||
//Under Linux, if the windows are closed in other threads, all the widgets handles
|
||||
//will be marked as deleted after exit of the event loop and in other threads. So the
|
||||
//handle should be deleted from trash before exit the pump_event.
|
||||
auto thread_id = ::nana::system::this_thread_id();
|
||||
wd_manager().call_safe_place(thread_id);
|
||||
wd_manager().remove_trash_handle(thread_id);
|
||||
|
||||
lock.forward();
|
||||
|
||||
if(0 == --(context->event_pump_ref_count))
|
||||
{
|
||||
if(0 == modal_window || 0 == context->window_count)
|
||||
if(0 == condition_wd || 0 == context->window_count)
|
||||
remove_thread_context();
|
||||
}
|
||||
|
||||
@ -1203,17 +1222,7 @@ namespace detail
|
||||
{
|
||||
thread_context* thrd = get_thread_context(0);
|
||||
if(thrd && thrd->event_window)
|
||||
{
|
||||
//the state none should be tested, becuase in an event, there would be draw after an update,
|
||||
//if the none is not tested, the draw after update will not be refreshed.
|
||||
switch(thrd->event_window->other.upd_state)
|
||||
{
|
||||
case core_window_t::update_state::none:
|
||||
case core_window_t::update_state::lazy:
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refresh;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
|
||||
//Dynamically set a cursor for a window
|
||||
@ -1281,7 +1290,7 @@ namespace detail
|
||||
return;
|
||||
|
||||
native_interface::calc_window_point(native_handle, pos);
|
||||
auto rev_wd = wd_manager().find_window(native_handle, pos.x, pos.y);
|
||||
auto rev_wd = wd_manager().find_window(native_handle, pos);
|
||||
if (rev_wd)
|
||||
set_cursor(rev_wd, rev_wd->predef_cursor, thrd);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Bedrock Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -12,7 +12,7 @@
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include <nana/gui/detail/bedrock_pi_data.hpp>
|
||||
@ -345,7 +345,7 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::pump_event(window modal_window, bool is_modal)
|
||||
void bedrock::pump_event(window condition_wd, bool is_modal)
|
||||
{
|
||||
const unsigned tid = ::GetCurrentThreadId();
|
||||
auto context = this->open_thread_context(tid);
|
||||
@ -365,9 +365,9 @@ namespace detail
|
||||
try
|
||||
{
|
||||
MSG msg;
|
||||
if(modal_window)
|
||||
if (condition_wd)
|
||||
{
|
||||
HWND native_handle = reinterpret_cast<HWND>(reinterpret_cast<core_window_t*>(modal_window)->root);
|
||||
HWND native_handle = reinterpret_cast<HWND>(reinterpret_cast<core_window_t*>(condition_wd)->root);
|
||||
if (is_modal)
|
||||
{
|
||||
HWND owner = ::GetWindow(native_handle, GW_OWNER);
|
||||
@ -437,35 +437,35 @@ namespace detail
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
(msgbox(modal_window, "An uncaptured std::exception during message pumping: ").icon(msgbox::icon_information)
|
||||
<<"\n in form: "<< API::window_caption(modal_window)
|
||||
<<"\n exception : "<< e.what()
|
||||
).show();
|
||||
(msgbox(condition_wd, "An uncaptured std::exception during message pumping: ").icon(msgbox::icon_information)
|
||||
<< "\n in form: " << API::window_caption(condition_wd)
|
||||
<<"\n exception : "<< e.what()
|
||||
).show();
|
||||
|
||||
internal_scope_guard lock;
|
||||
_m_except_handler();
|
||||
internal_scope_guard lock;
|
||||
this->close_thread_window(nana::system::this_thread_id());
|
||||
|
||||
intr_locker.forward();
|
||||
if (0 == --(context->event_pump_ref_count))
|
||||
{
|
||||
if ((nullptr == modal_window) || (0 == context->window_count))
|
||||
remove_thread_context();
|
||||
}
|
||||
throw;
|
||||
intr_locker.forward();
|
||||
if (0 == --(context->event_pump_ref_count))
|
||||
{
|
||||
if ((nullptr == condition_wd) || (0 == context->window_count))
|
||||
remove_thread_context();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
(msgbox(modal_window, "An exception during message pumping!").icon(msgbox::icon_information)
|
||||
(msgbox(condition_wd, "An exception during message pumping!").icon(msgbox::icon_information)
|
||||
<<"An uncaptured non-std exception during message pumping!"
|
||||
<< "\n in form: " << API::window_caption(modal_window)
|
||||
<< "\n in form: " << API::window_caption(condition_wd)
|
||||
).show();
|
||||
internal_scope_guard lock;
|
||||
_m_except_handler();
|
||||
this->close_thread_window(nana::system::this_thread_id());
|
||||
|
||||
intr_locker.forward();
|
||||
if(0 == --(context->event_pump_ref_count))
|
||||
{
|
||||
if((nullptr == modal_window) || (0 == context->window_count))
|
||||
if ((nullptr == condition_wd) || (0 == context->window_count))
|
||||
remove_thread_context();
|
||||
}
|
||||
throw;
|
||||
@ -474,7 +474,7 @@ namespace detail
|
||||
intr_locker.forward();
|
||||
if(0 == --(context->event_pump_ref_count))
|
||||
{
|
||||
if((nullptr == modal_window) || (0 == context->window_count))
|
||||
if ((nullptr == condition_wd) || (0 == context->window_count))
|
||||
remove_thread_context();
|
||||
}
|
||||
}//end pump_event
|
||||
@ -760,7 +760,7 @@ namespace detail
|
||||
if (bedrock::instance().wd_manager().available(wd) == false)
|
||||
return;
|
||||
|
||||
basic_window* prev_event_wd;
|
||||
basic_window* prev_event_wd = nullptr;
|
||||
if (thrd)
|
||||
{
|
||||
prev_event_wd = thrd->event_window;
|
||||
@ -784,7 +784,7 @@ namespace detail
|
||||
static auto& brock = bedrock::instance();
|
||||
static restrict::TRACKMOUSEEVENT track = {sizeof track, 0x00000002};
|
||||
|
||||
auto native_window = reinterpret_cast<native_window_type>(root_window);
|
||||
auto const native_window = reinterpret_cast<native_window_type>(root_window);
|
||||
|
||||
auto & wd_manager = brock.wd_manager();
|
||||
auto* root_runtime = wd_manager.root_runtime(native_window);
|
||||
@ -805,10 +805,10 @@ namespace detail
|
||||
internal_scope_guard lock;
|
||||
auto msgwnd = root_runtime->window;
|
||||
|
||||
switch(message)
|
||||
switch (message)
|
||||
{
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
if(msgwnd->other.attribute.root->ime_enabled)
|
||||
if (msgwnd->other.attribute.root->ime_enabled)
|
||||
{
|
||||
auto native_font = msgwnd->drawer.graphics.typeface().handle();
|
||||
LOGFONTW logfont;
|
||||
@ -820,7 +820,7 @@ namespace detail
|
||||
POINT pos;
|
||||
::GetCaretPos(&pos);
|
||||
|
||||
COMPOSITIONFORM cf = {CFS_POINT};
|
||||
COMPOSITIONFORM cf = { CFS_POINT };
|
||||
cf.ptCurrentPos = pos;
|
||||
restrict::imm_set_composition_window(imc, &cf);
|
||||
restrict::imm_release_context(root_window, imc);
|
||||
@ -828,36 +828,36 @@ namespace detail
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
bool take_over = false;
|
||||
auto mmi = reinterpret_cast<MINMAXINFO*>(lParam);
|
||||
{
|
||||
bool take_over = false;
|
||||
auto mmi = reinterpret_cast<MINMAXINFO*>(lParam);
|
||||
|
||||
if(!msgwnd->min_track_size.empty())
|
||||
if (!msgwnd->min_track_size.empty())
|
||||
{
|
||||
mmi->ptMinTrackSize.x = static_cast<LONG>(msgwnd->min_track_size.width + msgwnd->extra_width);
|
||||
mmi->ptMinTrackSize.y = static_cast<LONG>(msgwnd->min_track_size.height + msgwnd->extra_height);
|
||||
take_over = true;
|
||||
}
|
||||
|
||||
if (false == msgwnd->flags.fullscreen)
|
||||
{
|
||||
if (msgwnd->max_track_size.width && msgwnd->max_track_size.height)
|
||||
{
|
||||
mmi->ptMinTrackSize.x = static_cast<LONG>(msgwnd->min_track_size.width + msgwnd->extra_width);
|
||||
mmi->ptMinTrackSize.y = static_cast<LONG>(msgwnd->min_track_size.height + msgwnd->extra_height);
|
||||
mmi->ptMaxTrackSize.x = static_cast<LONG>(msgwnd->max_track_size.width + msgwnd->extra_width);
|
||||
mmi->ptMaxTrackSize.y = static_cast<LONG>(msgwnd->max_track_size.height + msgwnd->extra_height);
|
||||
if (mmi->ptMaxSize.x > mmi->ptMaxTrackSize.x)
|
||||
mmi->ptMaxSize.x = mmi->ptMaxTrackSize.x;
|
||||
if (mmi->ptMaxSize.y > mmi->ptMaxTrackSize.y)
|
||||
mmi->ptMaxSize.y = mmi->ptMaxTrackSize.y;
|
||||
|
||||
take_over = true;
|
||||
}
|
||||
|
||||
if(false == msgwnd->flags.fullscreen)
|
||||
{
|
||||
if(msgwnd->max_track_size.width && msgwnd->max_track_size.height)
|
||||
{
|
||||
mmi->ptMaxTrackSize.x = static_cast<LONG>(msgwnd->max_track_size.width + msgwnd->extra_width);
|
||||
mmi->ptMaxTrackSize.y = static_cast<LONG>(msgwnd->max_track_size.height + msgwnd->extra_height);
|
||||
if(mmi->ptMaxSize.x > mmi->ptMaxTrackSize.x)
|
||||
mmi->ptMaxSize.x = mmi->ptMaxTrackSize.x;
|
||||
if(mmi->ptMaxSize.y > mmi->ptMaxTrackSize.y)
|
||||
mmi->ptMaxSize.y = mmi->ptMaxTrackSize.y;
|
||||
|
||||
take_over = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (take_over)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
if (take_over)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case WM_SHOWWINDOW:
|
||||
if (msgwnd->visible == (FALSE == wParam))
|
||||
brock.event_expose(msgwnd, !msgwnd->visible);
|
||||
@ -882,7 +882,7 @@ namespace detail
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_MOUSEACTIVATE:
|
||||
if(msgwnd->flags.take_active == false)
|
||||
if (msgwnd->flags.take_active == false)
|
||||
return MA_NOACTIVATE;
|
||||
|
||||
def_window_proc = true;
|
||||
@ -893,8 +893,8 @@ namespace detail
|
||||
break;
|
||||
|
||||
pressed_wd = nullptr;
|
||||
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
|
||||
if(msgwnd && msgwnd->flags.enabled)
|
||||
msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y });
|
||||
if (msgwnd && msgwnd->flags.enabled)
|
||||
{
|
||||
if (msgwnd->flags.take_active && !msgwnd->flags.ignore_mouse_focus)
|
||||
{
|
||||
@ -918,8 +918,14 @@ namespace detail
|
||||
if (pressed_wd_space)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
|
||||
if ((nullptr == msgwnd) || (pressed_wd && (msgwnd != pressed_wd)))
|
||||
msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y });
|
||||
|
||||
//Don't take care about whether msgwnd is equal to the pressed_wd.
|
||||
//
|
||||
//pressed_wd will remains when opens a no-actived window in an mouse_down event(like combox popups the drop-list).
|
||||
//After the no-actived window is closed, the window doesn't respond to the mouse click other than pressed_wd.
|
||||
pressed_wd = nullptr;
|
||||
if (nullptr == msgwnd)
|
||||
break;
|
||||
|
||||
//if event on the menubar, just remove the menu if it is not associating with the menubar
|
||||
@ -928,7 +934,7 @@ namespace detail
|
||||
else
|
||||
brock.close_menu_if_focus_other_window(msgwnd->root);
|
||||
|
||||
if(msgwnd->flags.enabled)
|
||||
if (msgwnd->flags.enabled)
|
||||
{
|
||||
pressed_wd = msgwnd;
|
||||
|
||||
@ -956,7 +962,7 @@ namespace detail
|
||||
auto pos = native_interface::cursor_position();
|
||||
auto rootwd = native_interface::find_window(pos.x, pos.y);
|
||||
native_interface::calc_window_point(rootwd, pos);
|
||||
if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y))
|
||||
if (msgwnd != wd_manager.find_window(rootwd, pos))
|
||||
{
|
||||
//call the drawer mouse up event for restoring the surface graphics
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
@ -971,7 +977,7 @@ namespace detail
|
||||
pressed_wd = nullptr;
|
||||
}
|
||||
break;
|
||||
//mouse_click, mouse_up
|
||||
//mouse_click, mouse_up
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
@ -979,12 +985,12 @@ namespace detail
|
||||
if (pressed_wd_space)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
|
||||
if(nullptr == msgwnd)
|
||||
msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y });
|
||||
if (nullptr == msgwnd)
|
||||
break;
|
||||
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
if(msgwnd->flags.enabled)
|
||||
if (msgwnd->flags.enabled)
|
||||
{
|
||||
auto retain = msgwnd->annex.events_ptr;
|
||||
|
||||
@ -1008,7 +1014,7 @@ namespace detail
|
||||
}
|
||||
|
||||
//Do mouse_up, this handle may be closed by click handler.
|
||||
if(wd_manager.available(msgwnd) && msgwnd->flags.enabled)
|
||||
if (wd_manager.available(msgwnd) && msgwnd->flags.enabled)
|
||||
{
|
||||
arg.evt_code = event_code::mouse_up;
|
||||
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
|
||||
@ -1034,7 +1040,7 @@ namespace detail
|
||||
if (pressed_wd_space)
|
||||
break;
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
|
||||
msgwnd = wd_manager.find_window(native_window, {pmdec.mouse.x, pmdec.mouse.y});
|
||||
if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd))
|
||||
{
|
||||
brock.event_msleave(hovered_wd);
|
||||
@ -1057,7 +1063,7 @@ namespace detail
|
||||
if(prev_captured_inside)
|
||||
{
|
||||
evt_code = event_code::mouse_leave;
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
msgwnd->set_action(mouse_action::normal_captured);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1115,7 +1121,7 @@ namespace detail
|
||||
if (pointer_wd == root_window)
|
||||
{
|
||||
::ScreenToClient(pointer_wd, &scr_pos);
|
||||
auto scrolled_wd = wd_manager.find_window(reinterpret_cast<native_window_type>(pointer_wd), scr_pos.x, scr_pos.y);
|
||||
auto scrolled_wd = wd_manager.find_window(reinterpret_cast<native_window_type>(pointer_wd), { scr_pos.x, scr_pos.y });
|
||||
|
||||
def_window_proc = true;
|
||||
auto evt_wd = scrolled_wd;
|
||||
@ -1156,10 +1162,12 @@ namespace detail
|
||||
case WM_DROPFILES:
|
||||
{
|
||||
HDROP drop = reinterpret_cast<HDROP>(wParam);
|
||||
POINT pos;
|
||||
::DragQueryPoint(drop, &pos);
|
||||
POINT mswin_pos;
|
||||
::DragQueryPoint(drop, &mswin_pos);
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, pos.x, pos.y);
|
||||
const point pos{ mswin_pos.x, mswin_pos.y };
|
||||
|
||||
msgwnd = wd_manager.find_window(native_window, pos);
|
||||
if(msgwnd)
|
||||
{
|
||||
arg_dropfiles dropfiles;
|
||||
@ -1187,8 +1195,7 @@ namespace detail
|
||||
|
||||
if(msgwnd)
|
||||
{
|
||||
dropfiles.pos.x = pos.x;
|
||||
dropfiles.pos.y = pos.y;
|
||||
dropfiles.pos = pos;
|
||||
|
||||
wd_manager.calc_window_point(msgwnd, dropfiles.pos);
|
||||
dropfiles.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@ -1624,7 +1631,7 @@ namespace detail
|
||||
if (wd_manager().available(wd) == false)
|
||||
return false;
|
||||
|
||||
basic_window* prev_event_wd;
|
||||
basic_window* prev_event_wd = nullptr;
|
||||
if (thrd)
|
||||
{
|
||||
prev_event_wd = thrd->event_window;
|
||||
@ -1691,17 +1698,7 @@ namespace detail
|
||||
{
|
||||
auto* thrd = get_thread_context(0);
|
||||
if (thrd && thrd->event_window)
|
||||
{
|
||||
//the state none should be tested, becuase in an event, there would be draw after an update,
|
||||
//if the none is not tested, the draw after update will not be refreshed.
|
||||
switch (thrd->event_window->other.upd_state)
|
||||
{
|
||||
case core_window_t::update_state::none:
|
||||
case core_window_t::update_state::lazy:
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refresh;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
|
||||
//Dynamically set a cursor for a window
|
||||
@ -1724,9 +1721,16 @@ namespace detail
|
||||
thrd->cursor.handle = ::LoadCursor(nullptr, translate(cur));
|
||||
}
|
||||
|
||||
if (wd->root_widget->other.attribute.root->running_cursor != cur)
|
||||
auto this_cur = reinterpret_cast<HCURSOR>(
|
||||
#ifdef _WIN64
|
||||
::GetClassLongPtr(reinterpret_cast<HWND>(wd->root), GCLP_HCURSOR)
|
||||
#else
|
||||
::GetClassLong(reinterpret_cast<HWND>(wd->root), GCL_HCURSOR)
|
||||
#endif
|
||||
);
|
||||
|
||||
if(this_cur != thrd->cursor.handle)
|
||||
{
|
||||
wd->root_widget->other.attribute.root->running_cursor = cur;
|
||||
#ifdef _WIN64
|
||||
::SetClassLongPtr(reinterpret_cast<HWND>(wd->root), GCLP_HCURSOR,
|
||||
reinterpret_cast<LONG_PTR>(thrd->cursor.handle));
|
||||
@ -1735,6 +1739,7 @@ namespace detail
|
||||
static_cast<unsigned long>(reinterpret_cast<size_t>(thrd->cursor.handle)));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cursor::arrow == thrd->cursor.predef_cursor)
|
||||
{
|
||||
thrd->cursor.window = nullptr;
|
||||
@ -1779,7 +1784,7 @@ namespace detail
|
||||
}
|
||||
|
||||
native_interface::calc_window_point(native_handle, pos);
|
||||
auto rev_wd = wd_manager().find_window(native_handle, pos.x, pos.y);
|
||||
auto rev_wd = wd_manager().find_window(native_handle, pos);
|
||||
if (rev_wd)
|
||||
{
|
||||
set_cursor(rev_wd, rev_wd->predef_cursor, thrd);
|
||||
@ -1808,10 +1813,7 @@ namespace detail
|
||||
undefine_state_cursor(wd, thrd);
|
||||
|
||||
if(wd == thrd->cursor.window)
|
||||
{
|
||||
set_cursor(wd, cursor::arrow, thrd);
|
||||
wd->root_widget->other.attribute.root->running_cursor = cursor::arrow;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Drawer Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -18,7 +18,7 @@
|
||||
#include "dynamic_drawing_object.hpp"
|
||||
|
||||
#if defined(NANA_X11)
|
||||
#include <nana/detail/linux_X11/platform_spec.hpp>
|
||||
#include "../../detail/posix/platform_spec.hpp"
|
||||
#endif
|
||||
|
||||
namespace nana
|
||||
@ -297,9 +297,8 @@ namespace nana
|
||||
if (data_impl_->realizer && !data_impl_->refreshing)
|
||||
{
|
||||
data_impl_->refreshing = true;
|
||||
_m_effect_bground(true);
|
||||
data_impl_->realizer->refresh(graphics);
|
||||
_m_effect_bground(false);
|
||||
_m_effect_bground_subsequent();
|
||||
graphics.flush();
|
||||
data_impl_->refreshing = false;
|
||||
}
|
||||
@ -318,6 +317,7 @@ namespace nana
|
||||
data_impl_->realizer = &realizer;
|
||||
realizer._m_reset_overrided();
|
||||
realizer.attached(wd, graphics);
|
||||
realizer.typeface_changed(graphics);
|
||||
}
|
||||
|
||||
drawer_trigger* drawer::detached()
|
||||
@ -371,27 +371,22 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
void drawer::_m_effect_bground(bool before)
|
||||
void drawer::_m_effect_bground_subsequent()
|
||||
{
|
||||
auto & effect = data_impl_->window_handle->effect;
|
||||
|
||||
for (auto * dw : data_impl_->draws)
|
||||
dw->draw(graphics);
|
||||
|
||||
auto & effect = data_impl_->window_handle->effect;
|
||||
|
||||
if (effect.bground)
|
||||
{
|
||||
if (before)
|
||||
if (effect.bground_fade_rate >= 0.01)
|
||||
{
|
||||
if (effect.bground_fade_rate < 0.01)
|
||||
data_impl_->window_handle->other.glass_buffer.paste(graphics, 0, 0);
|
||||
graphics.blend(::nana::rectangle{ data_impl_->window_handle->other.glass_buffer.size() }, data_impl_->window_handle->other.glass_buffer, {}, 1 - effect.bground_fade_rate);
|
||||
}
|
||||
else if (effect.bground_fade_rate >= 0.01)
|
||||
data_impl_->window_handle->other.glass_buffer.blend(::nana::rectangle{ data_impl_->window_handle->other.glass_buffer.size() }, graphics, nana::point(), effect.bground_fade_rate);
|
||||
}
|
||||
}
|
||||
|
||||
bool drawer::_m_lazy_decleared() const
|
||||
{
|
||||
return (basic_window::update_state::refresh == data_impl_->window_handle->other.upd_state);
|
||||
}
|
||||
|
||||
drawer::method_state& drawer::_m_mth_state(int pos)
|
||||
|
||||
@ -80,19 +80,22 @@ namespace nana
|
||||
internal_scope_guard lock;
|
||||
if (dockers_)
|
||||
{
|
||||
|
||||
for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
|
||||
{
|
||||
if (reinterpret_cast<detail::docker_interface*>(evt) == *i)
|
||||
{
|
||||
//Checks whether this event is working now.
|
||||
if (emitting_count_ > 1)
|
||||
if (emitting_count_)
|
||||
{
|
||||
static_cast<docker_base*>(*i)->flag_deleted = true;
|
||||
deleted_flags_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bedrock::instance().evt_operation().cancel(evt);
|
||||
dockers_->erase(i);
|
||||
delete reinterpret_cast<detail::docker_interface*>(evt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -131,7 +134,11 @@ namespace nana
|
||||
for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();)
|
||||
{
|
||||
if (static_cast<docker_base*>(*i)->flag_deleted)
|
||||
{
|
||||
bedrock::instance().evt_operation().cancel(reinterpret_cast<event_handle>(*i));
|
||||
delete (*i);
|
||||
i = evt_->dockers_->erase(i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Platform Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -10,7 +10,7 @@
|
||||
* @file: nana/gui/detail/native_window_interface.cpp
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/screen.hpp>
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
@ -23,7 +23,6 @@
|
||||
#include <mutex>
|
||||
#endif
|
||||
#include <map>
|
||||
#include "../../paint/detail/image_ico.hpp"
|
||||
#elif defined(NANA_X11)
|
||||
#include <nana/system/platform.hpp>
|
||||
#endif
|
||||
@ -197,6 +196,13 @@ namespace nana{
|
||||
return rectangle{ primary_monitor_size() };
|
||||
}
|
||||
|
||||
#ifdef NANA_X11
|
||||
//The XMoveWindow and XMoveResizeWindow don't take effect if the specified window is
|
||||
//unmapped, and the members x and y of XSetSizeHints is obsoluted. So the position that
|
||||
//set to a unmapped windows should be kept and use the position when the window is mapped.
|
||||
std::map<Window, ::nana::point> exposed_positions; //locked by platform_scope_guard
|
||||
#endif
|
||||
|
||||
//platform-dependent
|
||||
native_interface::window_result native_interface::create_window(native_window_type owner, bool nested, const rectangle& r, const appearance& app)
|
||||
{
|
||||
@ -289,6 +295,7 @@ namespace nana{
|
||||
{
|
||||
win_attr.save_under = True;
|
||||
attr_mask |= CWSaveUnder;
|
||||
|
||||
parent = restrict::spec.root_window();
|
||||
calc_screen_point(owner, pos);
|
||||
}
|
||||
@ -303,7 +310,12 @@ namespace nana{
|
||||
{
|
||||
//make owner if it is a popup window
|
||||
if((!nested) && owner)
|
||||
{
|
||||
restrict::spec.make_owner(owner, reinterpret_cast<native_window_type>(handle));
|
||||
exposed_positions[handle] = pos;
|
||||
}
|
||||
|
||||
XChangeWindowAttributes(disp, handle, attr_mask, &win_attr);
|
||||
|
||||
XTextProperty name;
|
||||
char text[] = "Nana Window";
|
||||
@ -655,6 +667,14 @@ namespace nana{
|
||||
if(show)
|
||||
{
|
||||
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
|
||||
auto i = exposed_positions.find(reinterpret_cast<Window>(wd));
|
||||
if(i != exposed_positions.end())
|
||||
{
|
||||
::XMoveWindow(disp, reinterpret_cast<Window>(wd), i->second.x, i->second.y);
|
||||
exposed_positions.erase(i);
|
||||
}
|
||||
|
||||
Window grab = restrict::spec.grab(0);
|
||||
if(grab == reinterpret_cast<Window>(wd))
|
||||
capture_window(wd, true);
|
||||
@ -882,13 +902,7 @@ namespace nana{
|
||||
XWindowAttributes attr;
|
||||
::XGetWindowAttributes(disp, reinterpret_cast<Window>(wd), &attr);
|
||||
if(attr.map_state == IsUnmapped)
|
||||
{
|
||||
XSizeHints hints;
|
||||
hints.flags = USPosition;
|
||||
hints.x = x;
|
||||
hints.y = y;
|
||||
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
|
||||
}
|
||||
exposed_positions[reinterpret_cast<Window>(wd)] = ::nana::point{x, y};
|
||||
|
||||
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
||||
#endif
|
||||
@ -959,11 +973,11 @@ namespace nana{
|
||||
::XGetWindowAttributes(disp, reinterpret_cast<Window>(wd), &attr);
|
||||
if(attr.map_state == IsUnmapped)
|
||||
{
|
||||
hints.flags |= (USPosition | USSize);
|
||||
hints.x = x;
|
||||
hints.y = y;
|
||||
hints.flags |= USSize;
|
||||
hints.width = r.width;
|
||||
hints.height = r.height;
|
||||
|
||||
exposed_positions[reinterpret_cast<Window>(wd)] = point{x, y};
|
||||
}
|
||||
|
||||
if(hints.flags)
|
||||
|
||||
@ -22,26 +22,26 @@ namespace nana
|
||||
namespace detail
|
||||
{
|
||||
//class window_layout
|
||||
void window_layout::paint(core_window_t* wd, bool is_redraw, bool is_child_refreshed)
|
||||
void window_layout::paint(core_window_t* wd, paint_operation operation, bool req_refresh_children)
|
||||
{
|
||||
if (is_redraw && wd->flags.refreshing)
|
||||
if (wd->flags.refreshing && (paint_operation::try_refresh == operation))
|
||||
return;
|
||||
|
||||
if (nullptr == wd->effect.bground)
|
||||
{
|
||||
if (is_redraw && (!wd->drawer.graphics.empty()))
|
||||
if ((paint_operation::try_refresh == operation) && (!wd->drawer.graphics.empty()))
|
||||
{
|
||||
wd->flags.refreshing = true;
|
||||
wd->drawer.refresh();
|
||||
wd->flags.refreshing = false;
|
||||
}
|
||||
maproot(wd, is_redraw, is_child_refreshed);
|
||||
maproot(wd, (paint_operation::none != operation), req_refresh_children);
|
||||
}
|
||||
else
|
||||
_m_paint_glass_window(wd, is_redraw, is_child_refreshed, false, true);
|
||||
_m_paint_glass_window(wd, (paint_operation::try_refresh == operation), req_refresh_children, false, true);
|
||||
}
|
||||
|
||||
bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool is_child_refreshed)
|
||||
bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool req_refresh_children)
|
||||
{
|
||||
auto check_opaque = wd->seek_non_lite_widget_ancestor();
|
||||
if (check_opaque && check_opaque->flags.refreshing)
|
||||
@ -56,7 +56,7 @@ namespace nana
|
||||
if (category::flags::lite_widget != wd->other.category)
|
||||
graph.bitblt(vr, wd->drawer.graphics, nana::point(vr.x - wd->pos_root.x, vr.y - wd->pos_root.y));
|
||||
|
||||
_m_paste_children(wd, is_child_refreshed, have_refreshed, vr, graph, nana::point());
|
||||
_m_paste_children(wd, have_refreshed, req_refresh_children, vr, graph, nana::point());
|
||||
|
||||
if (wd->parent)
|
||||
{
|
||||
@ -81,11 +81,11 @@ namespace nana
|
||||
graph.bitblt(el.r, (el.window->drawer.graphics), p_src);
|
||||
}
|
||||
|
||||
_m_paste_children(el.window, is_child_refreshed, false, el.r, graph, nana::point{});
|
||||
_m_paste_children(el.window, false, req_refresh_children, el.r, graph, nana::point{});
|
||||
}
|
||||
}
|
||||
}
|
||||
_m_notify_glasses(wd, vr);
|
||||
_m_notify_glasses(wd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -116,7 +116,8 @@ namespace nana
|
||||
|
||||
for (auto* parent = wd->parent; parent; parent = parent->parent)
|
||||
{
|
||||
overlap(rectangle{ parent->pos_root, parent->dimension }, visual, visual);
|
||||
if (!overlap(rectangle{ parent->pos_root, parent->dimension }, visual, visual))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -255,8 +256,8 @@ namespace nana
|
||||
if (category::flags::lite_widget != child->other.category)
|
||||
glass_buffer.bitblt(nana::rectangle{ ovlp.x - wd->pos_owner.x, ovlp.y - wd->pos_owner.y, ovlp.width, ovlp.height }, child->drawer.graphics, {ovlp.position() - child->pos_owner});
|
||||
|
||||
ovlp.x += wd->pos_root.x;
|
||||
ovlp.y += wd->pos_root.y;
|
||||
ovlp.x += wd->parent->pos_root.x;
|
||||
ovlp.y += wd->parent->pos_root.y;
|
||||
_m_paste_children(child, false, false, ovlp, glass_buffer, rpos);
|
||||
}
|
||||
}
|
||||
@ -267,7 +268,7 @@ namespace nana
|
||||
|
||||
//_m_paste_children
|
||||
//@brief:paste children window to the root graphics directly. just paste the visual rectangle
|
||||
void window_layout::_m_paste_children(core_window_t* wd, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos)
|
||||
void window_layout::_m_paste_children(core_window_t* wd, bool have_refreshed, bool req_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos)
|
||||
{
|
||||
nana::rectangle rect;
|
||||
for (auto child : wd->children)
|
||||
@ -278,7 +279,7 @@ namespace nana
|
||||
|
||||
if (category::flags::root == child->other.category)
|
||||
{
|
||||
paint(child, is_child_refreshed, is_child_refreshed);
|
||||
paint(child, (req_refresh_children ? paint_operation::try_refresh : paint_operation::none), req_refresh_children);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -289,7 +290,7 @@ namespace nana
|
||||
bool have_child_refreshed = false;
|
||||
if (category::flags::lite_widget != child->other.category)
|
||||
{
|
||||
if (is_child_refreshed && (false == child->flags.refreshing))
|
||||
if (req_refresh_children && (false == child->flags.refreshing))
|
||||
{
|
||||
have_child_refreshed = true;
|
||||
child->flags.refreshing = true;
|
||||
@ -300,13 +301,13 @@ namespace nana
|
||||
graph.bitblt(nana::rectangle(rect.x - graph_rpos.x, rect.y - graph_rpos.y, rect.width, rect.height),
|
||||
child->drawer.graphics, nana::point(rect.x - child->pos_root.x, rect.y - child->pos_root.y));
|
||||
}
|
||||
_m_paste_children(child, is_child_refreshed, have_child_refreshed, rect, graph, graph_rpos);
|
||||
_m_paste_children(child, req_refresh_children, have_child_refreshed, rect, graph, graph_rpos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//If have_refreshed, the glass should be notified.
|
||||
_m_paint_glass_window(child, false, is_child_refreshed, have_refreshed, false);
|
||||
//Update the glass window's background if the parent have_refreshed.
|
||||
_m_paint_glass_window(child, have_refreshed, req_refresh_children, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -353,16 +354,14 @@ namespace nana
|
||||
}
|
||||
|
||||
if (notify_other)
|
||||
_m_notify_glasses(wd, vr);
|
||||
_m_notify_glasses(wd);
|
||||
}
|
||||
}
|
||||
|
||||
//_m_notify_glasses
|
||||
//@brief: Notify the glass windows that are overlapped with the specified vis_rect
|
||||
void window_layout::_m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& /*r_visual*/)
|
||||
/// Notify the glass windows that are overlapped with the specified visual rectangle.
|
||||
/// If a child window of sigwd is a glass window, it doesn't to be notified.
|
||||
void window_layout::_m_notify_glasses(core_window_t* const sigwd)
|
||||
{
|
||||
typedef category::flags cat_flags;
|
||||
|
||||
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
|
||||
for (auto wd : data_sect.effects_bground_windows)
|
||||
{
|
||||
@ -377,6 +376,8 @@ namespace nana
|
||||
}
|
||||
else if (sigwd != wd->parent)
|
||||
{
|
||||
using cat_flags = category::flags;
|
||||
|
||||
if (wd->parent && (cat_flags::lite_widget == wd->parent->other.category))
|
||||
{
|
||||
//Test if sigwd is an ancestor of the glass window, and there are lite widgets
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Window Manager Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -14,14 +14,17 @@
|
||||
#include <nana/config.hpp>
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include <nana/gui/detail/events_operation.hpp>
|
||||
#include <nana/gui/detail/handle_manager.hpp>
|
||||
#include <nana/gui/detail/window_manager.hpp>
|
||||
#include <nana/gui/detail/window_layout.hpp>
|
||||
#include "window_register.hpp"
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/detail/inner_fwd_implement.hpp>
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/gui/detail/effects_renderer.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#if defined(STD_THREAD_NOT_SUPPORTED)
|
||||
#include <nana/std_mutex.hpp>
|
||||
@ -34,6 +37,8 @@ namespace nana
|
||||
|
||||
namespace detail
|
||||
{
|
||||
using window_layer = window_layout;
|
||||
|
||||
//class shortkey_container
|
||||
struct shortkey_rep
|
||||
{
|
||||
@ -266,7 +271,8 @@ namespace detail
|
||||
struct window_manager::wdm_private_impl
|
||||
{
|
||||
root_register misc_register;
|
||||
handle_manager<core_window_t*, window_manager, window_handle_deleter> wd_register;
|
||||
window_register wd_register;
|
||||
|
||||
paint::image default_icon_big;
|
||||
paint::image default_icon_small;
|
||||
|
||||
@ -274,26 +280,34 @@ namespace detail
|
||||
};
|
||||
//end struct wdm_private_impl
|
||||
|
||||
//class revertible_mutex
|
||||
//class revertible_mutex
|
||||
struct thread_refcount
|
||||
{
|
||||
unsigned tid;
|
||||
std::size_t ref;
|
||||
unsigned tid; //Thread ID
|
||||
std::vector<unsigned> callstack_refs;
|
||||
|
||||
thread_refcount(unsigned thread_id, unsigned refs)
|
||||
: tid(thread_id)
|
||||
{
|
||||
callstack_refs.push_back(refs);
|
||||
}
|
||||
};
|
||||
|
||||
struct window_manager::revertible_mutex::implementation
|
||||
{
|
||||
std::recursive_mutex mutex;
|
||||
|
||||
thread_refcount thread;
|
||||
std::vector<thread_refcount> invoke_stack;
|
||||
unsigned thread_id; //Thread ID
|
||||
unsigned refs; //Ref count
|
||||
|
||||
std::vector<thread_refcount> records;
|
||||
};
|
||||
|
||||
window_manager::revertible_mutex::revertible_mutex()
|
||||
: impl_(new implementation)
|
||||
{
|
||||
impl_->thread.tid = 0;
|
||||
impl_->thread.ref = 0;
|
||||
impl_->thread_id = 0;
|
||||
impl_->refs = 0;
|
||||
}
|
||||
|
||||
window_manager::revertible_mutex::~revertible_mutex()
|
||||
@ -305,20 +319,20 @@ namespace detail
|
||||
{
|
||||
impl_->mutex.lock();
|
||||
|
||||
if(0 == impl_->thread.tid)
|
||||
impl_->thread.tid = nana::system::this_thread_id();
|
||||
if (0 == impl_->thread_id)
|
||||
impl_->thread_id = nana::system::this_thread_id();
|
||||
|
||||
++(impl_->thread.ref);
|
||||
++(impl_->refs);
|
||||
}
|
||||
|
||||
bool window_manager::revertible_mutex::try_lock()
|
||||
{
|
||||
if(impl_->mutex.try_lock())
|
||||
if (impl_->mutex.try_lock())
|
||||
{
|
||||
if (0 == impl_->thread.tid)
|
||||
impl_->thread.tid = nana::system::this_thread_id();
|
||||
if (0 == impl_->thread_id)
|
||||
impl_->thread_id = nana::system::this_thread_id();
|
||||
|
||||
++(impl_->thread.ref);
|
||||
++(impl_->refs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -326,47 +340,80 @@ namespace detail
|
||||
|
||||
void window_manager::revertible_mutex::unlock()
|
||||
{
|
||||
if(impl_->thread.tid == nana::system::this_thread_id())
|
||||
if(0 == --(impl_->thread.ref))
|
||||
impl_->thread.tid = 0;
|
||||
if (impl_->thread_id == nana::system::this_thread_id())
|
||||
if (0 == --(impl_->refs))
|
||||
impl_->thread_id = 0;
|
||||
|
||||
impl_->mutex.unlock();
|
||||
}
|
||||
|
||||
void window_manager::revertible_mutex::revert()
|
||||
{
|
||||
if(impl_->thread.ref && (impl_->thread.tid == nana::system::this_thread_id()))
|
||||
if (impl_->thread_id == nana::system::this_thread_id())
|
||||
{
|
||||
std::size_t cnt = impl_->thread.ref;
|
||||
auto const current_refs = impl_->refs;
|
||||
|
||||
impl_->invoke_stack.push_back(impl_->thread);
|
||||
impl_->thread.tid = 0;
|
||||
impl_->thread.ref = 0;
|
||||
//Check if there is a record
|
||||
for (auto & r : impl_->records)
|
||||
{
|
||||
if (r.tid == impl_->thread_id)
|
||||
{
|
||||
r.callstack_refs.push_back(current_refs);
|
||||
impl_->thread_id = 0; //Indicates a record is existing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < cnt; ++i)
|
||||
if (impl_->thread_id)
|
||||
{
|
||||
//Creates a new record
|
||||
impl_->records.emplace_back(impl_->thread_id, current_refs);
|
||||
impl_->thread_id = 0;
|
||||
}
|
||||
|
||||
impl_->refs = 0;
|
||||
|
||||
for (std::size_t i = 0; i < current_refs; ++i)
|
||||
impl_->mutex.unlock();
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("The revert is not allowed");
|
||||
}
|
||||
|
||||
void window_manager::revertible_mutex::forward()
|
||||
{
|
||||
impl_->mutex.lock();
|
||||
if(impl_->invoke_stack.size())
|
||||
|
||||
if (impl_->records.size())
|
||||
{
|
||||
auto thr = impl_->invoke_stack.back();
|
||||
if(thr.tid == nana::system::this_thread_id())
|
||||
auto const this_tid = nana::system::this_thread_id();
|
||||
|
||||
for (auto i = impl_->records.begin(); i != impl_->records.end(); ++i)
|
||||
{
|
||||
impl_->invoke_stack.pop_back();
|
||||
for (std::size_t i = 0; i < thr.ref; ++i)
|
||||
if (this_tid != i->tid)
|
||||
continue;
|
||||
|
||||
auto const refs = i->callstack_refs.back();
|
||||
|
||||
for (std::size_t u = 1; u < refs; ++u)
|
||||
impl_->mutex.lock();
|
||||
impl_->thread = thr;
|
||||
|
||||
impl_->thread_id = this_tid;
|
||||
impl_->refs = refs;
|
||||
|
||||
if (i->callstack_refs.size() > 1)
|
||||
i->callstack_refs.pop_back();
|
||||
else
|
||||
impl_->records.erase(i);
|
||||
return;
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Nana.GUI: The forward is not matched.");
|
||||
|
||||
throw std::runtime_error("The forward is not matched. Please report this issue");
|
||||
}
|
||||
|
||||
impl_->mutex.unlock();
|
||||
}
|
||||
//end class revertible_mutex
|
||||
//end class revertible_mutex
|
||||
|
||||
//Utilities in this unit.
|
||||
namespace utl
|
||||
@ -402,13 +449,11 @@ namespace detail
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
bool window_manager::is_queue(core_window_t* wd)
|
||||
{
|
||||
return (wd && (category::flags::root == wd->other.category));
|
||||
}
|
||||
|
||||
std::size_t window_manager::number_of_core_window() const
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
|
||||
return impl_->wd_register.size();
|
||||
}
|
||||
|
||||
@ -419,7 +464,9 @@ namespace detail
|
||||
|
||||
void window_manager::all_handles(std::vector<core_window_t*> &v) const
|
||||
{
|
||||
impl_->wd_register.all(v);
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
v = impl_->wd_register.queue();
|
||||
}
|
||||
|
||||
void window_manager::event_filter(core_window_t* wd, bool is_make, event_code evtid)
|
||||
@ -436,11 +483,15 @@ namespace detail
|
||||
|
||||
bool window_manager::available(core_window_t* wd)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
return impl_->wd_register.available(wd);
|
||||
}
|
||||
|
||||
bool window_manager::available(core_window_t * a, core_window_t* b)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
return (impl_->wd_register.available(a) && impl_->wd_register.available(b));
|
||||
}
|
||||
|
||||
@ -492,7 +543,7 @@ namespace detail
|
||||
auto* value = impl_->misc_register.insert(result.native_handle, root_misc(wd, result.width, result.height));
|
||||
|
||||
wd->bind_native_window(result.native_handle, result.width, result.height, result.extra_width, result.extra_height, value->root_graph);
|
||||
impl_->wd_register.insert(wd, wd->thread_id);
|
||||
impl_->wd_register.insert(wd);
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if (owner && (category::flags::frame == owner->other.category))
|
||||
@ -573,7 +624,8 @@ namespace detail
|
||||
wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::lite_widget_tag**)nullptr);
|
||||
else
|
||||
wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::widget_tag**)nullptr);
|
||||
impl_->wd_register.insert(wd, wd->thread_id);
|
||||
|
||||
impl_->wd_register.insert(wd);
|
||||
return wd;
|
||||
}
|
||||
|
||||
@ -660,21 +712,47 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
void window_manager::default_icon(const nana::paint::image& _small, const nana::paint::image& big)
|
||||
{
|
||||
impl_->default_icon_big = big;
|
||||
impl_->default_icon_small = _small;
|
||||
}
|
||||
|
||||
void window_manager::icon(core_window_t* wd, const paint::image& small_icon, const paint::image& big_icon)
|
||||
{
|
||||
if(!big_icon.empty() || !small_icon.empty())
|
||||
{
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
if (nullptr == wd)
|
||||
{
|
||||
if(category::flags::root == wd->other.category)
|
||||
native_interface::window_icon(wd->root, small_icon, big_icon);
|
||||
impl_->default_icon_big = big_icon;
|
||||
impl_->default_icon_small = small_icon;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
{
|
||||
if (category::flags::root == wd->other.category)
|
||||
native_interface::window_icon(wd->root, small_icon, big_icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sync_child_root_display(window_manager::core_window_t* wd)
|
||||
{
|
||||
for (auto & child : wd->children)
|
||||
{
|
||||
if (category::flags::root != child->other.category)
|
||||
{
|
||||
sync_child_root_display(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const vs_parents = child->visible_parents();
|
||||
|
||||
if (vs_parents != child->visible)
|
||||
{
|
||||
native_interface::show_window(child->root, vs_parents, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (child->visible != native_interface::is_window_visible(child->root))
|
||||
native_interface::show_window(child->root, child->visible, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -713,13 +791,20 @@ namespace detail
|
||||
if(category::flags::root != wd->other.category)
|
||||
bedrock::instance().event_expose(wd, visible);
|
||||
|
||||
if(nv)
|
||||
if (nv)
|
||||
{
|
||||
if (visible && !wd->visible_parents())
|
||||
return true;
|
||||
|
||||
native_interface::show_window(nv, visible, wd->flags.take_active);
|
||||
}
|
||||
|
||||
sync_child_root_display(wd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
window_manager::core_window_t* window_manager::find_window(native_window_type root, int x, int y)
|
||||
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos)
|
||||
{
|
||||
if (nullptr == root)
|
||||
return nullptr;
|
||||
@ -729,7 +814,6 @@ namespace detail
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
auto rrt = root_runtime(root);
|
||||
point pos{ x, y };
|
||||
if (rrt && _m_effective(rrt->window, pos))
|
||||
return _m_find(rrt->window, pos);
|
||||
}
|
||||
@ -759,6 +843,10 @@ namespace detail
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
arg.x = x;
|
||||
arg.y = y;
|
||||
|
||||
if (wd->effect.bground)
|
||||
wd->other.upd_state = basic_window::update_state::request_refresh;
|
||||
|
||||
brock.emit(event_code::move, wd, arg, true, brock.get_thread_context());
|
||||
return true;
|
||||
}
|
||||
@ -797,12 +885,14 @@ namespace detail
|
||||
//Move child widgets
|
||||
if(r.x != wd->pos_owner.x || r.y != wd->pos_owner.y)
|
||||
{
|
||||
point delta{ r.x - wd->pos_owner.x, r.y - wd->pos_owner.y };
|
||||
wd->pos_owner.x = r.x;
|
||||
wd->pos_owner.y = r.y;
|
||||
auto delta = r.position() - wd->pos_owner;
|
||||
wd->pos_owner = r.position();
|
||||
_m_move_core(wd, delta);
|
||||
moved = true;
|
||||
|
||||
if ((!size_changed) && wd->effect.bground)
|
||||
wd->other.upd_state = basic_window::update_state::request_refresh;
|
||||
|
||||
arg_move arg;
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
arg.x = r.x;
|
||||
@ -989,26 +1079,28 @@ namespace detail
|
||||
|
||||
if (wd->displayed())
|
||||
{
|
||||
using paint_operation = window_layer::paint_operation;
|
||||
|
||||
if(forced || (false == wd->belong_to_lazy()))
|
||||
{
|
||||
if (!wd->flags.refreshing)
|
||||
{
|
||||
window_layer::paint(wd, redraw, false);
|
||||
window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false);
|
||||
this->map(wd, forced, update_area);
|
||||
return true;
|
||||
}
|
||||
else if (forced)
|
||||
{
|
||||
window_layer::paint(wd, false, false);
|
||||
window_layer::paint(wd, paint_operation::none, false);
|
||||
this->map(wd, true, update_area);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (redraw)
|
||||
window_layer::paint(wd, true, false);
|
||||
window_layer::paint(wd, paint_operation::try_refresh, false);
|
||||
|
||||
if (wd->other.upd_state == core_window_t::update_state::lazy)
|
||||
wd->other.upd_state = core_window_t::update_state::refresh;
|
||||
wd->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1020,43 +1112,43 @@ namespace detail
|
||||
|
||||
//It's not worthy to redraw if visible is false
|
||||
if (impl_->wd_register.available(wd) && wd->displayed())
|
||||
window_layer::paint(wd, true, true);
|
||||
window_layer::paint(wd, window_layer::paint_operation::try_refresh, true);
|
||||
}
|
||||
|
||||
//do_lazy_refresh
|
||||
//@brief: defined a behavior of flush the screen
|
||||
//@return: it returns true if the wnd is available
|
||||
bool window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree)
|
||||
void window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
|
||||
if (false == impl_->wd_register.available(wd))
|
||||
return false;
|
||||
return;
|
||||
|
||||
//It's not worthy to redraw if visible is false
|
||||
if(wd->visible && (!wd->is_draw_through()))
|
||||
{
|
||||
using paint_operation = window_layer::paint_operation;
|
||||
if (wd->visible_parents())
|
||||
{
|
||||
if ((wd->other.upd_state == core_window_t::update_state::refresh) || force_copy_to_screen)
|
||||
if ((wd->other.upd_state == core_window_t::update_state::refreshed) || (wd->other.upd_state == core_window_t::update_state::request_refresh) || force_copy_to_screen)
|
||||
{
|
||||
window_layer::paint(wd, false, refresh_tree);
|
||||
window_layer::paint(wd, (wd->other.upd_state == core_window_t::update_state::request_refresh ? paint_operation::try_refresh : paint_operation::have_refreshed), refresh_tree);
|
||||
this->map(wd, force_copy_to_screen);
|
||||
}
|
||||
else if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
|
||||
{
|
||||
//The window is still mapped because of edge nimbus effect.
|
||||
//Avoid duplicate copy if action state is not changed and the window is not focused.
|
||||
if ((wd->flags.action != wd->flags.action_before) || (bedrock::instance().focus() == wd))
|
||||
if (wd->flags.action != wd->flags.action_before)
|
||||
this->map(wd, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
window_layer::paint(wd, true, refresh_tree); //only refreshing if it has an invisible parent
|
||||
window_layer::paint(wd, paint_operation::try_refresh, refresh_tree); //only refreshing if it has an invisible parent
|
||||
}
|
||||
wd->other.upd_state = core_window_t::update_state::none;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
//get_graphics
|
||||
@ -1305,13 +1397,13 @@ namespace detail
|
||||
{
|
||||
auto & tabs = wd->root_widget->other.attribute.root->tabstop;
|
||||
|
||||
auto end = tabs.cend();
|
||||
if (forward)
|
||||
{
|
||||
if (detail::tab_type::none == wd->flags.tab)
|
||||
return (tabs.front());
|
||||
else if (detail::tab_type::tabstop & wd->flags.tab)
|
||||
{
|
||||
auto end = tabs.cend();
|
||||
auto i = std::find(tabs.cbegin(), end, wd);
|
||||
if (i != end)
|
||||
{
|
||||
@ -1325,8 +1417,8 @@ namespace detail
|
||||
}
|
||||
else if (tabs.size() > 1) //at least 2 elments in tabs are required when moving backward.
|
||||
{
|
||||
auto i = std::find(tabs.cbegin(), tabs.cend(), wd);
|
||||
if (i != tabs.cend())
|
||||
auto i = std::find(tabs.cbegin(), end, wd);
|
||||
if (i != end)
|
||||
return (tabs.cbegin() == i ? tabs.back() : *(i - 1));
|
||||
}
|
||||
return nullptr;
|
||||
@ -1371,6 +1463,8 @@ namespace detail
|
||||
|
||||
void window_manager::remove_trash_handle(unsigned tid)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
impl_->wd_register.delete_trash(tid);
|
||||
}
|
||||
|
||||
@ -1635,7 +1729,7 @@ namespace detail
|
||||
|
||||
if (established)
|
||||
{
|
||||
utl::erase(pa_children, wd);
|
||||
utl::erase(wd->parent->children, wd);
|
||||
if (for_new->children.empty())
|
||||
wd->index = 0;
|
||||
else
|
||||
@ -1724,32 +1818,18 @@ namespace detail
|
||||
brock.emit(event_code::destroy, wd, arg, true, brock.get_thread_context());
|
||||
|
||||
//Delete the children widgets.
|
||||
for (auto i = wd->children.rbegin(), end = wd->children.rend(); i != end;)
|
||||
while (!wd->children.empty())
|
||||
{
|
||||
auto child = *i;
|
||||
|
||||
auto child = wd->children.back();
|
||||
if (category::flags::root == child->other.category)
|
||||
{
|
||||
//closing a child root window erases itself from wd->children,
|
||||
//to make sure the iterator is valid, it must be reloaded.
|
||||
|
||||
auto offset = std::distance(wd->children.rbegin(), i);
|
||||
|
||||
//!!!
|
||||
//a potential issue is that if the calling thread is not same with child's thread,
|
||||
//the child root window may not be erased from wd->children now.
|
||||
//Only the nested_form meets the condition
|
||||
native_interface::close_window(child->root);
|
||||
|
||||
i = wd->children.rbegin();
|
||||
std::advance(i, offset);
|
||||
end = wd->children.rend();
|
||||
continue;
|
||||
}
|
||||
_m_destroy(child);
|
||||
++i;
|
||||
wd->children.pop_back();
|
||||
}
|
||||
wd->children.clear();
|
||||
|
||||
|
||||
_m_disengage(wd, nullptr);
|
||||
window_layer::enable_effects_bground(wd, false);
|
||||
@ -1812,15 +1892,20 @@ namespace detail
|
||||
if(!wd->visible)
|
||||
return nullptr;
|
||||
|
||||
for(auto i = wd->children.rbegin(); i != wd->children.rend(); ++i)
|
||||
if (!wd->children.empty())
|
||||
{
|
||||
core_window_t* child = *i;
|
||||
if((child->other.category != category::flags::root) && _m_effective(child, pos))
|
||||
auto index = wd->children.size();
|
||||
|
||||
do
|
||||
{
|
||||
child = _m_find(child, pos);
|
||||
if(child)
|
||||
return child;
|
||||
}
|
||||
auto child = wd->children[--index];
|
||||
if ((child->other.category != category::flags::root) && _m_effective(child, pos))
|
||||
{
|
||||
child = _m_find(child, pos);
|
||||
if (child)
|
||||
return child;
|
||||
}
|
||||
} while (0 != index);
|
||||
}
|
||||
return wd;
|
||||
}
|
||||
|
||||
202
source/gui/detail/window_register.hpp
Normal file
202
source/gui/detail/window_register.hpp
Normal file
@ -0,0 +1,202 @@
|
||||
#ifndef NANA_WINDOW_REGISTER_HEADER_INCLUDED
|
||||
#define NANA_WINDOW_REGISTER_HEADER_INCLUDED
|
||||
|
||||
#include <nana/gui/detail/basic_window.hpp>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm> //std::find
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Key, typename Value, std::size_t CacheSize>
|
||||
class cache
|
||||
: noncopyable
|
||||
{
|
||||
public:
|
||||
typedef Key key_type;
|
||||
typedef Value value_type;
|
||||
typedef std::pair<key_type, value_type> pair_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
cache()
|
||||
:addr_(reinterpret_cast<pair_type*>(::operator new(sizeof(pair_type) * CacheSize)))
|
||||
{
|
||||
for (std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
bitmap_[i] = 0;
|
||||
seq_[i] = nana::npos;
|
||||
}
|
||||
}
|
||||
|
||||
~cache()
|
||||
{
|
||||
for (std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
if (bitmap_[i])
|
||||
addr_[i].~pair_type();
|
||||
}
|
||||
|
||||
::operator delete(addr_);
|
||||
}
|
||||
|
||||
bool insert(key_type k, value_type v)
|
||||
{
|
||||
size_type pos = _m_find_key(k);
|
||||
if (pos != nana::npos)
|
||||
{
|
||||
addr_[pos].second = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
//No key exists
|
||||
pos = _m_find_pos();
|
||||
|
||||
if (pos == nana::npos)
|
||||
{ //No room, and remove the last pair
|
||||
pos = seq_[CacheSize - 1];
|
||||
(addr_ + pos)->~pair_type();
|
||||
}
|
||||
|
||||
if (seq_[0] != nana::npos)
|
||||
{//Need to move
|
||||
for (int i = CacheSize - 1; i > 0; --i)
|
||||
seq_[i] = seq_[i - 1];
|
||||
}
|
||||
|
||||
seq_[0] = pos;
|
||||
|
||||
new (addr_ + pos) pair_type(k, v);
|
||||
bitmap_[pos] = 1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type * get(key_type k)
|
||||
{
|
||||
size_type pos = _m_find_key(k);
|
||||
if (pos != nana::npos)
|
||||
return &(addr_[pos].second);
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
size_type _m_find_key(key_type k) const
|
||||
{
|
||||
for (std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
if (bitmap_[i] && (addr_[i].first == k))
|
||||
return i;
|
||||
}
|
||||
return nana::npos;
|
||||
}
|
||||
|
||||
size_type _m_find_pos() const
|
||||
{
|
||||
for (std::size_t i = 0; i < CacheSize; ++i)
|
||||
{
|
||||
if (bitmap_[i] == 0)
|
||||
return i;
|
||||
}
|
||||
return nana::npos;
|
||||
}
|
||||
private:
|
||||
char bitmap_[CacheSize];
|
||||
size_type seq_[CacheSize];
|
||||
pair_type * addr_;
|
||||
};
|
||||
|
||||
class window_register
|
||||
{
|
||||
public:
|
||||
using window_handle_type = basic_window*;
|
||||
|
||||
void insert(window_handle_type wd)
|
||||
{
|
||||
if (wd)
|
||||
{
|
||||
base_.insert(wd);
|
||||
wdcache_.insert(wd, true);
|
||||
|
||||
if (category::flags::root == wd->other.category)
|
||||
queue_.push_back(wd);
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(window_handle_type wd)
|
||||
{
|
||||
remove(wd);
|
||||
}
|
||||
|
||||
void remove(window_handle_type wd)
|
||||
{
|
||||
if (base_.erase(wd))
|
||||
{
|
||||
wdcache_.insert(wd, false);
|
||||
trash_.push_back(wd);
|
||||
|
||||
if (category::flags::root == wd->other.category)
|
||||
{
|
||||
auto i = std::find(queue_.begin(), queue_.end(), wd);
|
||||
if (i != queue_.end())
|
||||
queue_.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delete_trash(unsigned thread_id)
|
||||
{
|
||||
if (0 == thread_id)
|
||||
{
|
||||
for (auto wd : trash_)
|
||||
delete wd;
|
||||
|
||||
trash_.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto i = trash_.begin(); i != trash_.end();)
|
||||
{
|
||||
if (thread_id == (*i)->thread_id)
|
||||
{
|
||||
delete (*i);
|
||||
i = trash_.erase(i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<window_handle_type>& queue() const
|
||||
{
|
||||
return queue_;
|
||||
}
|
||||
|
||||
/// Returns the number of registered windows
|
||||
std::size_t size() const
|
||||
{
|
||||
return base_.size();
|
||||
}
|
||||
|
||||
bool available(window_handle_type wd) const
|
||||
{
|
||||
if (nullptr == wd)
|
||||
return false;
|
||||
|
||||
auto exists = wdcache_.get(wd);
|
||||
if (exists)
|
||||
return *exists;
|
||||
|
||||
return wdcache_.insert(wd, (base_.count(wd) != 0));
|
||||
}
|
||||
private:
|
||||
mutable cache<window_handle_type, bool, 5> wdcache_;
|
||||
std::set<window_handle_type> base_;
|
||||
std::vector<window_handle_type> trash_;
|
||||
std::vector<window_handle_type> queue_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Elements of GUI Gadgets
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -148,22 +148,22 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
::nana::color highlighted(0x5e, 0xb6, 0xf7);
|
||||
::nana::color highlighted(static_cast<color_rgb>(0x5eb6f7));
|
||||
auto bld_bgcolor = bgcolor;
|
||||
auto bld_fgcolor = fgcolor;
|
||||
switch(es)
|
||||
{
|
||||
case element_state::hovered:
|
||||
case element_state::focus_hovered:
|
||||
bld_bgcolor = bgcolor.blend(highlighted, 0.8);
|
||||
bld_fgcolor = fgcolor.blend(highlighted, 0.8);
|
||||
bld_bgcolor = bgcolor.blend(highlighted, 0.2);
|
||||
bld_fgcolor = fgcolor.blend(highlighted, 0.2);
|
||||
break;
|
||||
case element_state::pressed:
|
||||
bld_bgcolor = bgcolor.blend(highlighted, 0.4);
|
||||
bld_fgcolor = fgcolor.blend(highlighted, 0.4);
|
||||
bld_bgcolor = bgcolor.blend(highlighted, 0.6);
|
||||
bld_fgcolor = fgcolor.blend(highlighted, 0.6);
|
||||
break;
|
||||
case element_state::disabled:
|
||||
bld_bgcolor = bld_fgcolor = nana::color(0xb2, 0xb7, 0xbc);
|
||||
bld_bgcolor = bld_fgcolor = static_cast<color_rgb>(0xb2b7bc);
|
||||
break;
|
||||
default:
|
||||
//Leave things as they are
|
||||
@ -493,10 +493,10 @@ namespace nana
|
||||
{
|
||||
case element_state::hovered:
|
||||
case element_state::focus_hovered:
|
||||
bgcolor = arg_bgcolor.blend(colors::white, 0.8);
|
||||
bgcolor = arg_bgcolor.blend(colors::white, 0.2);
|
||||
break;
|
||||
case element_state::pressed:
|
||||
bgcolor = arg_bgcolor.blend(colors::black, 0.8);
|
||||
bgcolor = arg_bgcolor.blend(colors::black, 0.2);
|
||||
break;
|
||||
case element_state::disabled:
|
||||
bgcolor = colors::dark_gray;
|
||||
@ -505,13 +505,13 @@ namespace nana
|
||||
}
|
||||
|
||||
auto part_px = (r.height - 3) * 5 / 13;
|
||||
graph.rectangle(r, false, bgcolor.blend(colors::black, 0.6));
|
||||
graph.rectangle(r, false, bgcolor.blend(colors::black, 0.4));
|
||||
|
||||
::nana::point left_top{ r.x + 1, r.y + 1 }, right_top{r.right() - 2, r.y + 1};
|
||||
::nana::point left_mid{ r.x + 1, r.y + 1 + static_cast<int>(part_px) }, right_mid{ right_top.x, left_mid.y };
|
||||
::nana::point left_bottom{ r.x + 1, r.bottom() - 2 }, right_bottom{ r.right() - 2, r.bottom() - 2 };
|
||||
|
||||
graph.palette(false, bgcolor.blend(colors::white, 0.9));
|
||||
graph.palette(false, bgcolor.blend(colors::white, 0.1));
|
||||
graph.line(left_top, left_mid);
|
||||
graph.line(right_top, right_mid);
|
||||
|
||||
@ -520,12 +520,12 @@ namespace nana
|
||||
|
||||
left_mid.y++;
|
||||
right_mid.y++;
|
||||
graph.palette(false, bgcolor.blend(colors::black, 0.8));
|
||||
graph.palette(false, bgcolor.blend(colors::black, 0.2));
|
||||
graph.line(left_mid, left_bottom);
|
||||
graph.line(right_mid, right_bottom);
|
||||
|
||||
::nana::rectangle part_r{ r.x + 2, r.y + 2, r.width - 4, part_px };
|
||||
graph.rectangle(part_r, true, bgcolor.blend(colors::white, 0.8));
|
||||
graph.rectangle(part_r, true, bgcolor.blend(colors::white, 0.2));
|
||||
|
||||
part_r.y += static_cast<int>(part_r.height);
|
||||
part_r.height = (r.height - 3 - part_r.height);
|
||||
@ -545,7 +545,7 @@ namespace nana
|
||||
{
|
||||
case element_state::hovered:
|
||||
case element_state::pressed:
|
||||
clr = clr.blend(colors::black, 0.8);
|
||||
clr = clr.blend(colors::black, 0.2);
|
||||
break;
|
||||
case element_state::disabled:
|
||||
clr = colors::dark_gray;
|
||||
@ -954,7 +954,7 @@ namespace nana
|
||||
ps[11].x = r.x + gap;
|
||||
ps[11].y = r.y + gap;
|
||||
|
||||
graph.palette(false, fgcolor.blend(colors::black, true));
|
||||
graph.palette(false, fgcolor.blend(colors::black, 1.0 - fgcolor.a()));
|
||||
|
||||
for (int i = 0; i < 11; ++i)
|
||||
graph.line(ps[i], ps[i + 1]);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Filebox
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -44,13 +44,13 @@ namespace nana
|
||||
std::string name;
|
||||
::tm modified_time;
|
||||
bool directory;
|
||||
nana::long_long_t bytes;
|
||||
long long bytes;
|
||||
|
||||
friend listbox::iresolver& operator>>(listbox::iresolver& ires, item_fs& m)
|
||||
{
|
||||
std::wstring type;
|
||||
ires>>m.name>>type>>type;
|
||||
m.directory = (type == L"Directory");
|
||||
m.directory = (to_utf8(type) == internationalization()("NANA_FILEBOX_DIRECTORY"));
|
||||
return ires;
|
||||
}
|
||||
|
||||
@ -65,6 +65,8 @@ namespace nana
|
||||
_m_add(tm, item.modified_time.tm_min)<<':';
|
||||
_m_add(tm, item.modified_time.tm_sec);
|
||||
|
||||
internationalization i18n;
|
||||
|
||||
ores<<item.name<<tm.str();
|
||||
if(!item.directory)
|
||||
{
|
||||
@ -72,12 +74,12 @@ namespace nana
|
||||
if(pos != item.name.npos && (pos + 1 < item.name.size()))
|
||||
ores<<item.name.substr(pos + 1);
|
||||
else
|
||||
ores<<L"File";
|
||||
ores<<i18n("NANA_FILEBOX_FILE");
|
||||
|
||||
ores<<_m_trans(item.bytes);
|
||||
}
|
||||
else
|
||||
ores<<L"Directory";
|
||||
ores << i18n("NANA_FILEBOX_DIRECTORY");
|
||||
return ores;
|
||||
}
|
||||
|
||||
@ -114,7 +116,8 @@ namespace nana
|
||||
|
||||
return s + ustr[uid];
|
||||
}
|
||||
ss<<bytes<<" Bytes";
|
||||
internationalization i18n;
|
||||
ss<<bytes<<" "<<i18n("NANA_FILEBOX_BYTES");
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
@ -138,6 +141,7 @@ namespace nana
|
||||
filebox_implement(window owner, bool io_read, const std::string& title)
|
||||
: form(owner, API::make_center(owner, 630, 440)), io_read_(io_read)
|
||||
{
|
||||
internationalization i18n;
|
||||
path_.create(*this);
|
||||
path_.splitstr("/");
|
||||
path_.events().selected.connect_unignorable([this](const arg_categorize<int>&)
|
||||
@ -157,7 +161,7 @@ namespace nana
|
||||
|
||||
filter_.create(*this);
|
||||
filter_.multi_lines(false);
|
||||
filter_.tip_string("Filter");
|
||||
filter_.tip_string(i18n("NANA_FILEBOX_FILTER"));
|
||||
|
||||
filter_.events().key_release.connect_unignorable([this](const arg_keyboard&)
|
||||
{
|
||||
@ -165,23 +169,23 @@ namespace nana
|
||||
});
|
||||
|
||||
btn_folder_.create(*this);
|
||||
btn_folder_.caption("&New Folder");
|
||||
btn_folder_.i18n(i18n_eval("NANA_FILEBOX_NEW_FOLDER_SHORTKEY"));
|
||||
|
||||
btn_folder_.events().click.connect_unignorable([this](const arg_click&)
|
||||
{
|
||||
form fm(this->handle(), API::make_center(*this, 300, 35));
|
||||
fm.caption("Name the new folder");
|
||||
fm.i18n(i18n_eval("NANA_FILEBOX_NEW_FOLDER_CAPTION"));
|
||||
|
||||
textbox folder(fm, nana::rectangle(5, 5, 160, 25));
|
||||
folder.multi_lines(false);
|
||||
|
||||
button btn(fm, nana::rectangle(170, 5, 60, 25));
|
||||
btn.caption("Create");
|
||||
btn.i18n(i18n_eval("NANA_BUTTON_CREATE"));
|
||||
|
||||
btn.events().click.connect_unignorable(folder_creator(*this, fm, folder));
|
||||
|
||||
button btn_cancel(fm, nana::rectangle(235, 5, 60, 25));
|
||||
btn_cancel.caption("Cancel");
|
||||
btn_cancel.i18n(i18n_eval("NANA_BUTTON_CANCEL"));
|
||||
|
||||
btn_cancel.events().click.connect_unignorable([&fm](const arg_click&)
|
||||
{
|
||||
@ -193,10 +197,10 @@ namespace nana
|
||||
tree_.create(*this);
|
||||
|
||||
ls_file_.create(*this);
|
||||
ls_file_.append_header("Name", 190);
|
||||
ls_file_.append_header("Modified", 145);
|
||||
ls_file_.append_header("Type", 80);
|
||||
ls_file_.append_header("Size", 70);
|
||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_NAME"), 190);
|
||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_MODIFIED"), 145);
|
||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_TYPE"), 80);
|
||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70);
|
||||
|
||||
auto fn_sel_file = [this](const arg_mouse& arg){
|
||||
_m_sel_file(arg);
|
||||
@ -274,7 +278,7 @@ namespace nana
|
||||
});
|
||||
|
||||
lb_file_.create(*this);
|
||||
lb_file_.caption("File:");
|
||||
lb_file_.i18n(i18n_eval("NANA_FILEBOX_FILE_COLON"));
|
||||
|
||||
tb_file_.create(*this);
|
||||
tb_file_.multi_lines(false);
|
||||
@ -290,14 +294,15 @@ namespace nana
|
||||
cb_types_.events().selected.connect_unignorable([this](const arg_combox&){ _m_list_fs(); });
|
||||
|
||||
btn_ok_.create(*this);
|
||||
btn_ok_.caption("&OK");
|
||||
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY"));
|
||||
|
||||
|
||||
btn_ok_.events().click.connect_unignorable([this](const arg_click&)
|
||||
{
|
||||
_m_ok();
|
||||
});
|
||||
btn_cancel_.create(*this);
|
||||
btn_cancel_.caption("&Cancel");
|
||||
btn_cancel_.i18n(i18n_eval("NANA_BUTTON_CANCEL_SHORTKEY"));
|
||||
|
||||
btn_cancel_.events().click.connect_unignorable([this](const arg_click&)
|
||||
{
|
||||
@ -309,7 +314,7 @@ namespace nana
|
||||
_m_init_tree();
|
||||
|
||||
if(0 == title.size())
|
||||
caption(io_read ? "Open" : "Save As");
|
||||
this->i18n(i18n_eval(io_read ? "NANA_FILEBOX_OPEN" : "NANA_FILEBOX_SAVE_AS"));
|
||||
else
|
||||
caption(title);
|
||||
}
|
||||
@ -640,11 +645,12 @@ namespace nana
|
||||
{
|
||||
auto path = tx_path_.caption();
|
||||
|
||||
msgbox mb(fm_, "Create Folder");
|
||||
internationalization i18n;
|
||||
msgbox mb(fm_, i18n("NANA_FILEBOX_NEW_FOLDER"));
|
||||
mb.icon(msgbox::icon_warning);
|
||||
if(0 == path.size() || path[0] == '.' || path[0] == '/')
|
||||
{
|
||||
mb<<L"Please input a valid name for the new folder.";
|
||||
mb << i18n("NANA_FILEBOX_ERROR_INVALID_FOLDER_NAME");
|
||||
mb();
|
||||
return;
|
||||
}
|
||||
@ -657,14 +663,14 @@ namespace nana
|
||||
|
||||
if(fst.type() != file_type::not_found && fst.type() != file_type::none)
|
||||
{
|
||||
mb<<L"The folder is existing, please rename it.";
|
||||
mb<<i18n("NANA_FILEBOX_ERROR_RENAME_FOLDER_BECAUSE_OF_EXISTING");
|
||||
mb();
|
||||
return;
|
||||
}
|
||||
|
||||
if(false == fs::create_directory(fspath))
|
||||
{
|
||||
mb<<L"Failed to create the folder, please rename it.";
|
||||
mb<<i18n("NANA_FILEBOX_ERROR_RENAME_FOLDER_BECAUSE_OF_FAILED_CREATION");
|
||||
mb();
|
||||
return;
|
||||
}
|
||||
@ -734,69 +740,74 @@ namespace nana
|
||||
|
||||
void _m_ok()
|
||||
{
|
||||
if(0 == selection_.target.size())
|
||||
std::string tar = selection_.target;
|
||||
|
||||
if(selection_.target.empty())
|
||||
{
|
||||
auto file = tb_file_.caption();
|
||||
if(file.size())
|
||||
{
|
||||
if(file[0] == L'.')
|
||||
internationalization i18n;
|
||||
if(file[0] == '.')
|
||||
{
|
||||
msgbox mb(*this, caption());
|
||||
mb.icon(msgbox::icon_warning);
|
||||
mb<<file<<std::endl<<L"The filename is invalid.";
|
||||
mb<<file<<std::endl<<i18n("NANA_FILEBOX_ERROR_INVALID_FILENAME");
|
||||
mb();
|
||||
return;
|
||||
}
|
||||
std::string tar;
|
||||
|
||||
if(file[0] == '/')
|
||||
tar = file;
|
||||
else
|
||||
tar = addr_.filesystem + file;
|
||||
|
||||
|
||||
bool good = true;
|
||||
|
||||
auto fattr = fs::status(tar);
|
||||
if(fattr.type() == fs::file_type::not_found)
|
||||
|
||||
//Check if the selected name is a directory
|
||||
auto is_dir = fs::is_directory(fattr);
|
||||
|
||||
if(!is_dir && _m_append_def_extension(tar))
|
||||
{
|
||||
good = (_m_append_def_extension(tar) && (fs::status(tar).type() == fs::file_type::not_found));
|
||||
//Add the extension, then check if it is a directory again.
|
||||
fattr = fs::status(tar);
|
||||
is_dir = fs::is_directory(fattr);
|
||||
}
|
||||
|
||||
if(good && fs::is_directory(fattr))
|
||||
if(is_dir)
|
||||
{
|
||||
_m_load_cat_path(tar);
|
||||
tb_file_.caption("");
|
||||
tb_file_.caption(std::string{});
|
||||
return;
|
||||
}
|
||||
|
||||
if(io_read_)
|
||||
{
|
||||
if(false == good)
|
||||
if(fs::file_type::not_found == fattr.type())
|
||||
{
|
||||
msgbox mb(*this, caption());
|
||||
mb.icon(msgbox::icon_information);
|
||||
mb<<L"The file \""<<nana::charset(tar, nana::unicode::utf8)<<L"\"\n is not existing. Please check and retry.";
|
||||
mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar);
|
||||
mb();
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
_m_finish(kind::filesystem, tar);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(good)
|
||||
if(fs::file_type::not_found != fattr.type())
|
||||
{
|
||||
msgbox mb(*this, caption(), msgbox::yes_no);
|
||||
mb.icon(msgbox::icon_question);
|
||||
mb<<L"The input file is existing, do you want to overwrite it?";
|
||||
mb<<i18n("NANA_FILEBOX_ERROR_QUERY_REWRITE_BECAUSE_OF_EXISTING");
|
||||
if(msgbox::pick_no == mb())
|
||||
return;
|
||||
}
|
||||
_m_finish(kind::filesystem, tar);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
_m_finish(kind::filesystem, selection_.target);
|
||||
|
||||
_m_finish(kind::filesystem, tar);
|
||||
}
|
||||
|
||||
void _m_tr_expand(item_proxy node, bool exp)
|
||||
@ -986,6 +997,9 @@ namespace nana
|
||||
|
||||
OPENFILENAME ofn;
|
||||
memset(&ofn, 0, sizeof ofn);
|
||||
|
||||
internal_scope_guard lock;
|
||||
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = reinterpret_cast<HWND>(API::root(impl_->owner));
|
||||
ofn.lpstrFile = &(wfile[0]);
|
||||
@ -1045,8 +1059,11 @@ namespace nana
|
||||
ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode
|
||||
ofn.Flags |= OFN_NOCHANGEDIR;
|
||||
|
||||
if(FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn)))
|
||||
return false;
|
||||
{
|
||||
internal_revert_guard revert;
|
||||
if (FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn)))
|
||||
return false;
|
||||
}
|
||||
|
||||
wfile.resize(std::wcslen(wfile.data()));
|
||||
impl_->file = to_utf8(wfile);
|
||||
|
||||
@ -61,14 +61,14 @@ namespace nana
|
||||
{
|
||||
_m_click(arg);
|
||||
});
|
||||
yes_.i18n(i18n_eval("OK"));
|
||||
yes_.i18n(i18n_eval("NANA_BUTTON_OK"));
|
||||
width_pixel += 77;
|
||||
|
||||
if(msgbox::yes_no == btn || msgbox::yes_no_cancel == btn)
|
||||
{
|
||||
yes_.i18n(i18n_eval("Yes"));
|
||||
yes_.i18n(i18n_eval("NANA_BUTTON_YES"));
|
||||
no_.create(*this);
|
||||
no_.i18n(i18n_eval("No"));
|
||||
no_.i18n(i18n_eval("NANA_BUTTON_NO"));
|
||||
no_.events().click.connect_unignorable([this](const arg_click& arg)
|
||||
{
|
||||
_m_click(arg);
|
||||
@ -79,7 +79,7 @@ namespace nana
|
||||
if(msgbox::yes_no_cancel == btn)
|
||||
{
|
||||
cancel_.create(*this);
|
||||
cancel_.i18n(i18n_eval("Cancel"));
|
||||
cancel_.i18n(i18n_eval("NANA_BUTTON_CANCEL"));
|
||||
cancel_.events().click.connect_unignorable([this](const arg_click& arg)
|
||||
{
|
||||
_m_click(arg);
|
||||
@ -493,7 +493,7 @@ namespace nana
|
||||
auto desc_extent = desc_.measure(470);
|
||||
|
||||
btn_ok_.create(*this);
|
||||
btn_ok_.i18n(i18n_eval("OK"));
|
||||
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK"));
|
||||
btn_ok_.events().click.connect_unignorable([this]{
|
||||
|
||||
if (verifier_ && !verifier_(handle()))
|
||||
@ -504,7 +504,7 @@ namespace nana
|
||||
});
|
||||
|
||||
btn_cancel_.create(*this);
|
||||
btn_cancel_.i18n(i18n_eval("Cancel"));
|
||||
btn_cancel_.i18n(i18n_eval("NANA_BUTTON_CANCEL"));
|
||||
btn_cancel_.events().click.connect_unignorable([this]{
|
||||
close();
|
||||
});
|
||||
@ -618,7 +618,7 @@ namespace nana
|
||||
place_.field_display(img_fields[i], false);
|
||||
}
|
||||
|
||||
size({desc_extent.width, height });
|
||||
move(API::make_center(this->owner(), desc_extent.width, height));
|
||||
caption(title);
|
||||
}
|
||||
|
||||
@ -1141,7 +1141,7 @@ namespace nana
|
||||
impl->path_edit.multi_lines(false);
|
||||
|
||||
impl->browse.create(impl->dock);
|
||||
impl->browse.i18n(i18n_eval("Browse"));
|
||||
impl->browse.i18n(i18n_eval("NANA_BUTTON_BROWSE"));
|
||||
impl->browse.events().click.connect_unignorable([wd, impl](const arg_click&)
|
||||
{
|
||||
impl->fbox.owner(wd);
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../detail/platform_spec_selector.hpp"
|
||||
|
||||
#if defined(NANA_LINUX) || defined(NANA_MACOS)
|
||||
#include <nana/system/platform.hpp>
|
||||
@ -201,7 +201,7 @@ namespace nana
|
||||
#if defined(NANA_WINDOWS)
|
||||
void notifications_window_proc(HWND wd, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
arg_notifier arg;
|
||||
arg_notifier arg = {};
|
||||
switch (lparam)
|
||||
{
|
||||
case WM_LBUTTONDBLCLK:
|
||||
@ -321,6 +321,7 @@ namespace nana
|
||||
|
||||
void notifier::icon(const std::string& icon_file)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
paint::image image_ico{ icon_file };
|
||||
auto icon_handle = paint::image_accessor::icon(image_ico);
|
||||
if (icon_handle)
|
||||
@ -330,14 +331,21 @@ namespace nana
|
||||
impl_->set_icon(image_ico);
|
||||
impl_->icon = image_ico;
|
||||
}
|
||||
#else
|
||||
static_cast<void>(icon_file); //eliminate unused parameter warning
|
||||
#endif
|
||||
}
|
||||
|
||||
void notifier::insert_icon(const std::string& icon_file)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
paint::image image_ico{ icon_file };
|
||||
auto icon_handle = paint::image_accessor::icon(image_ico);
|
||||
if (icon_handle)
|
||||
impl_->icons.emplace_back(static_cast<paint::image&&>(image_ico));
|
||||
#else
|
||||
static_cast<void>(icon_file); //eliminate unused parameter warning
|
||||
#endif
|
||||
}
|
||||
|
||||
void notifier::period(unsigned ms)
|
||||
|
||||
1527
source/gui/place.cpp
1527
source/gui/place.cpp
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Parts of Class Place
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -29,21 +29,77 @@ namespace nana
|
||||
virtual ~splitter_interface(){}
|
||||
};
|
||||
|
||||
class splitter_dtrigger
|
||||
class drawer_splitter
|
||||
: public drawer_trigger
|
||||
{
|
||||
public:
|
||||
void set_renderer(const std::function<void(window, paint::graphics&, mouse_action)>& rd)
|
||||
{
|
||||
renderer_ = rd;
|
||||
}
|
||||
private:
|
||||
void attached(widget_reference wdg, graph_reference) override
|
||||
{
|
||||
window_handle_ = wdg;
|
||||
}
|
||||
|
||||
void refresh(graph_reference graph) override
|
||||
{
|
||||
API::dev::copy_transparent_background(window_handle_, graph);
|
||||
if (renderer_)
|
||||
renderer_(window_handle_, graph, API::mouse_action(window_handle_));
|
||||
}
|
||||
|
||||
void mouse_enter(graph_reference graph, const arg_mouse&) override
|
||||
{
|
||||
refresh(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_move(graph_reference graph, const arg_mouse&) override
|
||||
{
|
||||
refresh(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_leave(graph_reference graph, const arg_mouse&) override
|
||||
{
|
||||
refresh(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_down(graph_reference graph, const arg_mouse&)
|
||||
{
|
||||
refresh(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_up(graph_reference graph, const arg_mouse&)
|
||||
{
|
||||
refresh(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
private:
|
||||
window window_handle_{nullptr};
|
||||
std::function<void(window, paint::graphics&, mouse_action)> renderer_;
|
||||
};
|
||||
|
||||
template<bool IsLite>
|
||||
class splitter
|
||||
: public widget_object <typename std::conditional<IsLite, category::lite_widget_tag, category::widget_tag>::type, splitter_dtrigger>,
|
||||
: public widget_object<category::widget_tag, drawer_splitter>,
|
||||
public splitter_interface
|
||||
{
|
||||
public:
|
||||
void set_renderer(const std::function<void(window, paint::graphics&, mouse_action)>& rd)
|
||||
{
|
||||
get_drawer_trigger().set_renderer(rd);
|
||||
}
|
||||
private:
|
||||
void _m_complete_creation() override
|
||||
{
|
||||
this->caption("place-splitter");
|
||||
widget_object <typename std::conditional<IsLite, category::lite_widget_tag, category::widget_tag>::type, splitter_dtrigger>::_m_complete_creation();
|
||||
widget_object<category::widget_tag, drawer_splitter>::_m_complete_creation();
|
||||
|
||||
API::effects_bground(*this, effects::bground_transparent(0), 0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -92,8 +148,8 @@ namespace nana
|
||||
{
|
||||
color xclr = colors::red;
|
||||
|
||||
if(x_state_ == ::nana::mouse_action::pressed)
|
||||
xclr = xclr.blend(colors::white, 0.8);
|
||||
if(x_state_ == ::nana::mouse_action::pressed)
|
||||
xclr = xclr.blend(colors::white, 0.2);
|
||||
|
||||
graph.rectangle(r, true, xclr);
|
||||
}
|
||||
@ -144,11 +200,8 @@ namespace nana
|
||||
private:
|
||||
::nana::rectangle _m_button_area() const
|
||||
{
|
||||
::nana::rectangle r{API::window_size(window_handle_)};
|
||||
|
||||
r.x = r.right() - 20;
|
||||
r.width = 20;
|
||||
return r;
|
||||
auto sz = API::window_size(window_handle_);
|
||||
return{static_cast<int>(sz.width) - 20, 0, 20, sz.height};
|
||||
}
|
||||
public:
|
||||
window window_handle_;
|
||||
@ -161,12 +214,17 @@ namespace nana
|
||||
};
|
||||
|
||||
class dockarea_caption
|
||||
: public widget_object < category::widget_tag, dockcaption_dtrigger >
|
||||
: public widget_object<category::widget_tag, dockcaption_dtrigger>
|
||||
{
|
||||
public:
|
||||
using widget_object<category::widget_tag, dockcaption_dtrigger>::get_drawer_trigger;
|
||||
};
|
||||
|
||||
static unsigned differ(unsigned x, unsigned y) noexcept
|
||||
{
|
||||
return (x > y ? x - y : 0);
|
||||
}
|
||||
|
||||
class dockarea
|
||||
: public widget_object <category::lite_widget_tag, drawer_trigger>
|
||||
{
|
||||
@ -183,6 +241,7 @@ namespace nana
|
||||
{
|
||||
notifier_ = notifier;
|
||||
}
|
||||
|
||||
void create(window parent)
|
||||
{
|
||||
host_window_ = parent;
|
||||
@ -191,17 +250,14 @@ namespace nana
|
||||
caption_.create(*this, true);
|
||||
caption_.get_drawer_trigger().on_close([this]
|
||||
{
|
||||
bool destroy_dockarea = true;
|
||||
|
||||
if (tabbar_)
|
||||
{
|
||||
tabbar_->erase(tabbar_->selected());
|
||||
|
||||
destroy_dockarea = (0 == tabbar_->length());
|
||||
if (tabbar_->length())
|
||||
return;
|
||||
}
|
||||
|
||||
if (destroy_dockarea)
|
||||
notifier_->request_close();
|
||||
notifier_->request_close();
|
||||
});
|
||||
|
||||
this->events().resized.connect([this](const arg_resized& arg)
|
||||
@ -331,14 +387,11 @@ namespace nana
|
||||
private:
|
||||
widget* _m_add_pane(factory & fn)
|
||||
{
|
||||
rectangle r{ point(), this->size() };
|
||||
rectangle r{ this->size() };
|
||||
|
||||
//get a rectangle excluding caption
|
||||
r.y = 20;
|
||||
if (r.height > 20)
|
||||
r.height -= 20;
|
||||
else
|
||||
r.height = 0;
|
||||
r.height = differ(r.height, 20);
|
||||
|
||||
if (!tabbar_)
|
||||
{
|
||||
@ -426,7 +479,7 @@ namespace nana
|
||||
value_.integer = 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
void reset() noexcept
|
||||
{
|
||||
kind_ = kind::none;
|
||||
value_.integer = 0;
|
||||
@ -434,30 +487,21 @@ namespace nana
|
||||
|
||||
bool is_negative() const
|
||||
{
|
||||
switch (kind_)
|
||||
{
|
||||
case kind::integer:
|
||||
return (value_.integer < 0);
|
||||
case kind::real:
|
||||
case kind::percent:
|
||||
return (value_.real < 0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
return (((kind::integer == kind_) && (value_.integer < 0)) ||
|
||||
((kind::real == kind_ || kind::percent == kind_) && (value_.real < 0)));
|
||||
}
|
||||
|
||||
bool empty() const throw()
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return (kind::none == kind_);
|
||||
}
|
||||
|
||||
kind kind_of() const
|
||||
kind kind_of() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
double get_value(int ref_percent) const
|
||||
double get_value(int ref_percent) const noexcept
|
||||
{
|
||||
switch (kind_)
|
||||
{
|
||||
@ -473,33 +517,33 @@ namespace nana
|
||||
return 0;
|
||||
}
|
||||
|
||||
int integer() const
|
||||
int integer() const noexcept
|
||||
{
|
||||
if (kind::integer == kind_)
|
||||
return value_.integer;
|
||||
return static_cast<int>(value_.real);
|
||||
}
|
||||
|
||||
double real() const
|
||||
double real() const noexcept
|
||||
{
|
||||
if (kind::integer == kind_)
|
||||
return value_.integer;
|
||||
return value_.real;
|
||||
}
|
||||
|
||||
void assign(int i)
|
||||
void assign(int i) noexcept
|
||||
{
|
||||
kind_ = kind::integer;
|
||||
value_.integer = i;
|
||||
}
|
||||
|
||||
void assign(double d)
|
||||
void assign(double d) noexcept
|
||||
{
|
||||
kind_ = kind::real;
|
||||
value_.real = d;
|
||||
}
|
||||
|
||||
void assign_percent(double d)
|
||||
void assign_percent(double d) noexcept
|
||||
{
|
||||
kind_ = kind::percent;
|
||||
value_.real = d / 100;
|
||||
@ -533,14 +577,11 @@ namespace nana
|
||||
margins_.clear();
|
||||
}
|
||||
|
||||
void push(const number_t& v)
|
||||
void push(const number_t& v, bool reset = false)
|
||||
{
|
||||
margins_.emplace_back(v);
|
||||
}
|
||||
if (reset)
|
||||
clear();
|
||||
|
||||
void set_value(const number_t& v)
|
||||
{
|
||||
clear();
|
||||
margins_.emplace_back(v);
|
||||
}
|
||||
|
||||
@ -550,6 +591,45 @@ namespace nana
|
||||
margins_ = v;
|
||||
}
|
||||
|
||||
number_t get_edge(std::size_t edge) const
|
||||
{
|
||||
int il{ -1 }, ir{ -1 }, it{ -1 }, ib{ -1 }; //index of four corners in margin
|
||||
switch (margins_.size())
|
||||
{
|
||||
case 0: break;
|
||||
case 1: //top
|
||||
il = ir = it = ib = 0;
|
||||
break;
|
||||
case 2://top,bottom and left,right
|
||||
it = ib = 0;
|
||||
il = ir = 1;
|
||||
break;
|
||||
default:
|
||||
il = 3; //left
|
||||
case 3: //top, right, bottom
|
||||
it = 0;
|
||||
ir = 1;
|
||||
ib = 2;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
switch (edge)
|
||||
{
|
||||
case 0: //top
|
||||
pos = it; break;
|
||||
case 1: //right
|
||||
pos = ir; break;
|
||||
case 2: //bottom
|
||||
pos = ib; break;
|
||||
case 3: //left
|
||||
pos = il; break;
|
||||
default:
|
||||
return number_t{};
|
||||
}
|
||||
|
||||
return (-1 == pos ? number_t{} : margins_[pos]);
|
||||
}
|
||||
|
||||
nana::rectangle area(const ::nana::rectangle& field_area) const
|
||||
{
|
||||
if (margins_.empty())
|
||||
@ -559,12 +639,11 @@ namespace nana
|
||||
if (all_edges_)
|
||||
{
|
||||
auto px = static_cast<int>(margins_.back().get_value(static_cast<int>(r.width)));
|
||||
const auto dbl_px = static_cast<unsigned>(px << 1);
|
||||
r.x += px;
|
||||
r.width = (r.width < dbl_px ? 0 : r.width - dbl_px);
|
||||
r.width = differ(r.width, (static_cast<unsigned>(px) << 1));
|
||||
|
||||
r.y += px;
|
||||
r.height = (r.height < dbl_px ? 0 : r.height - dbl_px);
|
||||
r.height = differ(r.height, (static_cast<unsigned>(px) << 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -573,7 +652,7 @@ namespace nana
|
||||
{
|
||||
case 0: break;
|
||||
case 1: //top
|
||||
it = 0;
|
||||
il = ir = it = ib = 0;
|
||||
break;
|
||||
case 2://top,bottom and left,right
|
||||
it = ib = 0;
|
||||
@ -587,49 +666,44 @@ namespace nana
|
||||
ib = 2;
|
||||
}
|
||||
|
||||
typedef decltype(r.height) px_type;
|
||||
auto calc = [](px_type a, px_type b)
|
||||
{
|
||||
return (a > b ? a - b : 0);
|
||||
};
|
||||
using px_type = decltype(r.height);
|
||||
|
||||
if (0 == it) //top
|
||||
{
|
||||
auto px = static_cast<int>(margins_[it].get_value(static_cast<int>(field_area.height)));
|
||||
r.y += px;
|
||||
r.height = calc(r.height, static_cast<px_type>(px));
|
||||
r.height = differ(r.height, static_cast<px_type>(px));
|
||||
}
|
||||
|
||||
if (-1 != ib) //bottom
|
||||
{
|
||||
auto px = static_cast<int>(margins_[ib].get_value(static_cast<int>(field_area.height)));
|
||||
r.height = calc(r.height, static_cast<px_type>(px));
|
||||
r.height = differ(r.height, static_cast<px_type>(px));
|
||||
}
|
||||
|
||||
if (-1 != il) //left
|
||||
{
|
||||
auto px = static_cast<px_type>(margins_[il].get_value(static_cast<int>(field_area.width)));
|
||||
r.x += px;
|
||||
r.width = calc(r.width, static_cast<px_type>(px));
|
||||
r.width = differ(r.width, static_cast<px_type>(px));
|
||||
}
|
||||
|
||||
if (-1 != ir) //right
|
||||
{
|
||||
auto px = static_cast<int>(margins_[ir].get_value(static_cast<int>(field_area.width)));
|
||||
r.width = calc(r.width, static_cast<px_type>(px));
|
||||
r.width = differ(r.width, static_cast<px_type>(px));
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
bool all_edges_ = true;
|
||||
bool all_edges_{ true };
|
||||
std::vector<number_t> margins_;
|
||||
};//end class margin
|
||||
|
||||
class repeated_array
|
||||
{
|
||||
public:
|
||||
|
||||
//A workaround for VC2013, becuase it does not generated an implicit declared move-constructor as defaulted.
|
||||
repeated_array() = default;
|
||||
|
||||
@ -678,15 +752,10 @@ namespace nana
|
||||
|
||||
number_t at(std::size_t pos) const
|
||||
{
|
||||
if (values_.empty())
|
||||
return{};
|
||||
if (values_.size() && (repeated_ || pos < values_.size()))
|
||||
return values_[pos % values_.size()];
|
||||
|
||||
if (repeated_)
|
||||
pos %= values_.size();
|
||||
else if (pos >= values_.size())
|
||||
return{};
|
||||
|
||||
return values_[pos];
|
||||
return{};
|
||||
}
|
||||
private:
|
||||
bool repeated_ = false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nana GUI Programming Interface Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -155,6 +155,12 @@ namespace API
|
||||
}
|
||||
}
|
||||
|
||||
void effects_bground(std::initializer_list<window> wdgs, const effects::bground_factory_interface& factory, double fade_rate)
|
||||
{
|
||||
for (auto wd : wdgs)
|
||||
effects_bground(wd, factory, fade_rate);
|
||||
}
|
||||
|
||||
bground_mode effects_bground_mode(window wd)
|
||||
{
|
||||
auto const iwd = reinterpret_cast<basic_window*>(wd);
|
||||
@ -210,6 +216,14 @@ namespace API
|
||||
return (restrict::wd_manager().available(iwd) ? iwd->annex.scheme : nullptr);
|
||||
}
|
||||
|
||||
void set_measurer(window wd, ::nana::dev::widget_content_measurer_interface* measurer)
|
||||
{
|
||||
auto iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(iwd))
|
||||
iwd->annex.content_measurer = measurer;
|
||||
}
|
||||
|
||||
void attach_drawer(widget& wd, drawer_trigger& dr)
|
||||
{
|
||||
const auto iwd = reinterpret_cast<basic_window*>(wd.handle());
|
||||
@ -321,6 +335,32 @@ namespace API
|
||||
iwd->flags.space_click_enabled = enable;
|
||||
}
|
||||
|
||||
bool copy_transparent_background(window wd, paint::graphics& graph)
|
||||
{
|
||||
auto & buf = reinterpret_cast<basic_window*>(wd)->other.glass_buffer;
|
||||
internal_scope_guard lock;
|
||||
|
||||
if (bground_mode::basic != API::effects_bground_mode(wd))
|
||||
return false;
|
||||
|
||||
buf.paste(rectangle{ buf.size() }, graph, 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool copy_transparent_background(window wd, const rectangle& src_r, paint::graphics& graph, const point& dst_pt)
|
||||
{
|
||||
auto iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
|
||||
if (bground_mode::basic != API::effects_bground_mode(wd))
|
||||
return false;
|
||||
|
||||
iwd->other.glass_buffer.paste(src_r, graph, dst_pt.x, dst_pt.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lazy_refresh()
|
||||
{
|
||||
restrict::bedrock.thread_context_lazy_refresh();
|
||||
@ -340,74 +380,15 @@ namespace API
|
||||
//close all windows in current thread
|
||||
void exit()
|
||||
{
|
||||
std::vector<basic_window*> v;
|
||||
|
||||
internal_scope_guard lock;
|
||||
restrict::wd_manager().all_handles(v);
|
||||
if(v.size())
|
||||
{
|
||||
std::vector<native_window_type> roots;
|
||||
native_window_type root = nullptr;
|
||||
unsigned tid = nana::system::this_thread_id();
|
||||
for(auto wd : v)
|
||||
{
|
||||
if((wd->thread_id == tid) && (wd->root != root))
|
||||
{
|
||||
root = wd->root;
|
||||
bool exists = false;
|
||||
for (auto i = roots.cbegin(); i != roots.cend(); ++i)
|
||||
{
|
||||
if (*i == root)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
roots.emplace_back(root);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto i : roots)
|
||||
interface_type::close_window(i);
|
||||
}
|
||||
restrict::bedrock.close_thread_window(nana::system::this_thread_id());
|
||||
}
|
||||
|
||||
//close all windows
|
||||
void exit_all()
|
||||
{
|
||||
std::vector<basic_window*> v;
|
||||
|
||||
internal_scope_guard lock;
|
||||
restrict::wd_manager().all_handles(v);
|
||||
if (v.size())
|
||||
{
|
||||
std::vector<native_window_type> roots;
|
||||
native_window_type root = nullptr;
|
||||
//unsigned tid = nana::system::this_thread_id();
|
||||
for (auto wd : v)
|
||||
{
|
||||
if (/*(wd->thread_id == tid) &&*/ (wd->root != root))
|
||||
{
|
||||
root = wd->root;
|
||||
bool exists = false;
|
||||
for (auto i = roots.cbegin(); i != roots.cend(); ++i)
|
||||
{
|
||||
if (*i == root)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
roots.emplace_back(root);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i : roots)
|
||||
interface_type::close_window(i);
|
||||
}
|
||||
restrict::bedrock.close_thread_window(0);
|
||||
}
|
||||
|
||||
//transform_shortkey_text
|
||||
@ -480,12 +461,13 @@ namespace API
|
||||
|
||||
void window_icon_default(const paint::image& small_icon, const paint::image& big_icon)
|
||||
{
|
||||
restrict::wd_manager().default_icon(small_icon, big_icon);
|
||||
restrict::wd_manager().icon(nullptr, small_icon, big_icon);
|
||||
}
|
||||
|
||||
void window_icon(window wd, const paint::image& small_icon, const paint::image& big_icon)
|
||||
{
|
||||
restrict::wd_manager().icon(reinterpret_cast<basic_window*>(wd), small_icon, big_icon);
|
||||
if(nullptr != wd)
|
||||
restrict::wd_manager().icon(reinterpret_cast<basic_window*>(wd), small_icon, big_icon);
|
||||
}
|
||||
|
||||
bool empty_window(window wd)
|
||||
@ -520,6 +502,11 @@ namespace API
|
||||
}
|
||||
}
|
||||
|
||||
bool is_transparent_background(window wd)
|
||||
{
|
||||
return (bground_mode::basic == effects_bground_mode(wd));
|
||||
}
|
||||
|
||||
native_window_type root(window wd)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
@ -992,24 +979,22 @@ namespace API
|
||||
|
||||
void modal_window(window wd)
|
||||
{
|
||||
auto const iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard isg;
|
||||
|
||||
if (!restrict::wd_manager().available(iwd))
|
||||
return;
|
||||
|
||||
if ((iwd->other.category == category::flags::root) && (iwd->flags.modal == false))
|
||||
{
|
||||
auto const iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard isg;
|
||||
|
||||
if (!restrict::wd_manager().available(iwd))
|
||||
return;
|
||||
|
||||
if ((iwd->other.category == category::flags::root) && (iwd->flags.modal == false))
|
||||
{
|
||||
iwd->flags.modal = true;
|
||||
iwd->flags.modal = true;
|
||||
#if defined(NANA_X11)
|
||||
interface_type::set_modal(iwd->root);
|
||||
interface_type::set_modal(iwd->root);
|
||||
#endif
|
||||
restrict::wd_manager().show(iwd, true);
|
||||
}
|
||||
else
|
||||
return;
|
||||
restrict::wd_manager().show(iwd, true);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
//modal has to guarantee that does not lock the mutex of window_manager before invokeing the pump_event,
|
||||
//otherwise, the modal will prevent the other thread access the window.
|
||||
@ -1018,7 +1003,8 @@ namespace API
|
||||
|
||||
void wait_for(window wd)
|
||||
{
|
||||
if (wd)
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(reinterpret_cast<basic_window*>(wd)))
|
||||
restrict::bedrock.pump_event(wd, false);
|
||||
}
|
||||
|
||||
@ -1335,7 +1321,7 @@ namespace API
|
||||
::nana::point clipos{pos};
|
||||
interface_type::calc_window_point(wd, clipos);
|
||||
return reinterpret_cast<window>(
|
||||
restrict::wd_manager().find_window(wd, clipos.x, clipos.y));
|
||||
restrict::wd_manager().find_window(wd, clipos));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -1395,6 +1381,7 @@ namespace API
|
||||
switch(iwd->flags.action)
|
||||
{
|
||||
case nana::mouse_action::normal:
|
||||
case nana::mouse_action::normal_captured:
|
||||
return (is_focused ? nana::element_state::focus_normal : nana::element_state::normal);
|
||||
case nana::mouse_action::hovered:
|
||||
return (is_focused ? nana::element_state::focus_hovered : nana::element_state::hovered);
|
||||
@ -1432,5 +1419,29 @@ namespace API
|
||||
{
|
||||
restrict::wd_manager().set_safe_place(reinterpret_cast<basic_window*>(wd), std::move(fn));
|
||||
}
|
||||
|
||||
optional<std::pair<size, size>> content_extent(window wd, unsigned limited_px, bool limit_width)
|
||||
{
|
||||
auto iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
|
||||
if (restrict::wd_manager().available(iwd) && iwd->annex.content_measurer)
|
||||
{
|
||||
paint::graphics* graph = &iwd->drawer.graphics;
|
||||
paint::graphics temp_graph;
|
||||
if (graph->empty())
|
||||
{
|
||||
temp_graph.make({ 1, 1 });
|
||||
temp_graph.typeface(graph->typeface());
|
||||
graph = &temp_graph;
|
||||
}
|
||||
|
||||
auto extent = iwd->annex.content_measurer->measure(*graph, limited_px, limit_width);
|
||||
if (extent)
|
||||
return std::make_pair(extent.value(), extent.value() + iwd->annex.content_measurer->extension());
|
||||
}
|
||||
|
||||
return{};
|
||||
}
|
||||
}//end namespace API
|
||||
}//end namespace nana
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(NANA_LINUX) || defined(NANA_MACOS)
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../detail/platform_spec_selector.hpp"
|
||||
#include <nana/system/platform.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Tooltip Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -210,24 +210,7 @@ namespace nana
|
||||
_m_get(wd).second = str;
|
||||
}
|
||||
|
||||
void show(const std::string& text)
|
||||
{
|
||||
if (nullptr == window_ || window_->tooltip_empty())
|
||||
{
|
||||
auto fp = factory();
|
||||
|
||||
window_ = std::unique_ptr<tooltip_interface, deleter_type>(fp->create(), [fp](tooltip_interface* ti)
|
||||
{
|
||||
fp->destroy(ti);
|
||||
});
|
||||
}
|
||||
|
||||
window_->duration(0);
|
||||
window_->tooltip_text(text);
|
||||
window_->tooltip_move(API::cursor_position(), true);
|
||||
}
|
||||
|
||||
void show_duration(window /*wd*/, point pos, const std::string& text, std::size_t duration)
|
||||
void show(const std::string& text, const point* pos, std::size_t duration)
|
||||
{
|
||||
if (nullptr == window_ || window_->tooltip_empty())
|
||||
{
|
||||
@ -242,8 +225,10 @@ namespace nana
|
||||
window_->duration(duration);
|
||||
window_->tooltip_text(text);
|
||||
|
||||
pos = pos_by_screen(pos, window_->tooltip_size(), true);
|
||||
window_->tooltip_move(pos, false);
|
||||
if (pos)
|
||||
window_->tooltip_move(pos_by_screen(*pos, window_->tooltip_size(), true), false);
|
||||
else
|
||||
window_->tooltip_move(API::cursor_position(), true);
|
||||
}
|
||||
|
||||
void close()
|
||||
@ -289,7 +274,7 @@ namespace nana
|
||||
{
|
||||
auto & pr = _m_get(arg.window_handle);
|
||||
if (pr.second.size())
|
||||
this->show(pr.second);
|
||||
this->show(pr.second, nullptr, 0);
|
||||
}
|
||||
else
|
||||
this->close();
|
||||
@ -329,7 +314,7 @@ namespace nana
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
API::calc_screen_point(wd, pos);
|
||||
ctrl::instance()->show_duration(wd, pos, text, duration);
|
||||
ctrl::instance()->show(text, &pos, duration);
|
||||
}
|
||||
|
||||
void tooltip::close()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Button Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -11,12 +11,44 @@
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/button.hpp>
|
||||
#include <nana/gui/detail/widget_content_measurer_interface.hpp>
|
||||
|
||||
#include <nana/paint/text_renderer.hpp>
|
||||
|
||||
namespace nana{ namespace drawerbase
|
||||
{
|
||||
namespace button
|
||||
{
|
||||
class trigger::measurer
|
||||
: public dev::widget_content_measurer_interface
|
||||
{
|
||||
public:
|
||||
measurer(trigger* t)
|
||||
: trigger_{ t }
|
||||
{}
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override
|
||||
{
|
||||
//Button doesn't provide a support of vfit and hfit
|
||||
if (limit_pixels)
|
||||
return{};
|
||||
|
||||
wchar_t shortkey;
|
||||
std::string::size_type shortkey_pos;
|
||||
|
||||
auto str = to_wstring(API::transform_shortkey_text(trigger_->wdg_->caption(), shortkey, &shortkey_pos));
|
||||
auto text_sz = graph.text_extent_size(str);
|
||||
|
||||
return size{ text_sz.width, text_sz.height };
|
||||
}
|
||||
|
||||
size extension() const override
|
||||
{
|
||||
return { 14, 10};
|
||||
}
|
||||
private:
|
||||
trigger * trigger_;
|
||||
};
|
||||
|
||||
//trigger
|
||||
//@brief: draw the button
|
||||
@ -26,6 +58,8 @@ namespace nana{ namespace drawerbase
|
||||
attr_.omitted = attr_.focused = attr_.pushed = attr_.enable_pushed = attr_.keep_pressed = false;
|
||||
attr_.focus_color = true;
|
||||
attr_.icon = nullptr;
|
||||
|
||||
measurer_.reset(new measurer{this});
|
||||
}
|
||||
|
||||
trigger::~trigger()
|
||||
@ -44,6 +78,7 @@ namespace nana{ namespace drawerbase
|
||||
API::tabstop(wd);
|
||||
API::effects_edge_nimbus(wd, effects::edge_nimbus::active);
|
||||
API::effects_edge_nimbus(wd, effects::edge_nimbus::over);
|
||||
API::dev::set_measurer(widget, measurer_.get());
|
||||
}
|
||||
|
||||
bool trigger::enable_pushed(bool eb)
|
||||
@ -120,7 +155,7 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
if (false == cite_.draw(graph, attr_.bgcolor, attr_.fgcolor, ::nana::rectangle{ graph.size() }, e_state))
|
||||
{
|
||||
if (bground_mode::basic != API::effects_bground_mode(wdg_->handle()))
|
||||
if (!API::is_transparent_background(*wdg_))
|
||||
{
|
||||
_m_draw_background(graph);
|
||||
_m_draw_border(graph);
|
||||
@ -251,17 +286,17 @@ namespace nana{ namespace drawerbase
|
||||
}
|
||||
else
|
||||
{
|
||||
graph.palette(true, ::nana::color(colors::white));
|
||||
graph.palette(true, color{ colors::white });
|
||||
if(attr_.omitted)
|
||||
{
|
||||
tr.render(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen, omitted_pixels, true);
|
||||
graph.palette(true, ::nana::color(colors::gray));
|
||||
graph.palette(true, color{ colors::gray });
|
||||
tr.render(pos, txtptr, txtlen, omitted_pixels, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen);
|
||||
graph.palette(true, ::nana::color(colors::gray));
|
||||
graph.palette(true, color{ colors::gray });
|
||||
graph.bidi_string(pos, txtptr, txtlen);
|
||||
}
|
||||
}
|
||||
@ -276,8 +311,8 @@ namespace nana{ namespace drawerbase
|
||||
nana::rectangle r(graph.size());
|
||||
r.pare_off(1);
|
||||
|
||||
auto from = attr_.bgcolor.blend(colors::white, 0.2);
|
||||
auto to = attr_.bgcolor.blend(colors::black, 0.95);
|
||||
auto from = attr_.bgcolor.blend(colors::white, 0.8);
|
||||
auto to = attr_.bgcolor.blend(colors::black, 0.05);
|
||||
|
||||
if (element_state::pressed == attr_.e_state)
|
||||
{
|
||||
@ -457,7 +492,7 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
bool button::transparent() const
|
||||
{
|
||||
return (bground_mode::basic == API::effects_bground_mode(*this));
|
||||
return API::is_transparent_background(*this);
|
||||
}
|
||||
|
||||
button& button::edge_effects(bool enable)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Categorize Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -78,7 +78,7 @@ namespace nana
|
||||
|
||||
if(ue.what == ue.none || (API::window_enabled(wd) == false))
|
||||
{ //the mouse is out of the widget.
|
||||
style_.bgcolor = style_.bgcolor.blend(static_cast<color_rgb>(0xa0c9f5), 0.9);
|
||||
style_.bgcolor = style_.bgcolor.blend(static_cast<color_rgb>(0xa0c9f5), 0.1);
|
||||
}
|
||||
graph.rectangle(r, true, style_.bgcolor);
|
||||
}
|
||||
@ -343,7 +343,7 @@ namespace nana
|
||||
{
|
||||
if(tree_.get_root()->child)
|
||||
{
|
||||
tree_.clear();
|
||||
tree_.clear(tree_.get_root());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A CheckBox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -55,7 +55,7 @@ namespace nana{ namespace drawerbase
|
||||
auto wdg = impl_->widget_ptr;
|
||||
|
||||
//draw background
|
||||
if (bground_mode::basic != API::effects_bground_mode(*wdg))
|
||||
if (!API::dev::copy_transparent_background(*wdg, graph))
|
||||
graph.rectangle(true, wdg->bgcolor());
|
||||
|
||||
//draw title
|
||||
@ -193,7 +193,7 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
bool checkbox::transparent() const
|
||||
{
|
||||
return (bground_mode::basic == API::effects_bground_mode(*this));
|
||||
return API::is_transparent_background(*this);
|
||||
}
|
||||
//end class checkbox
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,8 +17,10 @@
|
||||
#include <nana/gui/widgets/float_listbox.hpp>
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/widgets/skeletons/textbase_export_interface.hpp>
|
||||
#include <nana/gui/detail/widget_content_measurer_interface.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -80,6 +82,40 @@ namespace nana
|
||||
|
||||
class drawer_impl
|
||||
{
|
||||
class content_measurer
|
||||
: public dev::widget_content_measurer_interface
|
||||
{
|
||||
public:
|
||||
content_measurer(drawer_impl* drwimpl)
|
||||
: drw_{ drwimpl }
|
||||
{}
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override
|
||||
{
|
||||
//Combox doesn't provide a support of vfit and hfit
|
||||
if (limit_pixels)
|
||||
return{};
|
||||
|
||||
size content_size;
|
||||
for (std::size_t i = 0; i < drw_->the_number_of_options(); ++i)
|
||||
{
|
||||
auto & m = drw_->at(i);
|
||||
auto sz = graph.text_extent_size(m.item_text);
|
||||
|
||||
content_size.width = (std::max)(content_size.width, sz.width);
|
||||
content_size.height = (std::max)(content_size.height, sz.height);
|
||||
}
|
||||
|
||||
return content_size;
|
||||
}
|
||||
|
||||
size extension() const override
|
||||
{
|
||||
return{ 19, 4 };
|
||||
}
|
||||
private:
|
||||
drawer_impl* const drw_;
|
||||
};
|
||||
public:
|
||||
using graph_reference = paint::graphics&;
|
||||
using widget_reference = widget&;
|
||||
@ -92,6 +128,8 @@ namespace nana
|
||||
state_.button_state = element_state::normal;
|
||||
state_.pointer_where = parts::none;
|
||||
state_.lister = nullptr;
|
||||
|
||||
measurer_.reset(new content_measurer{this});
|
||||
}
|
||||
|
||||
void renderer(drawerbase::float_listbox::item_renderer* ir)
|
||||
@ -111,6 +149,8 @@ namespace nana
|
||||
|
||||
evt_agent_.reset(new event_agent{ static_cast<nana::combox&>(wd) });
|
||||
editor_->textbase().set_event_agent(evt_agent_.get());
|
||||
|
||||
API::dev::set_measurer(wd, measurer_.get());
|
||||
}
|
||||
|
||||
void detached()
|
||||
@ -139,7 +179,9 @@ namespace nana
|
||||
|
||||
void text_area(const nana::size& s)
|
||||
{
|
||||
nana::rectangle r(2, 2, s.width > 19 ? s.width - 19 : 0, s.height > 4 ? s.height - 4 : 0);
|
||||
auto extension = measurer_->extension();
|
||||
|
||||
nana::rectangle r(2, 2, s.width > extension.width ? s.width - extension.width : 0, s.height > extension.height ? s.height - extension.height : 0);
|
||||
if(image_enabled_)
|
||||
{
|
||||
unsigned place = image_pixels_ + 2;
|
||||
@ -147,6 +189,7 @@ namespace nana
|
||||
if(r.width > place) r.width -= place;
|
||||
}
|
||||
editor_->text_area(r);
|
||||
editor_->render(state_.focused);
|
||||
}
|
||||
|
||||
widgets::skeletons::text_editor * editor() const
|
||||
@ -187,6 +230,14 @@ namespace nana
|
||||
}
|
||||
|
||||
graph.gradual_rectangle(::nana::rectangle(graph.size()).pare_off(pare_off_px), clr_from, clr_to, true);
|
||||
if (API::is_transparent_background(this->widget_ptr()->handle()))
|
||||
{
|
||||
paint::graphics trns_graph{ graph.size() };
|
||||
if (API::dev::copy_transparent_background(this->widget_ptr()->handle(), trns_graph))
|
||||
{
|
||||
graph.blend(rectangle{ trns_graph.size() }, trns_graph, {}, 0.5);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
@ -316,7 +367,6 @@ namespace nana
|
||||
if(editor_)
|
||||
{
|
||||
text_area(widget_->size());
|
||||
editor_->render(state_.focused);
|
||||
}
|
||||
_m_draw_push_button(enb);
|
||||
_m_draw_image();
|
||||
@ -351,7 +401,8 @@ namespace nana
|
||||
if (calc_where(*graph_, pos.x, pos.y))
|
||||
state_.button_state = element_state::normal;
|
||||
|
||||
editor_->text(::nana::charset(items_[index]->item_text, ::nana::unicode::utf8), false);
|
||||
editor_->text(to_wstring(items_[index]->item_text), false);
|
||||
editor_->try_refresh();
|
||||
_m_draw_push_button(widget_->enabled());
|
||||
_m_draw_image();
|
||||
|
||||
@ -465,9 +516,10 @@ namespace nana
|
||||
facade<element::button> button;
|
||||
button.draw(*graph_, ::nana::color{ 3, 65, 140 }, colors::white, r, estate);
|
||||
|
||||
facade<element::arrow> arrow("solid_triangle");
|
||||
facade<element::arrow> arrow;// ("solid_triangle");
|
||||
arrow.direction(::nana::direction::south);
|
||||
|
||||
r.x += 4;
|
||||
r.y += (r.height / 2) - 7;
|
||||
r.width = r.height = 16;
|
||||
arrow.draw(*graph_, {}, colors::white, r, element_state::normal);
|
||||
@ -528,6 +580,8 @@ namespace nana
|
||||
unsigned image_pixels_{ 16 };
|
||||
widgets::skeletons::text_editor * editor_{ nullptr };
|
||||
std::unique_ptr<event_agent> evt_agent_;
|
||||
|
||||
std::unique_ptr<content_measurer> measurer_;
|
||||
struct state_type
|
||||
{
|
||||
bool focused;
|
||||
@ -537,188 +591,192 @@ namespace nana
|
||||
nana::float_listbox * lister;
|
||||
std::size_t item_index_before_selection;
|
||||
}state_;
|
||||
};
|
||||
|
||||
|
||||
}; //end class drawer_impl
|
||||
|
||||
|
||||
//class trigger
|
||||
trigger::trigger()
|
||||
: drawer_(new drawer_impl)
|
||||
{}
|
||||
trigger::trigger() :
|
||||
drawer_(new drawer_impl)
|
||||
{
|
||||
}
|
||||
|
||||
trigger::~trigger()
|
||||
{
|
||||
delete drawer_;
|
||||
}
|
||||
trigger::~trigger()
|
||||
{
|
||||
delete drawer_;
|
||||
}
|
||||
|
||||
drawer_impl& trigger::get_drawer_impl()
|
||||
{
|
||||
return *drawer_;
|
||||
}
|
||||
drawer_impl& trigger::get_drawer_impl()
|
||||
{
|
||||
return *drawer_;
|
||||
}
|
||||
|
||||
const drawer_impl& trigger::get_drawer_impl() const
|
||||
{
|
||||
return *drawer_;
|
||||
}
|
||||
const drawer_impl& trigger::get_drawer_impl() const
|
||||
{
|
||||
return *drawer_;
|
||||
}
|
||||
|
||||
void trigger::attached(widget_reference wdg, graph_reference graph)
|
||||
{
|
||||
wdg.bgcolor(colors::white);
|
||||
drawer_->attached(wdg, graph);
|
||||
void trigger::attached(widget_reference wdg, graph_reference graph)
|
||||
{
|
||||
wdg.bgcolor(colors::white);
|
||||
drawer_->attached(wdg, graph);
|
||||
|
||||
API::effects_edge_nimbus(wdg, effects::edge_nimbus::active);
|
||||
API::effects_edge_nimbus(wdg, effects::edge_nimbus::over);
|
||||
}
|
||||
API::effects_edge_nimbus(wdg, effects::edge_nimbus::active);
|
||||
API::effects_edge_nimbus(wdg, effects::edge_nimbus::over);
|
||||
}
|
||||
|
||||
void trigger::detached()
|
||||
{
|
||||
drawer_->detached();
|
||||
}
|
||||
void trigger::detached()
|
||||
{
|
||||
drawer_->detached();
|
||||
}
|
||||
|
||||
void trigger::refresh(graph_reference)
|
||||
void trigger::refresh(graph_reference)
|
||||
{
|
||||
drawer_->draw();
|
||||
}
|
||||
|
||||
void trigger::focus(graph_reference, const arg_focus& arg)
|
||||
{
|
||||
drawer_->set_focused(arg.getting);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
drawer_->draw();
|
||||
drawer_->editor()->reset_caret();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::focus(graph_reference, const arg_focus& arg)
|
||||
void trigger::mouse_enter(graph_reference, const arg_mouse&)
|
||||
{
|
||||
drawer_->set_button_state(element_state::hovered, true);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
drawer_->set_focused(arg.getting);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
drawer_->draw();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_leave(graph_reference, const arg_mouse&)
|
||||
{
|
||||
drawer_->set_button_state(element_state::normal, true);
|
||||
drawer_->editor()->mouse_enter(false);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
drawer_->draw();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_down(graph_reference, const arg_mouse& arg)
|
||||
{
|
||||
drawer_->set_button_state(element_state::pressed, false);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
auto * editor = drawer_->editor();
|
||||
editor->mouse_pressed(arg);
|
||||
drawer_->open_lister_if_push_button_positioned();
|
||||
|
||||
drawer_->draw();
|
||||
if(editor->attr().editable)
|
||||
editor->reset_caret();
|
||||
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_up(graph_reference, const arg_mouse& arg)
|
||||
{
|
||||
if (drawer_->widget_ptr()->enabled() && !drawer_->has_lister())
|
||||
{
|
||||
drawer_->editor()->mouse_pressed(arg);
|
||||
drawer_->set_button_state(element_state::hovered, false);
|
||||
drawer_->draw();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
bool redraw = drawer_->calc_where(graph, arg.pos.x, arg.pos.y);
|
||||
redraw |= drawer_->editor()->mouse_move(arg.left_button, arg.pos);
|
||||
|
||||
if(redraw)
|
||||
{
|
||||
drawer_->draw();
|
||||
drawer_->editor()->reset_caret();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_enter(graph_reference, const arg_mouse&)
|
||||
void trigger::mouse_wheel(graph_reference, const arg_wheel& arg)
|
||||
{
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
drawer_->set_button_state(element_state::hovered, true);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
drawer_->draw();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_leave(graph_reference, const arg_mouse&)
|
||||
{
|
||||
drawer_->set_button_state(element_state::normal, true);
|
||||
drawer_->editor()->mouse_enter(false);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
drawer_->draw();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_down(graph_reference, const arg_mouse& arg)
|
||||
{
|
||||
//drawer_->set_mouse_press(true);
|
||||
drawer_->set_button_state(element_state::pressed, false);
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
auto * editor = drawer_->editor();
|
||||
editor->mouse_pressed(arg);
|
||||
drawer_->open_lister_if_push_button_positioned();
|
||||
|
||||
drawer_->draw();
|
||||
if(editor->attr().editable)
|
||||
editor->reset_caret();
|
||||
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_up(graph_reference, const arg_mouse& arg)
|
||||
{
|
||||
if (drawer_->widget_ptr()->enabled() && !drawer_->has_lister())
|
||||
{
|
||||
drawer_->editor()->mouse_pressed(arg);
|
||||
drawer_->set_button_state(element_state::hovered, false);
|
||||
drawer_->draw();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
bool redraw = drawer_->calc_where(graph, arg.pos.x, arg.pos.y);
|
||||
redraw |= drawer_->editor()->mouse_move(arg.left_button, arg.pos);
|
||||
|
||||
if(redraw)
|
||||
{
|
||||
drawer_->draw();
|
||||
drawer_->editor()->reset_caret();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::mouse_wheel(graph_reference, const arg_wheel& arg)
|
||||
{
|
||||
if(drawer_->widget_ptr()->enabled())
|
||||
{
|
||||
if(drawer_->has_lister())
|
||||
drawer_->scroll_items(arg.upwards);
|
||||
else
|
||||
drawer_->move_items(arg.upwards, false);
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::key_press(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if(!drawer_->widget_ptr()->enabled())
|
||||
return;
|
||||
|
||||
bool call_other_keys = false;
|
||||
if(drawer_->editable())
|
||||
{
|
||||
bool is_move_up = false;
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_left:
|
||||
case keyboard::os_arrow_right:
|
||||
drawer_->editor()->respond_key(arg);
|
||||
drawer_->editor()->reset_caret();
|
||||
break;
|
||||
case keyboard::os_arrow_up:
|
||||
is_move_up = true;
|
||||
case keyboard::os_arrow_down:
|
||||
drawer_->move_items(is_move_up, true);
|
||||
break;
|
||||
default:
|
||||
call_other_keys = true;
|
||||
}
|
||||
}
|
||||
if(drawer_->has_lister())
|
||||
drawer_->scroll_items(arg.upwards);
|
||||
else
|
||||
{
|
||||
bool is_move_up = false;
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_left:
|
||||
case keyboard::os_arrow_up:
|
||||
is_move_up = true;
|
||||
case keyboard::os_arrow_right:
|
||||
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);
|
||||
|
||||
API::dev::lazy_refresh();
|
||||
drawer_->move_items(arg.upwards, false);
|
||||
}
|
||||
}
|
||||
|
||||
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
||||
void trigger::key_press(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if(!drawer_->widget_ptr()->enabled())
|
||||
return;
|
||||
|
||||
bool call_other_keys = false;
|
||||
if(drawer_->editable())
|
||||
{
|
||||
if (drawer_->editor()->respond_char(arg))
|
||||
API::dev::lazy_refresh();
|
||||
bool is_move_up = false;
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_left:
|
||||
case keyboard::os_arrow_right:
|
||||
drawer_->editor()->respond_key(arg);
|
||||
drawer_->editor()->reset_caret();
|
||||
break;
|
||||
case keyboard::os_arrow_up:
|
||||
is_move_up = true;
|
||||
case keyboard::os_arrow_down:
|
||||
drawer_->move_items(is_move_up, true);
|
||||
break;
|
||||
default:
|
||||
call_other_keys = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool is_move_up = false;
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_left:
|
||||
case keyboard::os_arrow_up:
|
||||
is_move_up = true;
|
||||
case keyboard::os_arrow_right:
|
||||
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);
|
||||
|
||||
drawer_->editor()->try_refresh();
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
drawer_->editor()->respond_char(arg);
|
||||
if (drawer_->editor()->try_refresh())
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
//end class trigger
|
||||
|
||||
//class item_proxy
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A date chooser Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -93,7 +93,8 @@ namespace nana
|
||||
r.y = static_cast<int>(newbuf.height() - r.height) / 2;
|
||||
newbuf.stretch(nzbuf, r);
|
||||
|
||||
nzbuf.blend(::nana::rectangle{ nzbuf.size() }, dzbuf, nana::point(), fade * (count - i));
|
||||
dzbuf.blend(::nana::rectangle{ nzbuf.size() }, nzbuf, {}, 1 - fade * (count - i));
|
||||
|
||||
graph.bitblt(refpos.x, refpos.y, dzbuf);
|
||||
|
||||
API::update_window(window_handle);
|
||||
@ -121,7 +122,8 @@ namespace nana
|
||||
nzbuf.rectangle(true, colors::white);
|
||||
newbuf.stretch(nzbuf, r);
|
||||
|
||||
nzbuf.blend(::nana::rectangle{ nzbuf.size() }, dzbuf, nana::point(), fade * (count - i));
|
||||
dzbuf.blend(::nana::rectangle{ nzbuf.size() }, nzbuf, {}, 1.0 - fade * (count - i));
|
||||
|
||||
graph.bitblt(refpos.x, refpos.y, dzbuf);
|
||||
|
||||
API::update_window(window_handle);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A group widget implementation
|
||||
* Nana C++ Library(http://www.nanaro.org)
|
||||
* Copyright(C) 2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2015-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -12,6 +12,9 @@
|
||||
* @Author: Stefan Pfeifer(st-321), Ariel Vina-Rodriguez (qPCR4vir)
|
||||
*
|
||||
* @brief group is a widget used to visually group and layout other widgets.
|
||||
*
|
||||
* @contributor:
|
||||
* dankan1890(https://github.com/dankan1890)
|
||||
*/
|
||||
|
||||
|
||||
@ -36,6 +39,8 @@ namespace nana{
|
||||
unsigned gap{2};
|
||||
std::string usr_div_str;
|
||||
|
||||
nana::size caption_dimension;
|
||||
|
||||
std::vector<std::unique_ptr<checkbox>> options;
|
||||
radio_group * radio_logic{nullptr};
|
||||
|
||||
@ -60,22 +65,24 @@ namespace nana{
|
||||
|
||||
void update_div()
|
||||
{
|
||||
::nana::size sz = caption.measure(1000);
|
||||
caption_dimension = caption.measure(1000);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "vert margin=[0," << gap << "," << gap + 5 << "," << gap << "]"
|
||||
<< " <weight=" << sz.height << " <weight=5> <" << field_title << " weight=" << sz.width + 1 << "> >"
|
||||
<< "<<vert margin=5 " << field_options << ">";
|
||||
std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
|
||||
div += "<weight=" + std::to_string(caption_dimension.height) + " <weight=5><" + field_title + " weight=" + std::to_string(caption_dimension.width + 1) + ">>";
|
||||
div += "<<vert margin=5 " + std::string(field_options) + ">";
|
||||
|
||||
if (!usr_div_str.empty())
|
||||
ss << "<" << usr_div_str << ">>";
|
||||
div += "<" + usr_div_str + ">>";
|
||||
else
|
||||
ss << ">";
|
||||
div += ">";
|
||||
|
||||
place_content.div(ss.str().c_str());
|
||||
place_content.div(div.c_str());
|
||||
|
||||
if (options.empty())
|
||||
place_content.field_display(field_options, false);
|
||||
|
||||
if (caption.caption().empty())
|
||||
place_content.field_display(field_title, false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -202,25 +209,23 @@ namespace nana{
|
||||
outter.collocate();
|
||||
|
||||
color pbg = API::bgcolor(this->parent());
|
||||
impl_->caption.bgcolor(pbg.blend(colors::black, 0.975));
|
||||
color bg = pbg.blend(colors::black, 0.950);
|
||||
|
||||
bgcolor(bg);
|
||||
impl_->caption.bgcolor(pbg.blend(colors::black, 0.025));
|
||||
|
||||
this->bgcolor(pbg.blend(colors::black, 0.05));
|
||||
|
||||
drawing dw(*this);
|
||||
|
||||
::nana::size sz = impl_->caption.measure(1000);
|
||||
|
||||
// This drawing function is owner by the onwer of dw (the outer panel of the group widget), not by dw !!
|
||||
dw.draw([this, sz, bg, pbg](paint::graphics& graph)
|
||||
dw.draw([this](paint::graphics& graph)
|
||||
{
|
||||
auto gap_px = impl_->gap - 1;
|
||||
|
||||
graph.rectangle(true, pbg);
|
||||
graph.round_rectangle(rectangle(point(gap_px, sz.height / 2),
|
||||
nana::size(graph.width() - 2 * gap_px, graph.height() - sz.height / 2 - gap_px)
|
||||
graph.rectangle(true, API::bgcolor(this->parent()));
|
||||
graph.round_rectangle(rectangle(point(gap_px, impl_->caption_dimension.height / 2),
|
||||
nana::size(graph.width() - 2 * gap_px, graph.height() - impl_->caption_dimension.height / 2 - gap_px)
|
||||
),
|
||||
3, 3, colors::gray_border, true, bg);
|
||||
3, 3, colors::gray_border, true, this->bgcolor());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Label Control Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -13,8 +13,9 @@
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/label.hpp>
|
||||
#include <nana/unicode_bidi.hpp>
|
||||
#include <nana/gui/widgets/skeletons/text_token_stream.hpp>
|
||||
#include <nana/gui/detail/widget_content_measurer_interface.hpp>
|
||||
#include <nana/unicode_bidi.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
@ -80,14 +81,14 @@ namespace nana
|
||||
{
|
||||
traceable_.clear();
|
||||
|
||||
nana::paint::font ft = graph.typeface(); //used for restoring the font
|
||||
auto pre_font = graph.typeface(); //used for restoring the font
|
||||
|
||||
const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height;
|
||||
|
||||
font_ = ft;
|
||||
font_ = pre_font;
|
||||
fblock_ = nullptr;
|
||||
|
||||
_m_set_default(ft, fgcolor);
|
||||
_m_set_default(pre_font, fgcolor);
|
||||
|
||||
_m_measure(graph);
|
||||
|
||||
@ -116,10 +117,10 @@ namespace nana
|
||||
|
||||
if((tv != align_v::top) && extent_v_pixels < graph.height())
|
||||
{
|
||||
rs.pos.y = static_cast<int>(graph.height() - extent_v_pixels);
|
||||
|
||||
if(align_v::center == tv)
|
||||
rs.pos.y = static_cast<int>(graph.height() - extent_v_pixels) >> 1;
|
||||
else if(align_v::bottom == tv)
|
||||
rs.pos.y = static_cast<int>(graph.height() - extent_v_pixels);
|
||||
rs.pos.y >>= 1;
|
||||
}
|
||||
else
|
||||
rs.pos.y = 0;
|
||||
@ -145,10 +146,10 @@ namespace nana
|
||||
rs.pos.y += static_cast<int>(rs.pixels.back().pixels);
|
||||
}
|
||||
|
||||
graph.typeface(ft);
|
||||
graph.typeface(pre_font);
|
||||
}
|
||||
|
||||
bool find(int x, int y, std::wstring& target, std::wstring& url) const
|
||||
bool find(int x, int y, std::wstring& target, std::wstring& url) const noexcept
|
||||
{
|
||||
for (auto & t : traceable_)
|
||||
{
|
||||
@ -183,10 +184,10 @@ namespace nana
|
||||
rs.text_align = th;
|
||||
rs.text_align_v = tv;
|
||||
|
||||
for(auto i = dstream_.begin(), end = dstream_.end(); i != end; ++i)
|
||||
for(auto & line: dstream_)
|
||||
{
|
||||
rs.pixels.clear();
|
||||
unsigned w = _m_line_pixels(*i, def_line_pixels, rs);
|
||||
unsigned w = _m_line_pixels(line, def_line_pixels, rs);
|
||||
|
||||
if(limited && (w > limited))
|
||||
w = limited;
|
||||
@ -202,7 +203,7 @@ namespace nana
|
||||
}
|
||||
private:
|
||||
//Manage the fblock for a specified rectangle if it is a traceable fblock.
|
||||
void _m_inser_if_traceable(int x, int y, const nana::size& sz, widgets::skeletons::fblock* fbp)
|
||||
void _m_insert_if_traceable(int x, int y, const nana::size& sz, widgets::skeletons::fblock* fbp)
|
||||
{
|
||||
if(fbp->target.size() || fbp->url.size())
|
||||
{
|
||||
@ -224,7 +225,7 @@ namespace nana
|
||||
def_.fgcolor = fgcolor;
|
||||
}
|
||||
|
||||
const ::nana::color& _m_fgcolor(nana::widgets::skeletons::fblock* fp)
|
||||
const ::nana::color& _m_fgcolor(nana::widgets::skeletons::fblock* fp) noexcept
|
||||
{
|
||||
while(fp->fgcolor.invisible())
|
||||
{
|
||||
@ -235,9 +236,9 @@ namespace nana
|
||||
return fp->fgcolor;
|
||||
}
|
||||
|
||||
std::size_t _m_font_size(nana::widgets::skeletons::fblock* fp)
|
||||
double _m_font_size(nana::widgets::skeletons::fblock* fp) noexcept
|
||||
{
|
||||
while(fp->font_size == 0xFFFFFFFF)
|
||||
while(fp->font_size < 0)
|
||||
{
|
||||
fp = fp->parent;
|
||||
if(nullptr == fp)
|
||||
@ -246,7 +247,7 @@ namespace nana
|
||||
return fp->font_size;
|
||||
}
|
||||
|
||||
bool _m_bold(nana::widgets::skeletons::fblock* fp)
|
||||
bool _m_bold(nana::widgets::skeletons::fblock* fp) noexcept
|
||||
{
|
||||
while(fp->bold_empty)
|
||||
{
|
||||
@ -257,7 +258,7 @@ namespace nana
|
||||
return fp->bold;
|
||||
}
|
||||
|
||||
const std::string& _m_fontname(nana::widgets::skeletons::fblock* fp)
|
||||
const std::string& _m_fontname(nana::widgets::skeletons::fblock* fp) noexcept
|
||||
{
|
||||
while(fp->font.empty())
|
||||
{
|
||||
@ -273,12 +274,14 @@ namespace nana
|
||||
if(fp != fblock_)
|
||||
{
|
||||
auto& name = _m_fontname(fp);
|
||||
auto fontsize = static_cast<unsigned>(_m_font_size(fp));
|
||||
auto fontsize = _m_font_size(fp);
|
||||
bool bold = _m_bold(fp);
|
||||
|
||||
if((fontsize != font_.size()) || bold != font_.bold() || name != font_.name())
|
||||
{
|
||||
font_.make(name, fontsize, bold);
|
||||
paint::font::font_style fs;
|
||||
fs.weight = (bold ? 800 : 400);
|
||||
font_ = paint::font{ name, fontsize, fs };
|
||||
graph.typeface(font_);
|
||||
}
|
||||
fblock_ = fp;
|
||||
@ -304,7 +307,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
void _m_align_x_base(const render_status& rs, pixel_tag & px, unsigned w)
|
||||
void _m_align_x_base(const render_status& rs, pixel_tag & px, unsigned w) noexcept
|
||||
{
|
||||
switch(rs.text_align)
|
||||
{
|
||||
@ -344,7 +347,7 @@ namespace nana
|
||||
|
||||
std::vector<iterator> line_values;
|
||||
|
||||
for(auto i = line.begin(), end = line.end(); i != end; ++i)
|
||||
for(auto i = line.begin(); i != line.end(); ++i)
|
||||
{
|
||||
data * data_ptr = i->data_ptr;
|
||||
nana::size sz = data_ptr->size();
|
||||
@ -365,7 +368,8 @@ namespace nana
|
||||
sz.height = max_ascent + max_descent;
|
||||
}
|
||||
|
||||
if(w + sz.width <= rs.allowed_width)
|
||||
//Check if the content is displayed in a new line.
|
||||
if((0 == rs.allowed_width) || (w + sz.width <= rs.allowed_width))
|
||||
{
|
||||
w += sz.width;
|
||||
|
||||
@ -376,12 +380,11 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_tag px;
|
||||
_m_align_x_base(rs, px, (w ? w : sz.width));
|
||||
|
||||
if(w)
|
||||
{
|
||||
pixel_tag px;
|
||||
|
||||
_m_align_x_base(rs, px, w);
|
||||
|
||||
if(max_ascent + max_descent > max_px)
|
||||
max_px = max_descent + max_ascent;
|
||||
else
|
||||
@ -391,8 +394,6 @@ namespace nana
|
||||
px.baseline = max_ascent;
|
||||
px.values.swap(line_values);
|
||||
|
||||
rs.pixels.emplace_back(px);
|
||||
|
||||
w = sz.width;
|
||||
max_px = sz.height;
|
||||
max_ascent = as;
|
||||
@ -401,18 +402,16 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_tag px;
|
||||
|
||||
_m_align_x_base(rs, px, sz.width);
|
||||
px.pixels = sz.height;
|
||||
px.baseline = as;
|
||||
|
||||
px.values.emplace_back(i);
|
||||
|
||||
rs.pixels.emplace_back(px);
|
||||
max_px = 0;
|
||||
max_ascent = max_descent = 0;
|
||||
}
|
||||
|
||||
rs.pixels.emplace_back(px);
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,49 +441,48 @@ namespace nana
|
||||
|
||||
const int lastpos = static_cast<int>(graph.height()) - 1;
|
||||
|
||||
for(auto i = rs.pixels.begin(), end = rs.pixels.end(); i != end; ++i)
|
||||
for(auto & px : rs.pixels)
|
||||
{
|
||||
for (auto & render_iterator : i->values)
|
||||
for(auto & render_iterator: px.values)
|
||||
{
|
||||
auto & value = *render_iterator;
|
||||
if(false == value.data_ptr->is_text())
|
||||
{
|
||||
if(text.size())
|
||||
{
|
||||
_m_draw_block(graph, text, block_start, rs);
|
||||
if(lastpos <= rs.pos.y)
|
||||
return false;
|
||||
text.clear();
|
||||
}
|
||||
nana::size sz = value.data_ptr->size();
|
||||
|
||||
pixel_tag px = rs.pixels[rs.index];
|
||||
if ((rs.allowed_width < rs.pos.x + sz.width) && (rs.pos.x != px.x_base))
|
||||
{
|
||||
//Change a line.
|
||||
rs.pos.y += static_cast<int>(px.pixels);
|
||||
px = rs.pixels[++rs.index];
|
||||
rs.pos.x = px.x_base;
|
||||
}
|
||||
|
||||
int y = rs.pos.y + _m_text_top(px, value.fblock_ptr, value.data_ptr);
|
||||
|
||||
value.data_ptr->nontext_render(graph, rs.pos.x, y);
|
||||
_m_inser_if_traceable(rs.pos.x, y, sz, value.fblock_ptr);
|
||||
rs.pos.x += static_cast<int>(sz.width);
|
||||
|
||||
if(lastpos < y)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (value.data_ptr->is_text())
|
||||
{
|
||||
//hold the block while the text is empty,
|
||||
//it stands for the first block
|
||||
if(text.empty())
|
||||
if (text.empty())
|
||||
block_start = render_iterator;
|
||||
|
||||
text += value.data_ptr->text();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(text.size())
|
||||
{
|
||||
_m_draw_block(graph, text, block_start, rs);
|
||||
if(lastpos <= rs.pos.y)
|
||||
return false;
|
||||
text.clear();
|
||||
}
|
||||
nana::size sz = value.data_ptr->size();
|
||||
|
||||
pixel_tag px = rs.pixels[rs.index];
|
||||
if ((rs.allowed_width < rs.pos.x + sz.width) && (rs.pos.x != px.x_base))
|
||||
{
|
||||
//Change a line.
|
||||
rs.pos.y += static_cast<int>(px.pixels);
|
||||
px = rs.pixels[++rs.index];
|
||||
rs.pos.x = px.x_base;
|
||||
}
|
||||
|
||||
int y = rs.pos.y + _m_text_top(px, value.fblock_ptr, value.data_ptr);
|
||||
|
||||
value.data_ptr->nontext_render(graph, rs.pos.x, y);
|
||||
_m_insert_if_traceable(rs.pos.x, y, sz, value.fblock_ptr);
|
||||
rs.pos.x += static_cast<int>(sz.width);
|
||||
|
||||
if(lastpos < y)
|
||||
return false;
|
||||
}
|
||||
|
||||
if(text.size())
|
||||
@ -496,7 +494,7 @@ namespace nana
|
||||
return (rs.pos.y <= lastpos);
|
||||
}
|
||||
|
||||
static bool _m_overline(const render_status& rs, int right, bool equal_required)
|
||||
static bool _m_overline(const render_status& rs, int right, bool equal_required) noexcept
|
||||
{
|
||||
if(align::left == rs.text_align)
|
||||
return (equal_required ? right >= static_cast<int>(rs.allowed_width) : right > static_cast<int>(rs.allowed_width));
|
||||
@ -567,10 +565,13 @@ namespace nana
|
||||
else
|
||||
{
|
||||
auto str = data_ptr->text().substr(text_range.first, text_range.second);
|
||||
graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr));
|
||||
sz = graph.text_extent_size(str);
|
||||
|
||||
graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr));
|
||||
}
|
||||
_m_inser_if_traceable(rs.pos.x, y, sz, fblock_ptr);
|
||||
|
||||
|
||||
_m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr);
|
||||
rs.pos.x += static_cast<int>(sz.width);
|
||||
|
||||
if(text_range.second < len)
|
||||
@ -584,7 +585,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos)
|
||||
static std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos)
|
||||
{
|
||||
std::size_t n = i->data_ptr->text().length();
|
||||
while(pos >= n)
|
||||
@ -599,13 +600,13 @@ namespace nana
|
||||
dstream dstream_;
|
||||
bool format_enabled_ = false;
|
||||
::nana::widgets::skeletons::fblock * fblock_ = nullptr;
|
||||
std::deque<traceable> traceable_;
|
||||
::std::deque<traceable> traceable_;
|
||||
|
||||
::nana::paint::font font_;
|
||||
struct def_font_tag
|
||||
{
|
||||
::std::string font_name;
|
||||
std::size_t font_size;
|
||||
double font_size;
|
||||
bool font_bold;
|
||||
::nana::color fgcolor;
|
||||
}def_;
|
||||
@ -613,13 +614,16 @@ namespace nana
|
||||
|
||||
//class trigger
|
||||
//@brief: Draw the label
|
||||
struct trigger::impl_t
|
||||
struct trigger::implement
|
||||
{
|
||||
class measurer;
|
||||
|
||||
widget * wd{nullptr};
|
||||
paint::graphics * graph{nullptr};
|
||||
std::unique_ptr<measurer> msr_ptr{ nullptr };
|
||||
|
||||
align text_align{align::left};
|
||||
align_v text_align_v;
|
||||
align_v text_align_v{align_v::top};
|
||||
|
||||
class renderer renderer;
|
||||
|
||||
@ -643,16 +647,44 @@ namespace nana
|
||||
std::vector<std::function<void(command, const std::string&)>> listener_;
|
||||
};
|
||||
|
||||
class trigger::implement::measurer
|
||||
: public dev::widget_content_measurer_interface
|
||||
{
|
||||
public:
|
||||
measurer(implement* impl)
|
||||
: impl_{ impl }
|
||||
{}
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override
|
||||
{
|
||||
//Label now doesn't support to measure content with a specified height.
|
||||
if (graph && ((0 == limit_pixels) || limit_width))
|
||||
{
|
||||
return impl_->renderer.measure(graph, limit_pixels, impl_->text_align, impl_->text_align_v);
|
||||
}
|
||||
return{};
|
||||
}
|
||||
|
||||
size extension() const override
|
||||
{
|
||||
return{ 2, 2 };
|
||||
}
|
||||
private:
|
||||
implement * const impl_;
|
||||
};
|
||||
|
||||
trigger::trigger()
|
||||
:impl_(new impl_t)
|
||||
{}
|
||||
:impl_(new implement)
|
||||
{
|
||||
impl_->msr_ptr.reset(new trigger::implement::measurer{impl_});
|
||||
}
|
||||
|
||||
trigger::~trigger()
|
||||
{
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
trigger::impl_t * trigger::impl() const
|
||||
trigger::implement * trigger::impl() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
@ -661,6 +693,7 @@ namespace nana
|
||||
{
|
||||
impl_->graph = &graph;
|
||||
impl_->wd = &widget;
|
||||
API::dev::set_measurer(widget, impl_->msr_ptr.get());
|
||||
}
|
||||
|
||||
void trigger::mouse_move(graph_reference, const arg_mouse& arg)
|
||||
@ -750,7 +783,7 @@ namespace nana
|
||||
if(nullptr == impl_->wd) return;
|
||||
|
||||
window wd = impl_->wd->handle();
|
||||
if(bground_mode::basic != API::effects_bground_mode(wd))
|
||||
if (!API::dev::copy_transparent_background(wd, graph))
|
||||
graph.rectangle(true, API::bgcolor(wd));
|
||||
|
||||
impl_->renderer.render(graph, API::fgcolor(wd), impl_->text_align, impl_->text_align_v);
|
||||
@ -796,7 +829,7 @@ namespace nana
|
||||
|
||||
bool label::transparent() const throw()
|
||||
{
|
||||
return (bground_mode::basic == API::effects_bground_mode(*this));
|
||||
return API::is_transparent_background(*this);
|
||||
}
|
||||
|
||||
label& label::format(bool f)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user