Merge remote-tracking branch 'Jinhao/develop' into develop

This commit is contained in:
qPCR4vir 2019-07-30 10:22:38 +02:00
commit 0562136c19
59 changed files with 2588 additions and 1942 deletions

28
build/vc2019/nana.sln Normal file
View 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

316
build/vc2019/nana.vcxproj Normal file
View File

@ -0,0 +1,316 @@
<?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>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</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>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>../bin/</OutDir>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>../bin/</OutDir>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</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>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</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>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</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>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</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\animation.cpp" />
<ClCompile Include="..\..\source\gui\basis.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\dragdrop.cpp" />
<ClCompile Include="..\..\source\gui\dragger.cpp" />
<ClCompile Include="..\..\source\gui\drawing.cpp" />
<ClCompile Include="..\..\source\gui\effects.cpp" />
<ClCompile Include="..\..\source\gui\element.cpp" />
<ClCompile Include="..\..\source\gui\filebox.cpp" />
<ClCompile Include="..\..\source\gui\layout_utility.cpp" />
<ClCompile Include="..\..\source\gui\msgbox.cpp" />
<ClCompile Include="..\..\source\gui\notifier.cpp" />
<ClCompile Include="..\..\source\gui\place.cpp" />
<ClCompile Include="..\..\source\gui\programming_interface.cpp" />
<ClCompile Include="..\..\source\gui\screen.cpp" />
<ClCompile Include="..\..\source\gui\state_cursor.cpp" />
<ClCompile Include="..\..\source\gui\timer.cpp" />
<ClCompile Include="..\..\source\gui\tooltip.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\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\gui\wvl.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>
<ItemGroup>
<ClInclude Include="..\..\include\nana\any.hpp" />
<ClInclude Include="..\..\include\nana\basic_types.hpp" />
<ClInclude Include="..\..\include\nana\c++defines.hpp" />
<ClInclude Include="..\..\include\nana\charset.hpp" />
<ClInclude Include="..\..\include\nana\concepts.hpp" />
<ClInclude Include="..\..\include\nana\config.hpp" />
<ClInclude Include="..\..\include\nana\datetime.hpp" />
<ClInclude Include="..\..\include\nana\deploy.hpp" />
<ClInclude Include="..\..\include\nana\fwd.hpp" />
<ClInclude Include="..\..\include\nana\gui.hpp" />
<ClInclude Include="..\..\include\nana\gui\animation.hpp" />
<ClInclude Include="..\..\include\nana\gui\basis.hpp" />
<ClInclude Include="..\..\include\nana\gui\dragdrop.hpp" />
<ClInclude Include="..\..\include\nana\gui\dragger.hpp" />
<ClInclude Include="..\..\include\nana\gui\drawing.hpp" />
<ClInclude Include="..\..\include\nana\gui\effects.hpp" />
<ClInclude Include="..\..\include\nana\gui\element.hpp" />
<ClInclude Include="..\..\include\nana\gui\filebox.hpp" />
<ClInclude Include="..\..\include\nana\gui\layout_utility.hpp" />
<ClInclude Include="..\..\include\nana\gui\msgbox.hpp" />
<ClInclude Include="..\..\include\nana\gui\notifier.hpp" />
<ClInclude Include="..\..\include\nana\gui\place.hpp" />
<ClInclude Include="..\..\include\nana\gui\programming_interface.hpp" />
<ClInclude Include="..\..\include\nana\gui\screen.hpp" />
<ClInclude Include="..\..\include\nana\gui\state_cursor.hpp" />
<ClInclude Include="..\..\include\nana\gui\timer.hpp" />
<ClInclude Include="..\..\include\nana\gui\tooltip.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\button.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\categorize.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\checkbox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\combox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\date_chooser.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\float_listbox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\form.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\group.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\label.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\listbox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\menu.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\menubar.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\panel.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\picture.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\progress.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\scroll.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\slider.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\spinbox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\tabbar.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\textbox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\toolbar.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\treebox.hpp" />
<ClInclude Include="..\..\include\nana\gui\widgets\widget.hpp" />
<ClInclude Include="..\..\include\nana\gui\wvl.hpp" />
<ClInclude Include="..\..\include\nana\internationalization.hpp" />
<ClInclude Include="..\..\include\nana\key_type.hpp" />
<ClInclude Include="..\..\include\nana\optional.hpp" />
<ClInclude Include="..\..\include\nana\stdc++.hpp" />
<ClInclude Include="..\..\include\nana\std_condition_variable.hpp" />
<ClInclude Include="..\..\include\nana\std_mutex.hpp" />
<ClInclude Include="..\..\include\nana\std_thread.hpp" />
<ClInclude Include="..\..\include\nana\traits.hpp" />
<ClInclude Include="..\..\include\nana\unicode_bidi.hpp" />
<ClInclude Include="..\..\include\nana\verbose_preprocessor.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\include\nana\pop_ignore_diagnostic" />
<None Include="..\..\include\nana\push_ignore_diagnostic" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,489 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Sources\audio">
<UniqueIdentifier>{81850bad-7436-405a-beb5-357c5e34f039}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\audio\detail">
<UniqueIdentifier>{44582b36-4575-4663-ac02-e80417f95d05}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\detail">
<UniqueIdentifier>{b7e3cdb7-99ac-473d-86c8-53dddce70480}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\filesystem">
<UniqueIdentifier>{02fa693c-edc1-4e04-bf1d-ec3c2a89182a}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\gui">
<UniqueIdentifier>{cffe7506-b96c-42aa-a747-41b5115d9580}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\gui\detail">
<UniqueIdentifier>{b6b2c032-c6a4-4884-8c14-eca4aa69ef0c}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\gui\widgets">
<UniqueIdentifier>{58f2e0f8-4d63-40db-807d-d7adf71c4ebe}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\gui\widgets\skeletons">
<UniqueIdentifier>{f288a25d-3ce8-4c2e-a86f-9aeda44bc557}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\paint">
<UniqueIdentifier>{90b2da01-605d-489b-b6c5-2af8d3c2d8a6}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\paint\detail">
<UniqueIdentifier>{430feed0-e1d9-45cb-8d59-e1a48a04d19f}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\system">
<UniqueIdentifier>{dcf62634-a658-453b-a58d-f1a96a12a8b8}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\threads">
<UniqueIdentifier>{c1cdf46a-519f-422a-947f-39e173045414}</UniqueIdentifier>
</Filter>
<Filter Include="Include">
<UniqueIdentifier>{d68bd89c-170f-445f-b79f-aa03c881ab6b}</UniqueIdentifier>
</Filter>
<Filter Include="Include\gui">
<UniqueIdentifier>{a5d87649-2cd1-4a8f-a1f9-7151eaf6c772}</UniqueIdentifier>
</Filter>
<Filter Include="Include\gui\widgets">
<UniqueIdentifier>{0e6a58ab-652c-45d7-b9aa-8d9f2fa80ea1}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\source\any.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\basic_types.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\charset.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\datetime.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\deploy.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\internationalization.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\stdc++.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\unicode_bidi.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\detail\audio_device.cpp">
<Filter>Sources\audio\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\detail\audio_stream.cpp">
<Filter>Sources\audio\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\detail\buffer_preparation.cpp">
<Filter>Sources\audio\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\player.cpp">
<Filter>Sources\audio</Filter>
</ClCompile>
<ClCompile Include="..\..\source\detail\platform_spec_windows.cpp">
<Filter>Sources\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\filesystem\filesystem.cpp">
<Filter>Sources\filesystem</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\basic_window.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\bedrock_pi.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\bedrock_windows.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\color_schemes.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\drawer.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\element_store.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\events_operation.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp">
<Filter>Sources\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp">
<Filter>Sources\gui\widgets\skeletons</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp">
<Filter>Sources\gui\widgets\skeletons</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\button.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\categorize.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\checkbox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\combox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\form.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\label.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\menu.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\menubar.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\panel.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\picture.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\progress.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\slider.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\tabbar.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\textbox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\toolbar.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\treebox.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\widget.cpp">
<Filter>Sources\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\detail\image_process_provider.cpp">
<Filter>Sources\paint\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\detail\native_paint_interface.cpp">
<Filter>Sources\paint\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\graphics.cpp">
<Filter>Sources\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\image.cpp">
<Filter>Sources\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\image_process_selector.cpp">
<Filter>Sources\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\pixel_buffer.cpp">
<Filter>Sources\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\text_renderer.cpp">
<Filter>Sources\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\dataexch.cpp">
<Filter>Sources\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\platform.cpp">
<Filter>Sources\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\shared_wrapper.cpp">
<Filter>Sources\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\timepiece.cpp">
<Filter>Sources\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\threads\pool.cpp">
<Filter>Sources\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp">
<Filter>Sources\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\animation.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\basis.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\dragger.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\drawing.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\effects.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\element.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\filebox.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\layout_utility.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\msgbox.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\notifier.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\place.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\programming_interface.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\screen.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\state_cursor.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\timer.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\tooltip.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\wvl.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\dragdrop.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\nana\gui\widgets\spinbox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\group.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\treebox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\listbox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\menu.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\menubar.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\progress.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\widget.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\textbox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\toolbar.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\button.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\combox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\label.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\panel.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\picture.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\tabbar.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\categorize.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\scroll.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\slider.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\checkbox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\date_chooser.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\float_listbox.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\widgets\form.hpp">
<Filter>Include\gui\widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\animation.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\basis.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\dragger.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\drawing.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\effects.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\element.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\filebox.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\layout_utility.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\msgbox.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\notifier.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\place.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\programming_interface.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\screen.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\state_cursor.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\timer.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\tooltip.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\wvl.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\any.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\basic_types.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\c++defines.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\charset.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\concepts.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\config.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\datetime.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\deploy.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\fwd.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\internationalization.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\key_type.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\optional.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\std_condition_variable.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\std_mutex.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\std_thread.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\stdc++.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\traits.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\unicode_bidi.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\verbose_preprocessor.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\dragdrop.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\include\nana\pop_ignore_diagnostic">
<Filter>Include</Filter>
</None>
<None Include="..\..\include\nana\push_ignore_diagnostic">
<Filter>Include</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -118,7 +118,5 @@ namespace nana
} }
} }
#define NANA_RGB(a) (((DWORD)(a) & 0xFF)<<16) | ((DWORD)(a) & 0xFF00) | (((DWORD)(a) & 0xFF0000) >> 16 )
#include <nana/pop_ignore_diagnostic> #include <nana/pop_ignore_diagnostic>
#endif //NANA_DEPLOY_HPP #endif //NANA_DEPLOY_HPP

View File

@ -1 +1,54 @@
#include "gui/wvl.hpp" /**
* Nana GUI Header
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2019 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.hpp
* @description
* the header file contains the files required for running of Nana.GUI
*/
#ifndef NANA_GUI_HPP
#define NANA_GUI_HPP
#include "gui/compact.hpp"
#include "gui/screen.hpp"
#include "gui/widgets/form.hpp"
#include "gui/drawing.hpp"
#include "gui/msgbox.hpp"
#include "gui/place.hpp"
namespace nana
{
#ifdef NANA_AUTOMATIC_GUI_TESTING
/// @brief Take control of the GUI and optionally automatically tests it.
///
/// @detail It transfers to nana the program flow control, which begin pumping messages
/// from the underlying OS, interpreting and sending it with suitable arguments
/// to the nana widgets that registered a response in the corresponding event.
/// It also accept arguments to be used in case of automatic GUI testing.
/// Other Way the arguments are ignored.
void exec(
unsigned wait = 1, ///< for the GUI to be constructed, in seconds
unsigned wait_end = 1, ///< for the GUI to be destructed, in seconds
std::function<void()> = {} ///< emit events to mimics user actions and may assert results
);
/// send a click message to this widget - useful in GUI testing
void click(widget& w);
/// in seconds
void Wait(unsigned wait = 0);
#else
void exec();
#endif
}//end namespace nana
#endif

View File

@ -24,10 +24,11 @@ namespace nana
{ {
namespace detail namespace detail
{ {
struct native_window_handle_impl{}; struct basic_window;
struct window_handle_impl{};
struct event_handle_impl{}; struct native_window_handle_impl;
struct native_drawable_impl{}; struct native_drawable_impl;
struct event_handle_impl;
} }
struct accel_key struct accel_key
@ -87,10 +88,11 @@ namespace nana
struct root_tag : public widget_tag{ static const flags value = flags::root; }; struct root_tag : public widget_tag{ static const flags value = flags::root; };
}// end namespace category }// end namespace category
using native_window_type = detail::native_window_handle_impl*; using window = detail::basic_window*; ///< The window handle type representing nana window objects
using window = detail::window_handle_impl*; ///< \see [What is window class ](https://sourceforge.net/p/nanapro/discussion/general/thread/bd0fabfb/) using native_window_type = detail::native_window_handle_impl*; ///< The native window handle type representing system native windows. E.g, HWND in windows, Window in X11
using event_handle = detail::event_handle_impl*;
using native_drawable_type = detail::native_drawable_impl*; using event_handle = detail::event_handle_impl*; ///< The event handle type representing nana window events
using native_drawable_type = detail::native_drawable_impl*; ///< The drawable handle type representing system native drawable objects. E.g. HDC in windows, Drawable in X11
struct keyboard struct keyboard

View File

@ -0,0 +1,57 @@
/**
* Nana GUI Library Definition
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2019 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/compact.hpp
* @description
* the header file contains the files required for running of Nana.GUI
*/
#ifndef NANA_GUI_WVL_HPP
#define NANA_GUI_WVL_HPP
#include "programming_interface.hpp"
namespace nana
{
namespace detail
{
struct form_loader_private
{
template<typename, bool> friend class form_loader;
private:
static void insert_form(::nana::widget*);
};
template<typename Form, bool IsVisible>
class form_loader
{
public:
template<typename... Args>
Form & operator()(Args &&... args) const
{
auto p = new Form(std::forward<Args>(args)...);
if (p->empty())
throw std::runtime_error("form_loader failed to create the form");
detail::form_loader_private::insert_form(p);
if (IsVisible)
p->show();
return *p;
}
};
}
template<typename Form, bool IsVisible = true>
using form_loader = detail::form_loader<Form, IsVisible>;
}//end namespace nana
#endif

View File

@ -37,8 +37,6 @@ namespace detail
bedrock(const bedrock&) = delete; bedrock(const bedrock&) = delete;
bedrock& operator=(const bedrock&) = delete; bedrock& operator=(const bedrock&) = delete;
public: public:
using core_window_t = basic_window;
struct thread_context; struct thread_context;
class flag_guard; class flag_guard;
@ -59,16 +57,16 @@ namespace detail
~bedrock(); ~bedrock();
void pump_event(window, bool is_modal); void pump_event(window, bool is_modal);
void flush_surface(core_window_t*, bool forced, const rectangle* update_area = nullptr); void flush_surface(basic_window*, bool forced, const rectangle* update_area = nullptr);
static int inc_window(thread_t tid = 0); static int inc_window(thread_t tid = 0);
thread_context* open_thread_context(thread_t tid = 0); thread_context* open_thread_context(thread_t tid = 0);
thread_context* get_thread_context(thread_t tid = 0); thread_context* get_thread_context(thread_t tid = 0);
void remove_thread_context(thread_t tid = 0); void remove_thread_context(thread_t tid = 0);
static bedrock& instance(); static bedrock& instance();
core_window_t* focus(); basic_window* focus();
void set_menubar_taken(core_window_t*); void set_menubar_taken(basic_window*);
//Delay Restores focus when a menu which attached to menubar is closed //Delay Restores focus when a menu which attached to menubar is closed
void delay_restore(int); void delay_restore(int);
@ -84,7 +82,7 @@ namespace detail
bool shortkey_occurred() const; bool shortkey_occurred() const;
element_store& get_element_store() const; element_store& get_element_store() const;
void map_through_widgets(core_window_t*, native_drawable_type); void map_through_widgets(basic_window*, native_drawable_type);
//Closes the windows which are associated with the specified thread. If the given thread_id is 0, it closes all windows //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(thread_t thread_id); void close_thread_window(thread_t thread_id);
@ -94,28 +92,28 @@ namespace detail
static void delete_platform_assoc(window_platform_assoc*); static void delete_platform_assoc(window_platform_assoc*);
void keyboard_accelerator(native_window_type, const accel_key&, const std::function<void()>&); void keyboard_accelerator(native_window_type, const accel_key&, const std::function<void()>&);
public: public:
void event_expose(core_window_t *, bool exposed); void event_expose(basic_window *, bool exposed);
void event_move(core_window_t*, int x, int y); void event_move(basic_window*, int x, int y);
bool event_msleave(core_window_t*); bool event_msleave(basic_window*);
void event_focus_changed(core_window_t* root_wd, native_window_type receiver, bool getting); void event_focus_changed(basic_window* root_wd, native_window_type receiver, bool getting);
void thread_context_destroy(core_window_t*); void thread_context_destroy(basic_window*);
void thread_context_lazy_refresh(); void thread_context_lazy_refresh();
void update_cursor(core_window_t*); void update_cursor(basic_window*);
void set_cursor(core_window_t*, nana::cursor, thread_context*); void set_cursor(basic_window*, nana::cursor, thread_context*);
void define_state_cursor(core_window_t*, nana::cursor, thread_context*); void define_state_cursor(basic_window*, nana::cursor, thread_context*);
void undefine_state_cursor(core_window_t*, thread_context*); void undefine_state_cursor(basic_window*, thread_context*);
color_schemes& scheme(); color_schemes& scheme();
events_operation& evt_operation(); events_operation& evt_operation();
window_manager& wd_manager(); window_manager& wd_manager();
void manage_form_loader(core_window_t*, bool insert_or_remove); void manage_form_loader(basic_window*, bool insert_or_remove);
public: public:
// if 'bForce__EmitInternal', then ONLY internal (widget's) events are processed (even through explicit filtering) // if 'bForce__EmitInternal', then ONLY internal (widget's) events are processed (even through explicit filtering)
bool emit(event_code, core_window_t*, const event_arg&, bool ask_update, thread_context*, const bool bForce__EmitInternal = false); bool emit(event_code, basic_window*, const event_arg&, bool ask_update, thread_context*, const bool bForce__EmitInternal = false);
private: private:
void _m_emit_core(event_code, core_window_t*, bool draw_only, const event_arg&, const bool bForce__EmitInternal); void _m_emit_core(event_code, basic_window*, bool draw_only, const event_arg&, const bool bForce__EmitInternal);
void _m_event_filter(event_code, core_window_t*, thread_context*); void _m_event_filter(event_code, basic_window*, thread_context*);
private: private:
static bedrock bedrock_object; static bedrock bedrock_object;

View File

@ -1,223 +0,0 @@
/*
* Effects Renderer
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 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/effects_renderer.cpp
*/
#ifndef NANA_GUI_DETAIL_EFFECTS_RENDERER_HPP
#define NANA_GUI_DETAIL_EFFECTS_RENDERER_HPP
#include <nana/gui/effects.hpp>
#include <nana/paint/graphics.hpp>
#include <nana/paint/pixel_buffer.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/window_layout.hpp>
namespace nana{
namespace detail
{
template<typename CoreWindow>
class edge_nimbus_renderer
{
edge_nimbus_renderer() = default;
public:
using core_window_t = CoreWindow;
using window_layer = ::nana::detail::window_layout;
using graph_reference = ::nana::paint::graphics&;
static edge_nimbus_renderer& instance()
{
static edge_nimbus_renderer object;
return object;
}
constexpr unsigned weight() const
{
return 2;
}
void erase(core_window_t* wd)
{
if (effects::edge_nimbus::none == wd->effect.edge_nimbus)
return;
core_window_t * root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
for (auto i = nimbus.begin(); i != nimbus.end(); ++i)
{
if (i->window == wd)
{
auto pixels = weight();
rectangle r{wd->pos_root, wd->dimension};
r.x -= static_cast<int>(pixels);
r.y -= static_cast<int>(pixels);
r.width += static_cast<unsigned>(pixels << 1);
r.height += static_cast<unsigned>(pixels << 1);
root_wd->root_graph->paste(root_wd->root, r, r.x, r.y);
nimbus.erase(i);
break;
}
}
}
void render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr)
{
bool copy_separately = true;
std::vector<std::pair<rectangle, core_window_t*>> rd_set;
if (wd->root_widget->other.attribute.root->effects_edge_nimbus.size())
{
auto root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
auto focused = root_wd->other.attribute.root->focus;
const unsigned pixels = weight();
auto graph = root_wd->root_graph;
nana::rectangle r;
for(auto & action : nimbus)
{
if(_m_edge_nimbus(action.window, focused) && window_layer::read_visual_rectangle(action.window, r))
{
if (action.window == wd)
{
if (update_area)
::nana::overlap(*update_area, rectangle(r), r);
copy_separately = false;
}
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
if ((forced && (action.window == wd)) || (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;
}
}
else if(action.rendered)
{
action.rendered = false;
if (action.window == wd)
copy_separately = false;
::nana::rectangle erase_r(
action.window->pos_root.x - static_cast<int>(pixels),
action.window->pos_root.y - static_cast<int>(pixels),
static_cast<unsigned>(action.window->dimension.width + (pixels << 1)),
static_cast<unsigned>(action.window->dimension.height + (pixels << 1))
);
graph->paste(root_wd->root, erase_r, erase_r.x, erase_r.y);
}
}
}
if (copy_separately)
{
rectangle vr;
if (window_layer::read_visual_rectangle(wd, vr))
{
if (update_area)
::nana::overlap(*update_area, rectangle(vr), vr);
wd->root_graph->paste(wd->root, vr, vr.x, vr.y);
}
}
rectangle wd_r{ wd->pos_root, wd->dimension };
wd_r.pare_off(-static_cast<int>(this->weight()));
//Render
for (auto & rd : rd_set)
{
auto other_wd = rd.second;
if (other_wd != wd)
{
rectangle other_r{ other_wd->pos_root, other_wd->dimension };
other_r.pare_off(-static_cast<int>(this->weight()));
if (!overlapped(wd_r, other_r))
continue;
}
_m_render_edge_nimbus(other_wd, rd.first);
}
}
private:
/// Determines whether the effect will be rendered for the given window.
static bool _m_edge_nimbus(core_window_t * const wd, core_window_t * const focused_wd)
{
// Don't render the effect if the window is disabled.
if (wd->flags.enabled)
{
if ((focused_wd == wd) && (static_cast<unsigned>(wd->effect.edge_nimbus) & static_cast<unsigned>(effects::edge_nimbus::active)))
return true;
else if ((static_cast<unsigned>(wd->effect.edge_nimbus) & static_cast<unsigned>(effects::edge_nimbus::over)) && (wd->flags.action == mouse_action::hovered))
return true;
}
return false;
}
void _m_render_edge_nimbus(core_window_t* wd, const nana::rectangle & visual)
{
wd->flags.action_before = wd->flags.action;
auto r = visual;
r.pare_off(-static_cast<int>(weight()));
rectangle good_r;
if (overlap(r, rectangle{ wd->root_graph->size() }, good_r))
{
if ((good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) ||
(good_r.right() > visual.right()) || (good_r.bottom() > visual.bottom()))
{
auto graph = wd->root_graph;
nana::paint::pixel_buffer pixbuf(graph->handle(), r);
pixel_argb_t px0, px1, px2, px3;
px0 = pixbuf.pixel(0, 0);
px1 = pixbuf.pixel(r.width - 1, 0);
px2 = pixbuf.pixel(0, r.height - 1);
px3 = pixbuf.pixel(r.width - 1, r.height - 1);
good_r.x = good_r.y = 1;
good_r.width = r.width - 2;
good_r.height = r.height - 2;
pixbuf.rectangle(good_r, wd->annex.scheme->activated.get_color(), 0.95, false);
good_r.x = good_r.y = 0;
good_r.width = r.width;
good_r.height = r.height;
pixbuf.rectangle(good_r, wd->annex.scheme->activated.get_color(), 0.4, false);
pixbuf.pixel(0, 0, px0);
pixbuf.pixel(r.width - 1, 0, px1);
pixbuf.pixel(0, r.height - 1, px2);
pixbuf.pixel(r.width - 1, r.height - 1, px3);
pixbuf.paste(wd->root, { r.x, r.y });
std::vector<typename window_layer::wd_rectangle> overlaps;
if(window_layer::read_overlaps(wd, visual, overlaps))
{
for(auto & wdr : overlaps)
graph->paste(wd->root, wdr.r, wdr.r.x, wdr.r.y);
}
}
else
wd->root_graph->paste(wd->root, visual, visual.x, visual.y);
}
}
};
}
}//end namespace nana
#endif

View File

@ -24,9 +24,13 @@
namespace nana namespace nana
{ {
namespace API
{
bool is_window(window); ///< Determines whether a window is existing, equal to !empty_window.
}
namespace detail namespace detail
{ {
bool check_window(window);
void events_operation_register(event_handle); void events_operation_register(event_handle);
class event_interface class event_interface
@ -36,16 +40,16 @@ namespace nana
virtual void remove(event_handle) = 0; virtual void remove(event_handle) = 0;
}; };
class docker_interface class event_docker_interface
{ {
public: public:
virtual ~docker_interface() = default; virtual ~event_docker_interface() = default;
virtual event_interface* get_event() const = 0; virtual event_interface* get_event() const = 0;
}; };
struct docker_base struct docker_base
: public docker_interface : public event_docker_interface
{ {
event_interface * const event_ptr; event_interface * const event_ptr;
bool flag_deleted; bool flag_deleted;
@ -78,11 +82,11 @@ namespace nana
event_base * const evt_; event_base * const evt_;
}; };
event_handle _m_emplace(detail::docker_interface*, bool in_front); event_handle _m_emplace(detail::event_docker_interface*, bool in_front);
protected: protected:
unsigned emitting_count_{ 0 }; unsigned emitting_count_{ 0 };
bool deleted_flags_{ false }; bool deleted_flags_{ false };
std::vector<detail::docker_interface*> * dockers_{ nullptr }; std::vector<detail::event_docker_interface*> * dockers_{ nullptr };
}; };
}//end namespace detail }//end namespace detail
@ -228,7 +232,7 @@ namespace nana
d->invoke(arg); d->invoke(arg);
if (window_handle && (!detail::check_window(window_handle))) if (window_handle && (!::nana::API::is_window(window_handle)))
break; break;
} }
} }

View File

@ -35,11 +35,9 @@ namespace detail
class window_layout class window_layout
{ {
public: public:
typedef basic_window core_window_t;
struct wd_rectangle struct wd_rectangle
{ {
core_window_t * window; basic_window * window;
rectangle r; rectangle r;
}; };
@ -49,27 +47,27 @@ namespace detail
try_refresh try_refresh
}; };
public: public:
static void paint(core_window_t*, paint_operation, bool request_refresh_children); static void paint(basic_window*, paint_operation, bool request_refresh_children);
static bool maproot(core_window_t*, bool have_refreshed, bool request_refresh_children); static bool maproot(basic_window*, bool have_refreshed, bool request_refresh_children);
static void paste_children_to_graphics(core_window_t*, nana::paint::graphics& graph); static void paste_children_to_graphics(basic_window*, nana::paint::graphics& graph);
//read_visual_rectangle //read_visual_rectangle
//@brief: Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget, //@brief: Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget,
// the visual rectangle is a rectangular block that a window should be displayed on screen. // the visual rectangle is a rectangular block that a window should be displayed on screen.
// The result is a rectangle that is a visible area for its ancesters. // The result is a rectangle that is a visible area for its ancesters.
static bool read_visual_rectangle(core_window_t*, nana::rectangle& visual); static bool read_visual_rectangle(basic_window*, nana::rectangle& visual);
//read_overlaps //read_overlaps
// reads the overlaps that are overlapped a rectangular block // reads the overlaps that are overlapped a rectangular block
static bool read_overlaps(core_window_t*, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks); static bool read_overlaps(basic_window*, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks);
static bool enable_effects_bground(core_window_t *, bool enabled); static bool enable_effects_bground(basic_window *, bool enabled);
//make_bground //make_bground
// update the glass buffer of a glass window. // update the glass buffer of a glass window.
static void make_bground(core_window_t* const); static void make_bground(basic_window* const);
private: private:
/// _m_paste_children /// _m_paste_children
@ -82,16 +80,16 @@ namespace detail
* @param graph A graphics object to which the child windows are pasted. * @param graph A graphics object to which the child windows are pasted.
* @param graph_rpos The reference point to the graph. * @param graph_rpos The reference point to the graph.
*/ */
static void _m_paste_children(core_window_t* window, bool has_refreshed, bool request_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos); static void _m_paste_children(basic_window* window, bool has_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); static void _m_paint_glass_window(basic_window*, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other);
//Notify the windows which have brground to update their background buffer. //Notify the windows which have brground to update their background buffer.
static void _m_notify_glasses(core_window_t* const sigwd); static void _m_notify_glasses(basic_window* const sigwd);
private: private:
struct data_section struct data_section
{ {
std::vector<core_window_t*> effects_bground_windows; std::vector<basic_window*> effects_bground_windows;
}; };
static data_section data_sect; static data_section data_sect;
};//end class window_layout };//end class window_layout

View File

@ -67,95 +67,93 @@ namespace detail
using native_window = native_window_type; using native_window = native_window_type;
using mutex_type = revertible_mutex; using mutex_type = revertible_mutex;
using core_window_t = basic_window;
window_manager(); window_manager();
~window_manager(); ~window_manager();
std::size_t number_of_core_window() const; std::size_t window_count() const;
mutex_type & internal_lock() const; mutex_type & internal_lock() const;
void all_handles(std::vector<core_window_t*>&) const; void all_handles(std::vector<basic_window*>&) const;
void event_filter(core_window_t*, bool is_make, event_code); void event_filter(basic_window*, bool is_make, event_code);
bool available(core_window_t*); bool available(basic_window*);
bool available(core_window_t *, core_window_t*); bool available(basic_window *, basic_window*);
core_window_t* create_root(core_window_t*, bool nested, rectangle, const appearance&, widget*); basic_window* create_root(basic_window*, bool nested, rectangle, const appearance&, widget*);
core_window_t* create_widget(core_window_t*, const rectangle&, bool is_lite, widget*); basic_window* create_widget(basic_window*, const rectangle&, bool is_lite, widget*);
void close(core_window_t*); void close(basic_window*);
//destroy //destroy
//@brief: Delete the window handle //@brief: Delete the window handle
void destroy(core_window_t*); void destroy(basic_window*);
//destroy_handle //destroy_handle
//@brief: Delete window handle, the handle type must be a root and a frame. //@brief: Delete window handle, the handle type must be a root and a frame.
// Deletes a window whose category type is a root type or a frame type. // Deletes a window whose category type is a root type or a frame type.
void destroy_handle(core_window_t*); void destroy_handle(basic_window*);
void icon(core_window_t*, const paint::image& small_icon, const paint::image& big_icon); void icon(basic_window*, const paint::image& small_icon, const paint::image& big_icon);
bool show(core_window_t* wd, bool visible); bool show(basic_window* wd, bool visible);
//find a widget window at specified position //find a widget window at specified position
//@param root A root window //@param root A root window
//@param pos Position //@param pos Position
//@param ignore_captured A flag indicates whether to ignore redirecting the result to its captured window. If this paramter is true, it returns the window at the position, if the parameter is false, it returns the captured window if the captured window don't ignore children. //@param ignore_captured A flag indicates whether to ignore redirecting the result to its captured window. If this paramter is true, it returns the window at the position, if the parameter is false, it returns the captured window if the captured window don't ignore children.
core_window_t* find_window(native_window_type root, const point& pos, bool ignore_captured = false); basic_window* find_window(native_window_type root, const point& pos, bool ignore_captured = false);
//move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window //move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window
bool move(core_window_t*, int x, int y, bool passive); bool move(basic_window*, int x, int y, bool passive);
bool move(core_window_t*, const rectangle&); bool move(basic_window*, const rectangle&);
bool size(core_window_t*, nana::size, bool passive, bool ask_update); bool size(basic_window*, nana::size, bool passive, bool ask_update);
core_window_t* root(native_window_type) const; basic_window* root(native_window_type) const;
//Copy the root buffer that wnd specified into DeviceContext //Copy the root buffer that wnd specified into DeviceContext
void map(core_window_t*, bool forced, const rectangle* update_area = nullptr); void map(basic_window*, bool forced, const rectangle* update_area = nullptr);
bool update(core_window_t*, bool redraw, bool force, const rectangle* update_area = nullptr); bool update(basic_window*, bool redraw, bool force, const rectangle* update_area = nullptr);
void update_requesters(core_window_t* root_wd); void update_requesters(basic_window* root_wd);
void refresh_tree(core_window_t*); void refresh_tree(basic_window*);
void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false); void do_lazy_refresh(basic_window*, bool force_copy_to_screen, bool refresh_tree = false);
bool set_parent(core_window_t* wd, core_window_t* new_parent); bool set_parent(basic_window* wd, basic_window* new_parent);
core_window_t* set_focus(core_window_t*, bool root_has_been_focused, arg_focus::reason); basic_window* set_focus(basic_window*, bool root_has_been_focused, arg_focus::reason);
core_window_t* capture_redirect(core_window_t*); basic_window* capture_redirect(basic_window*);
bool capture_window_entered(int root_x, int root_y, bool& prev); bool capture_window_entered(int root_x, int root_y, bool& prev);
core_window_t * capture_window() const; basic_window * capture_window() const;
void capture_window(core_window_t*, bool capture, bool ignore_children_if_captured); void capture_window(basic_window*, bool capture, bool ignore_children_if_captured);
void enable_tabstop(core_window_t*); void enable_tabstop(basic_window*);
core_window_t* tabstop(core_window_t*, bool forward) const; //forward means move to next in logic. basic_window* tabstop(basic_window*, bool forward) const; //forward means move to next in logic.
void remove_trash_handle(thread_t tid); void remove_trash_handle(thread_t tid);
bool enable_effects_bground(core_window_t*, bool); bool enable_effects_bground(basic_window*, bool);
bool calc_window_point(core_window_t*, nana::point&); bool calc_window_point(basic_window*, nana::point&);
root_misc* root_runtime(native_window) const; root_misc* root_runtime(native_window) const;
bool register_shortkey(core_window_t*, unsigned long key); bool register_shortkey(basic_window*, unsigned long key);
void unregister_shortkey(core_window_t*, bool with_children); void unregister_shortkey(basic_window*, bool with_children);
core_window_t* find_shortkey(native_window_type, unsigned long key); basic_window* find_shortkey(native_window_type, unsigned long key);
void set_safe_place(core_window_t* wd, std::function<void()>&& fn); void set_safe_place(basic_window* wd, std::function<void()>&& fn);
void call_safe_place(thread_t thread_id); void call_safe_place(thread_t thread_id);
private: private:
void _m_disengage(core_window_t*, core_window_t* for_new); void _m_disengage(basic_window*, basic_window* for_new);
void _m_destroy(core_window_t*); void _m_destroy(basic_window*);
void _m_move_core(core_window_t*, const point& delta); void _m_move_core(basic_window*, const point& delta);
void _m_shortkeys(core_window_t*, bool with_chlidren, std::vector<std::pair<core_window_t*, unsigned long>>& keys) const; void _m_shortkeys(basic_window*, bool with_chlidren, std::vector<std::pair<basic_window*, unsigned long>>& keys) const;
core_window_t* _m_find(core_window_t*, const point&); basic_window* _m_find(basic_window*, const point&);
static bool _m_effective(core_window_t*, const point& root_pos); static bool _m_effective(basic_window*, const point& root_pos);
private: private:
mutable mutex_type mutex_; mutable mutex_type mutex_;
@ -166,10 +164,10 @@ namespace detail
{ {
struct captured struct captured
{ {
core_window_t *window; basic_window *window;
bool inside; bool inside;
bool ignore_children; bool ignore_children;
std::vector<std::pair<core_window_t*, bool> > history; std::vector<std::pair<basic_window*, bool> > history;
}capture; }capture;
}attr_; }attr_;

View File

@ -59,11 +59,7 @@ namespace nana
void text(const ::std::string&); void text(const ::std::string&);
void icon(const ::std::string& icon_file); void icon(const ::std::string& icon_file);
void insert_icon(const ::std::string& icon_file); void insert_icon(const ::std::string& icon_file);
#if 0 //deprecated
void period(unsigned millisecond);
#else
void period(std::chrono::milliseconds time); void period(std::chrono::milliseconds time);
#endif
detail::notifier_events& events(); detail::notifier_events& events();
window handle() const; window handle() const;
private: private:

View File

@ -22,14 +22,16 @@
namespace nana namespace nana
{ {
/// Can repeatedly call a piece of code.
class timer;
struct arg_elapse struct arg_elapse
: public event_arg : public event_arg
{ {
long long id; //timer identifier; timer* sender; //indicates which timer emitted this notification
}; };
/// Can repeatedly call a piece of code.
class timer class timer
{ {
struct implement; struct implement;

View File

@ -1219,7 +1219,6 @@ namespace nana
unsigned min_column_width{ 20 }; ///< def=20 . non counting suspension_width unsigned min_column_width{ 20 }; ///< def=20 . non counting suspension_width
unsigned suspension_width{ 8 }; ///< def= . the trigger will set this to the width if ("...")
unsigned text_margin{ 5 }; ///< def= 5. Additional or extended with added (before) to the text width to determine the cell width. cell_w = text_w + ext_w +1 unsigned 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 item_height_ex{ 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex unsigned item_height_ex{ 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex
@ -1603,6 +1602,8 @@ the nana::detail::basic_window member pointer scheme
* It returns true to deselect the selected items. It returns false to cancel to deselect the selected items. * It returns true to deselect the selected items. It returns false to cancel to deselect the selected items.
*/ */
void set_deselect(std::function<bool(nana::mouse)> predicate); void set_deselect(std::function<bool(nana::mouse)> predicate);
unsigned suspension_width() const;
private: private:
drawerbase::listbox::essence & _m_ess() const; drawerbase::listbox::essence & _m_ess() const;
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const override; nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const override;

View File

@ -1,88 +0,0 @@
/**
* Nana GUI Library Definition
* 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/wvl.hpp
* @description
* the header file contains the files required for running of Nana.GUI
*/
#ifndef NANA_GUI_WVL_HPP
#define NANA_GUI_WVL_HPP
#include "programming_interface.hpp"
#include "screen.hpp"
#include "widgets/form.hpp"
#include "drawing.hpp"
#include "msgbox.hpp"
#include "place.hpp"
namespace nana
{
namespace detail
{
struct form_loader_private
{
template<typename, bool> friend class form_loader;
private:
static void insert_form(::nana::widget*);
};
template<typename Form, bool IsVisible>
class form_loader
{
public:
template<typename... Args>
Form & operator()(Args &&... args) const
{
auto p = new Form(std::forward<Args>(args)...);
if (p->empty())
throw std::logic_error("form_loader failed to create the form");
detail::form_loader_private::insert_form(p);
if (IsVisible)
p->show();
return *p;
}
};
}
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 optionally automatically tests it.
///
/// @detail It transfers to nana the program flow control, which begin pumping messages
/// from the underlying OS, interpreting and sending it with suitable arguments
/// to the nana widgets that registered a response in the corresponding event.
/// It also accept arguments to be used in case of automatic GUI testing.
/// Other Way the arguments are ignored.
void exec(
unsigned wait = 1, ///< for the GUI to be constructed, in seconds
unsigned wait_end = 1, ///< for the GUI to be destructed, in seconds
std::function<void()> = {} ///< emit events to mimics user actions and may assert results
);
/// send a click message to this widget - useful in GUI testing
void click(widget& w);
/// in seconds
void Wait(unsigned wait = 0);
#else
void exec();
#endif
}//end namespace nana
#endif

View File

@ -11,13 +11,19 @@ namespace nana
public: public:
using graph_reference = graphics &; using graph_reference = graphics &;
enum class mode
{
truncate_with_ellipsis,
truncate_letter_with_ellipsis,
word_wrap
};
text_renderer(graph_reference graph, align = align::left); text_renderer(graph_reference graph, align = align::left);
nana::size extent_size(int x, int y, const wchar_t*, std::size_t len, unsigned restricted_pixels) const; nana::size extent_size(int x, int y, const wchar_t*, std::size_t len, unsigned space_pixels) const;
void render(const point&, const wchar_t*, std::size_t len); void render(const point&, const wchar_t*, std::size_t len);
void render(const point&, const wchar_t*, std::size_t len, unsigned restricted_pixels, bool omitted); void render(const point&, const wchar_t*, std::size_t len, unsigned space_pixels, mode);
void render(const point&, const wchar_t*, std::size_t len, unsigned restricted_pixels);
private: private:
graph_reference graph_; graph_reference graph_;
align text_align_; align text_align_;

View File

@ -14,24 +14,23 @@
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
#include <windows.h> #include <windows.h>
#endif #endif
#include <cassert>
#include <array> #include <array>
namespace { namespace {
std::tm localtime() std::tm localtime()
{ {
#if defined(NANA_WINDOWS) && !defined(NANA_MINGW) #if defined(NANA_WINDOWS) && !defined(NANA_MINGW)
time_t t; std::time_t t = std::time(nullptr);
::time(&t);
std::tm tm; std::tm tm;
if (localtime_s(&tm, &t) != 0) if (localtime_s(&tm, &t) != 0)
assert(false); throw std::runtime_error("invalid local time");
return tm; return tm;
#else #else
time_t t = std::time(nullptr); time_t t = std::time(nullptr);
struct tm * tm_addr = std::localtime(&t); struct tm * tm_addr = std::localtime(&t);
assert(tm_addr); if(nullptr == tm_addr)
throw std::runtime_error("invalid local time");
return *tm_addr; return *tm_addr;
#endif #endif

View File

@ -1,7 +1,7 @@
/** /**
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -96,19 +96,19 @@ namespace detail
unsigned whitespace_pixels; unsigned whitespace_pixels;
}string; }string;
unsigned fgcolor_rgb{ 0xFFFFFFFF };
unsigned bgcolor_rgb{ 0xFFFFFFFF };
unsigned fgcolor_native{ 0xFFFFFFFF }; //Windows RGB format: 0xBBGGRR
unsigned bgcolor_native{ 0xFFFFFFFF }; //Windows RGB format
drawable_impl_type(const drawable_impl_type&) = delete; drawable_impl_type(const drawable_impl_type&) = delete;
drawable_impl_type& operator=(const drawable_impl_type&) = delete; drawable_impl_type& operator=(const drawable_impl_type&) = delete;
drawable_impl_type(); drawable_impl_type();
~drawable_impl_type(); ~drawable_impl_type();
unsigned get_color() const;
unsigned get_text_color() const;
void set_color(const ::nana::color&); void set_color(const ::nana::color&);
void set_text_color(const ::nana::color&); void set_text_color(const ::nana::color&);
private:
unsigned color_{ 0xffffffff };
unsigned text_color_{0xffffffff};
}; };
class platform_spec class platform_spec

View File

@ -1,7 +1,7 @@
/* /*
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Nana Software License, Version 1.0. * Distributed under the Nana Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -27,7 +27,6 @@
#include <algorithm> #include <algorithm>
#include <nana/paint/graphics.hpp> #include <nana/paint/graphics.hpp>
#include <nana/gui/detail/bedrock.hpp> #include <nana/gui/detail/bedrock.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include <nana/gui/detail/window_manager.hpp> #include <nana/gui/detail/window_manager.hpp>
#include <nana/system/platform.hpp> #include <nana/system/platform.hpp>
#include <nana/paint/pixel_buffer.hpp> #include <nana/paint/pixel_buffer.hpp>
@ -35,6 +34,7 @@
#include <sstream> #include <sstream>
#include "posix/msg_dispatcher.hpp" #include "posix/msg_dispatcher.hpp"
#include "../gui/detail/basic_window.hpp"
namespace nana namespace nana
{ {
@ -95,7 +95,7 @@ namespace detail
return std::string(); return std::string();
} }
//end class conf //end class conf
#if 0
//class charset_conv //class charset_conv
charset_conv::charset_conv(const char* tocode, const char* fromcode) charset_conv::charset_conv(const char* tocode, const char* fromcode)
{ {
@ -140,6 +140,7 @@ namespace detail
return rstr; return rstr;
} }
//end class charset_conv //end class charset_conv
#endif
#endif #endif
//Caret implementation //Caret implementation
@ -209,15 +210,15 @@ namespace detail
class timer_runner class timer_runner
{ {
typedef void (*timer_proc_t)(std::size_t id); using handler_type = void(*)(const timer_core*);
struct timer_tag struct timer_tag
{ {
std::size_t id; const timer_core* handle;
thread_t tid; thread_t thread_id;
std::size_t interval; std::size_t interval;
std::size_t timestamp; std::size_t timestamp;
timer_proc_t proc; handler_type handler;
}; };
//timer_group //timer_group
@ -233,32 +234,32 @@ namespace detail
struct timer_group struct timer_group
{ {
bool proc_entered{false}; //This flag indicates whether the timers are going to do event. bool proc_entered{false}; //This flag indicates whether the timers are going to do event.
std::set<std::size_t> timers; std::set<const timer_core*> timers;
std::vector<std::size_t> delay_deleted; std::vector<const timer_core*> delay_deleted;
}; };
public: public:
timer_runner() timer_runner()
: is_proc_handling_(false) : is_proc_handling_(false)
{} {}
void set(std::size_t id, std::size_t interval, timer_proc_t proc) void set(const timer_core* handle, std::size_t interval, handler_type handler)
{ {
auto i = holder_.find(id); auto i = holder_.find(handle);
if(i != holder_.end()) if(i != holder_.end())
{ {
i->second.interval = interval; i->second.interval = interval;
i->second.proc = proc; i->second.handler = handler;
return; return;
} }
auto tid = nana::system::this_thread_id(); auto tid = nana::system::this_thread_id();
threadmap_[tid].timers.insert(id); threadmap_[tid].timers.insert(handle);
timer_tag & tag = holder_[id]; timer_tag & tag = holder_[handle];
tag.id = id; tag.handle = handle;
tag.tid = tid; tag.thread_id = tid;
tag.interval = interval; tag.interval = interval;
tag.timestamp = 0; tag.timestamp = 0;
tag.proc = proc; tag.handler = handler;
} }
bool is_proc_handling() const bool is_proc_handling() const
@ -266,12 +267,12 @@ namespace detail
return is_proc_handling_; return is_proc_handling_;
} }
void kill(std::size_t id) bool kill(const timer_core* handle)
{ {
auto i = holder_.find(id); auto i = holder_.find(handle);
if(i != holder_.end()) if(i != holder_.end())
{ {
auto tid = i->second.tid; auto tid = i->second.thread_id;
auto ig = threadmap_.find(tid); auto ig = threadmap_.find(tid);
if(ig != threadmap_.end()) //Generally, the ig should not be the end of threadmap_ if(ig != threadmap_.end()) //Generally, the ig should not be the end of threadmap_
@ -279,20 +280,16 @@ namespace detail
auto & group = ig->second; auto & group = ig->second;
if(!group.proc_entered) if(!group.proc_entered)
{ {
group.timers.erase(id); group.timers.erase(handle);
if(group.timers.empty()) if(group.timers.empty())
threadmap_.erase(ig); threadmap_.erase(ig);
} }
else else
group.delay_deleted.push_back(id); group.delay_deleted.push_back(handle);
} }
holder_.erase(i); holder_.erase(i);
} }
} return holder_.empty();
bool empty() const
{
return (holder_.empty());
} }
void timer_proc(thread_t tid) void timer_proc(thread_t tid)
@ -314,7 +311,7 @@ namespace detail
tag.timestamp = ticks; tag.timestamp = ticks;
try try
{ {
tag.proc(tag.id); tag.handler(tag.handle);
}catch(...){} //nothrow }catch(...){} //nothrow
} }
} }
@ -330,7 +327,7 @@ namespace detail
private: private:
bool is_proc_handling_; bool is_proc_handling_;
std::map<thread_t, timer_group> threadmap_; std::map<thread_t, timer_group> threadmap_;
std::map<std::size_t, timer_tag> holder_; std::map<const timer_core*, timer_tag> holder_;
}; };
drawable_impl_type::drawable_impl_type() drawable_impl_type::drawable_impl_type()
@ -338,49 +335,28 @@ namespace detail
string.tab_length = 4; string.tab_length = 4;
string.tab_pixels = 0; string.tab_pixels = 0;
string.whitespace_pixels = 0; string.whitespace_pixels = 0;
#if defined(NANA_USE_XFT)
conv_.handle = ::iconv_open("UTF-8", NANA_UNICODE);
conv_.code = NANA_UNICODE;
#endif
}
drawable_impl_type::~drawable_impl_type()
{
#if defined(NANA_USE_XFT)
::iconv_close(conv_.handle);
#endif
}
unsigned drawable_impl_type::get_color() const
{
return color_;
}
unsigned drawable_impl_type::get_text_color() const
{
return text_color_;
} }
void drawable_impl_type::set_color(const ::nana::color& clr) void drawable_impl_type::set_color(const ::nana::color& clr)
{ {
color_ = (clr.px_color().value & 0xFFFFFF); bgcolor_rgb = (clr.px_color().value & 0xFFFFFF);
} }
void drawable_impl_type::set_text_color(const ::nana::color& clr) void drawable_impl_type::set_text_color(const ::nana::color& clr)
{ {
text_color_ = (clr.px_color().value & 0xFFFFFF); fgcolor_rgb = (clr.px_color().value & 0xFFFFFF);
update_text_color(); update_text_color();
} }
void drawable_impl_type::update_color() void drawable_impl_type::update_color()
{ {
if (color_ != current_color_) if (bgcolor_rgb != current_color_)
{ {
auto & spec = nana::detail::platform_spec::instance(); auto & spec = nana::detail::platform_spec::instance();
platform_scope_guard lock; platform_scope_guard lock;
current_color_ = color_; current_color_ = bgcolor_rgb;
auto col = color_; auto col = bgcolor_rgb;
switch (spec.screen_depth()) switch (spec.screen_depth())
{ {
case 16: case 16:
@ -391,18 +367,32 @@ namespace detail
} }
::XSetForeground(spec.open_display(), context, col); ::XSetForeground(spec.open_display(), context, col);
::XSetBackground(spec.open_display(), context, col); ::XSetBackground(spec.open_display(), context, col);
#if defined(NANA_USE_XFT)
//xft_fgcolor also needs to be assigned.
//assumes the xft_fgcolor is not assigned in update_color. There is a situation that causes a bug.
//
//update_text_color ( if fgcolor_rgb = A, then current_color = A and xft_fgcolor = A)
//update_color (if bgcolor_rgb = B, then current_color = B and xft_fgcolor is still A)
//update_text_color ( if fgcolor_rgb = B, then current_color = B, xft_fgcolor is still A)
xft_fgcolor.color.red = ((0xFF0000 & col) >> 16) * 0x101;
xft_fgcolor.color.green = ((0xFF00 & col) >> 8) * 0x101;
xft_fgcolor.color.blue = (0xFF & col) * 0x101;
xft_fgcolor.color.alpha = 0xFFFF;
#endif
} }
} }
void drawable_impl_type::update_text_color() void drawable_impl_type::update_text_color()
{ {
if (text_color_ != current_color_) if (fgcolor_rgb != current_color_)
{ {
auto & spec = nana::detail::platform_spec::instance(); auto & spec = nana::detail::platform_spec::instance();
platform_scope_guard lock; platform_scope_guard lock;
current_color_ = text_color_; current_color_ = fgcolor_rgb;
auto col = text_color_; auto col = fgcolor_rgb;
switch (spec.screen_depth()) switch (spec.screen_depth())
{ {
case 16: case 16:
@ -445,7 +435,7 @@ namespace detail
} }
platform_spec::timer_runner_tag::timer_runner_tag() platform_spec::timer_runner_tag::timer_runner_tag()
: runner(0), delete_declared(false) : runner(nullptr), delete_declared(false)
{} {}
platform_spec::platform_spec() platform_spec::platform_spec()
@ -987,32 +977,34 @@ namespace detail
return r; return r;
} }
void platform_spec::set_timer(std::size_t id, std::size_t interval, void (*timer_proc)(std::size_t)) void platform_spec::set_timer(const timer_core* handle, std::size_t interval, void (*timer_proc)(const timer_core*))
{ {
std::lock_guard<decltype(timer_.mutex)> lock(timer_.mutex); std::lock_guard<decltype(timer_.mutex)> lock(timer_.mutex);
if(0 == timer_.runner) if(!timer_.runner)
timer_.runner = new timer_runner; timer_.runner = new timer_runner;
timer_.runner->set(id, interval, timer_proc);
timer_.runner->set(handle, interval, timer_proc);
timer_.delete_declared = false; timer_.delete_declared = false;
} }
void platform_spec::kill_timer(std::size_t id) void platform_spec::kill_timer(const timer_core* handle)
{ {
if(timer_.runner == 0) return;
std::lock_guard<decltype(timer_.mutex)> lock(timer_.mutex); std::lock_guard<decltype(timer_.mutex)> lock(timer_.mutex);
timer_.runner->kill(id); if(timer_.runner)
if(timer_.runner->empty()) {
// Test if there is not a timer after killing
if(timer_.runner->kill(handle))
{ {
if(timer_.runner->is_proc_handling() == false) if(timer_.runner->is_proc_handling() == false)
{ {
delete timer_.runner; delete timer_.runner;
timer_.runner = 0; timer_.runner = nullptr;
} }
else else
timer_.delete_declared = true; timer_.delete_declared = true;
} }
} }
}
void platform_spec::timer_proc(thread_t tid) void platform_spec::timer_proc(thread_t tid)
{ {
@ -1023,7 +1015,7 @@ namespace detail
if(timer_.delete_declared) if(timer_.delete_declared)
{ {
delete timer_.runner; delete timer_.runner;
timer_.runner = 0; timer_.runner = nullptr;
timer_.delete_declared = false; timer_.delete_declared = false;
} }
} }

View File

@ -1,7 +1,7 @@
/** /**
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -42,28 +42,22 @@ namespace detail
::DeleteObject(pixmap); ::DeleteObject(pixmap);
} }
unsigned drawable_impl_type::get_color() const #define NANA_WINDOWS_RGB(a) (((DWORD)(a) & 0xFF)<<16) | ((DWORD)(a) & 0xFF00) | (((DWORD)(a) & 0xFF0000) >> 16 )
{
return color_;
}
unsigned drawable_impl_type::get_text_color() const
{
return text_color_;
}
void drawable_impl_type::set_color(const ::nana::color& clr) void drawable_impl_type::set_color(const ::nana::color& clr)
{ {
color_ = (clr.px_color().value & 0xFFFFFF); bgcolor_rgb = (clr.px_color().value & 0xFFFFFF);
bgcolor_native = NANA_WINDOWS_RGB(bgcolor_rgb);
} }
void drawable_impl_type::set_text_color(const ::nana::color& clr) void drawable_impl_type::set_text_color(const ::nana::color& clr)
{ {
auto rgb = (clr.px_color().value & 0xFFFFFF); auto rgb = (clr.px_color().value & 0xFFFFFF);
if (text_color_ != rgb) if (fgcolor_rgb != rgb)
{ {
::SetTextColor(context, NANA_RGB(rgb)); fgcolor_rgb = rgb;
text_color_ = rgb; fgcolor_native = NANA_WINDOWS_RGB(rgb);
::SetTextColor(context, fgcolor_native);
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -42,7 +42,6 @@
#if defined(NANA_USE_XFT) #if defined(NANA_USE_XFT)
#include <X11/Xft/Xft.h> #include <X11/Xft/Xft.h>
#include <iconv.h>
#include <fstream> #include <fstream>
#endif #endif
@ -62,19 +61,6 @@ namespace detail
private: private:
std::ifstream ifs_; std::ifstream ifs_;
}; };
class charset_conv
{
charset_conv(const charset_conv&) = delete;
charset_conv& operator=(const charset_conv*) = delete;
public:
charset_conv(const char* tocode, const char* fromcode);
~charset_conv();
std::string charset(const std::string& str) const;
std::string charset(const char * buf, std::size_t len) const;
private:
iconv_t handle_;
};
#endif #endif
struct drawable_impl_type struct drawable_impl_type
@ -95,16 +81,15 @@ namespace detail
unsigned whitespace_pixels; unsigned whitespace_pixels;
}string; }string;
unsigned fgcolor_rgb{ 0xFFFFFFFF };
unsigned bgcolor_rgb{ 0xFFFFFFFF };
#if defined(NANA_USE_XFT) #if defined(NANA_USE_XFT)
XftDraw * xftdraw{nullptr}; XftDraw * xftdraw{nullptr};
XftColor xft_fgcolor; XftColor xft_fgcolor;
const std::string charset(const std::wstring& str, const std::string& strcode);
#endif #endif
drawable_impl_type(); drawable_impl_type();
~drawable_impl_type();
unsigned get_color() const;
unsigned get_text_color() const;
void set_color(const ::nana::color&); void set_color(const ::nana::color&);
void set_text_color(const ::nana::color&); void set_text_color(const ::nana::color&);
@ -115,16 +100,6 @@ namespace detail
drawable_impl_type& operator=(const drawable_impl_type&) = delete; drawable_impl_type& operator=(const drawable_impl_type&) = delete;
unsigned current_color_{ 0xFFFFFF }; unsigned current_color_{ 0xFFFFFF };
unsigned color_{ 0xFFFFFFFF };
unsigned text_color_{ 0xFFFFFFFF };
#if defined(NANA_USE_XFT)
struct conv_tag
{
iconv_t handle;
std::string code;
}conv_;
#endif
}; };
struct atombase_tag struct atombase_tag
@ -171,6 +146,13 @@ namespace detail
//A forward declaration of caret data //A forward declaration of caret data
struct caret_rep; struct caret_rep;
/// class timer_core
/**
* Platform-spec only provides the declaration for intrducing a handle type, the definition
* of timer_core is given by gui/timer.cpp
*/
class timer_core;
class timer_runner; class timer_runner;
class platform_scope_guard class platform_scope_guard
@ -251,8 +233,8 @@ namespace detail
//when native_interface::show a window that is registered as a grab //when native_interface::show a window that is registered as a grab
//window, the native_interface grabs the window. //window, the native_interface grabs the window.
Window grab(Window); Window grab(Window);
void set_timer(std::size_t id, std::size_t interval, void (*timer_proc)(std::size_t id)); void set_timer(const timer_core*, std::size_t interval, void (*timer_proc)(const timer_core* tm));
void kill_timer(std::size_t id); void kill_timer(const timer_core*);
void timer_proc(thread_t tid); void timer_proc(thread_t tid);
//Message dispatcher //Message dispatcher

View File

@ -110,42 +110,6 @@ namespace nana
return tm.str(); return tm.str();
} }
return {}; return {};
/*
// Deprecated
//Windows stores file times using the FILETIME structure, which is a 64 bit value of 100ns intervals from January 1, 1601.
//What's worse is that this 1601 date is fairly common to see given that it's the all zeroes value, and it is far before the
//earliest date representable with time_t.std::filesystem can't change the reality of the underlying platform.
try {
#if NANA_USING_BOOST_FILESYSTEM
// The return type of boost::filesystem::last_write_time isn't
// the same as in nana and std implementations of this function
auto ftime = std::chrono::system_clock::from_time_t(fs::last_write_time(path));
#else
auto ftime = fs::last_write_time(path);
#endif
// crash: VS2015 will not read the time for some files (for example: C:/hiberfil.sys)
// and will return file_time_type(-1) without throwing
// https://msdn.microsoft.com/en-us/library/dn823784.aspx
if (ftime == ((fs::file_time_type::min)())) return{};
//A workaround for VC2013
using time_point = decltype(ftime);
auto cftime = time_point::clock::to_time_t(ftime);
std::stringstream tm;
tm << std::put_time(std::localtime(&cftime), "%Y-%m-%d, %H:%M:%S");
return tm.str();
}
catch (...) {
return{};
}
#endif
*/
} }
bool modified_file_time(const fs::path& p, struct tm& t) bool modified_file_time(const fs::path& p, struct tm& t)

View File

@ -10,7 +10,7 @@
* @file: nana/gui/detail/basic_window.cpp * @file: nana/gui/detail/basic_window.cpp
*/ */
#include <nana/gui/detail/basic_window.hpp> #include "basic_window.hpp"
#include <nana/gui/detail/native_window_interface.hpp> #include <nana/gui/detail/native_window_interface.hpp>
namespace nana namespace nana

View File

@ -14,11 +14,11 @@
#ifndef NANA_GUI_DETAIL_BASIC_WINDOW_HPP #ifndef NANA_GUI_DETAIL_BASIC_WINDOW_HPP
#define NANA_GUI_DETAIL_BASIC_WINDOW_HPP #define NANA_GUI_DETAIL_BASIC_WINDOW_HPP
#include <nana/push_ignore_diagnostic> #include <nana/push_ignore_diagnostic>
#include "drawer.hpp" #include <nana/gui/detail/drawer.hpp>
#include "events_holder.hpp" #include <nana/gui/detail/events_holder.hpp>
#include "widget_geometrics.hpp" #include <nana/gui/detail/widget_geometrics.hpp>
#include "widget_content_measurer_interface.hpp" #include <nana/gui/detail/widget_content_measurer_interface.hpp>
#include "widget_notifier_interface.hpp" #include <nana/gui/detail/widget_notifier_interface.hpp>
#include <nana/basic_types.hpp> #include <nana/basic_types.hpp>
#include <nana/system/platform.hpp> #include <nana/system/platform.hpp>
#include <nana/gui/effects.hpp> #include <nana/gui/effects.hpp>

View File

@ -11,16 +11,18 @@
*/ */
#include "../../detail/platform_spec_selector.hpp" #include "../../detail/platform_spec_selector.hpp"
#include "basic_window.hpp"
#include "bedrock_types.hpp" #include "bedrock_types.hpp"
#include <nana/gui/compact.hpp>
#include <nana/gui/widgets/widget.hpp>
#include <nana/gui/detail/event_code.hpp> #include <nana/gui/detail/event_code.hpp>
#include <nana/system/platform.hpp> #include <nana/system/platform.hpp>
#include <sstream>
#include <nana/system/timepiece.hpp> #include <nana/system/timepiece.hpp>
#include <nana/gui/wvl.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include <nana/gui/detail/native_window_interface.hpp> #include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp> #include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/element_store.hpp> #include <nana/gui/detail/element_store.hpp>
#include <sstream>
#include <algorithm> #include <algorithm>
namespace nana namespace nana
@ -64,11 +66,6 @@ namespace nana
namespace detail namespace detail
{ {
bool check_window(window wd)
{
return bedrock::instance().wd_manager().available(reinterpret_cast<window_manager::core_window_t*>(wd));
}
void events_operation_register(event_handle evt) void events_operation_register(event_handle evt)
{ {
bedrock::instance().evt_operation().register_evt(evt); bedrock::instance().evt_operation().register_evt(evt);
@ -77,7 +74,7 @@ namespace nana
class bedrock::flag_guard class bedrock::flag_guard
{ {
public: public:
flag_guard(bedrock* brock, core_window_t * wd) flag_guard(bedrock* brock, basic_window * wd)
: brock_{ brock }, wd_(wd) : brock_{ brock }, wd_(wd)
{ {
wd_->flags.refreshing = true; wd_->flags.refreshing = true;
@ -90,7 +87,7 @@ namespace nana
} }
private: private:
bedrock *const brock_; bedrock *const brock_;
core_window_t *const wd_; basic_window *const wd_;
}; };
//class root_guard //class root_guard
@ -111,7 +108,7 @@ namespace nana
} }
//end class root_guard //end class root_guard
bedrock::core_window_t* bedrock::focus() basic_window* bedrock::focus()
{ {
auto wd = wd_manager().root(native_interface::get_focus_window()); auto wd = wd_manager().root(native_interface::get_focus_window());
return (wd ? wd->other.attribute.root->focus : nullptr); return (wd ? wd->other.attribute.root->focus : nullptr);
@ -127,7 +124,7 @@ namespace nana
return pi_data_->wd_manager; return pi_data_->wd_manager;
} }
void bedrock::manage_form_loader(core_window_t* wd, bool insert_or_remove) void bedrock::manage_form_loader(basic_window* wd, bool insert_or_remove)
{ {
if (insert_or_remove) if (insert_or_remove)
{ {
@ -144,7 +141,7 @@ namespace nana
void bedrock::close_thread_window(thread_t thread_id) void bedrock::close_thread_window(thread_t thread_id)
{ {
std::vector<core_window_t*> v; std::vector<basic_window*> v;
wd_manager().all_handles(v); wd_manager().all_handles(v);
std::vector<native_window_type> roots; std::vector<native_window_type> roots;
@ -163,7 +160,7 @@ namespace nana
native_interface::close_window(i); native_interface::close_window(i);
} }
void bedrock::event_expose(core_window_t * wd, bool exposed) void bedrock::event_expose(basic_window * wd, bool exposed)
{ {
if (nullptr == wd) return; if (nullptr == wd) return;
@ -171,11 +168,11 @@ namespace nana
arg_expose arg; arg_expose arg;
arg.exposed = exposed; arg.exposed = exposed;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
if (emit(event_code::expose, wd, arg, false, get_thread_context())) if (emit(event_code::expose, wd, arg, false, get_thread_context()))
{ {
//Get the window who has the activated caret //Get the window who has the activated caret
const core_window_t * caret_wd = ((wd->annex.caret_ptr && wd->annex.caret_ptr->activated()) ? wd : wd->child_caret()); auto const caret_wd = ((wd->annex.caret_ptr && wd->annex.caret_ptr->activated()) ? wd : wd->child_caret());
if (caret_wd) if (caret_wd)
{ {
if (exposed) if (exposed)
@ -198,19 +195,19 @@ namespace nana
} }
} }
void bedrock::event_move(core_window_t* wd, int x, int y) void bedrock::event_move(basic_window* wd, int x, int y)
{ {
if (wd) if (wd)
{ {
arg_move arg; arg_move arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.x = x; arg.x = x;
arg.y = y; arg.y = y;
emit(event_code::move, wd, arg, true, get_thread_context()); emit(event_code::move, wd, arg, true, get_thread_context());
} }
} }
bool bedrock::event_msleave(core_window_t* hovered) bool bedrock::event_msleave(basic_window* hovered)
{ {
if (wd_manager().available(hovered) && hovered->flags.enabled) if (wd_manager().available(hovered) && hovered->flags.enabled)
{ {
@ -218,7 +215,7 @@ namespace nana
arg_mouse arg; arg_mouse arg;
arg.evt_code = event_code::mouse_leave; arg.evt_code = event_code::mouse_leave;
arg.window_handle = reinterpret_cast<window>(hovered); arg.window_handle = hovered;
arg.pos.x = arg.pos.y = 0; arg.pos.x = arg.pos.y = 0;
arg.left_button = arg.right_button = arg.mid_button = false; arg.left_button = arg.right_button = arg.mid_button = false;
arg.ctrl = arg.shift = false; arg.ctrl = arg.shift = false;
@ -229,12 +226,12 @@ namespace nana
} }
//The wd must be a root window //The wd must be a root window
void bedrock::event_focus_changed(core_window_t* root_wd, native_window_type receiver, bool getting) void bedrock::event_focus_changed(basic_window* root_wd, native_window_type receiver, bool getting)
{ {
auto focused = root_wd->other.attribute.root->focus; auto focused = root_wd->other.attribute.root->focus;
arg_focus arg; arg_focus arg;
arg.window_handle = reinterpret_cast<window>(focused); arg.window_handle = focused;
arg.getting = getting; arg.getting = getting;
arg.receiver = receiver; arg.receiver = receiver;
@ -260,7 +257,7 @@ namespace nana
} }
} }
void bedrock::update_cursor(core_window_t * wd) void bedrock::update_cursor(basic_window * wd)
{ {
internal_scope_guard isg; internal_scope_guard isg;
if (wd_manager().available(wd)) if (wd_manager().available(wd))
@ -282,7 +279,7 @@ namespace nana
} }
} }
void bedrock::set_menubar_taken(core_window_t* wd) void bedrock::set_menubar_taken(basic_window* wd)
{ {
auto pre = pi_data_->menu.taken_window; auto pre = pi_data_->menu.taken_window;
pi_data_->menu.taken_window = wd; pi_data_->menu.taken_window = wd;
@ -396,7 +393,7 @@ namespace nana
return pi_data_->scheme; return pi_data_->scheme;
} }
void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::event_arg& event_arg, const bool bForce__EmitInternal) void bedrock::_m_emit_core(event_code evt_code, basic_window* wd, bool draw_only, const ::nana::event_arg& event_arg, const bool bForce__EmitInternal)
{ {
auto retain = wd->annex.events_ptr; auto retain = wd->annex.events_ptr;
auto evts_ptr = retain.get(); auto evts_ptr = retain.get();
@ -416,7 +413,7 @@ namespace nana
wd->drawer.click(*arg, bForce__EmitInternal); wd->drawer.click(*arg, bForce__EmitInternal);
} }
if (bProcess__External_event) if (bProcess__External_event)
evts_ptr->click.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->click.emit(*arg, wd);
} }
} }
break; break;
@ -471,7 +468,7 @@ namespace nana
} }
if (bProcess__External_event) if (bProcess__External_event)
evt_addr->emit(*arg, reinterpret_cast<window>(wd)); evt_addr->emit(*arg, wd);
break; break;
} }
case event_code::mouse_wheel: case event_code::mouse_wheel:
@ -486,7 +483,7 @@ namespace nana
} }
if (bProcess__External_event) if (bProcess__External_event)
evts_ptr->mouse_wheel.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->mouse_wheel.emit(*arg, wd);
} }
break; break;
} }
@ -530,7 +527,7 @@ namespace nana
} }
if (bProcess__External_event) if (bProcess__External_event)
evt_addr->emit(*arg, reinterpret_cast<window>(wd)); evt_addr->emit(*arg, wd);
break; break;
} }
case event_code::expose: case event_code::expose:
@ -538,7 +535,7 @@ namespace nana
{ {
auto arg = dynamic_cast<const arg_expose*>(&event_arg); auto arg = dynamic_cast<const arg_expose*>(&event_arg);
if (arg) if (arg)
evts_ptr->expose.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->expose.emit(*arg, wd);
} }
break; break;
case event_code::focus: case event_code::focus:
@ -552,7 +549,7 @@ namespace nana
wd->drawer.focus(*arg, bForce__EmitInternal); wd->drawer.focus(*arg, bForce__EmitInternal);
} }
if (bProcess__External_event) if (bProcess__External_event)
evts_ptr->focus.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->focus.emit(*arg, wd);
} }
break; break;
} }
@ -567,7 +564,7 @@ namespace nana
wd->drawer.move(*arg, bForce__EmitInternal); wd->drawer.move(*arg, bForce__EmitInternal);
} }
if (bProcess__External_event) if (bProcess__External_event)
evts_ptr->move.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->move.emit(*arg, wd);
} }
break; break;
} }
@ -582,7 +579,7 @@ namespace nana
wd->drawer.resizing(*arg, bForce__EmitInternal); wd->drawer.resizing(*arg, bForce__EmitInternal);
} }
if (bProcess__External_event) if (bProcess__External_event)
evts_ptr->resizing.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->resizing.emit(*arg, wd);
} }
break; break;
} }
@ -597,7 +594,7 @@ namespace nana
wd->drawer.resized(*arg, bForce__EmitInternal); wd->drawer.resized(*arg, bForce__EmitInternal);
} }
if (bProcess__External_event) if (bProcess__External_event)
evts_ptr->resized.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->resized.emit(*arg, wd);
} }
break; break;
} }
@ -609,7 +606,7 @@ namespace nana
{ {
auto evt_root = dynamic_cast<events_root_extension*>(evts_ptr); auto evt_root = dynamic_cast<events_root_extension*>(evts_ptr);
if (evt_root) if (evt_root)
evt_root->unload.emit(*arg, reinterpret_cast<window>(wd)); evt_root->unload.emit(*arg, wd);
} }
} }
break; break;
@ -618,7 +615,7 @@ namespace nana
{ {
auto arg = dynamic_cast<const arg_destroy*>(&event_arg); auto arg = dynamic_cast<const arg_destroy*>(&event_arg);
if (arg) if (arg)
evts_ptr->destroy.emit(*arg, reinterpret_cast<window>(wd)); evts_ptr->destroy.emit(*arg, wd);
} }
break; break;
default: default:
@ -626,7 +623,7 @@ namespace nana
} }
} }
void bedrock::thread_context_destroy(core_window_t * wd) void bedrock::thread_context_destroy(basic_window * wd)
{ {
auto ctx = get_thread_context(0); auto ctx = get_thread_context(0);
if(ctx && ctx->event_window == wd) if(ctx && ctx->event_window == wd)
@ -637,15 +634,15 @@ namespace nana
{ {
auto ctx = get_thread_context(0); auto ctx = get_thread_context(0);
if(ctx && ctx->event_window) if(ctx && ctx->event_window)
ctx->event_window->other.upd_state = core_window_t::update_state::refreshed; ctx->event_window->other.upd_state = basic_window::update_state::refreshed;
} }
bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal) bool bedrock::emit(event_code evt_code, basic_window* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal)
{ {
if(wd_manager().available(wd) == false) if(wd_manager().available(wd) == false)
return false; return false;
core_window_t * prev_wd = nullptr; basic_window * prev_wd = nullptr;
if(thrd) if(thrd)
{ {
prev_wd = thrd->event_window; prev_wd = thrd->event_window;
@ -680,7 +677,7 @@ namespace nana
return good_wd; return good_wd;
} }
void bedrock::_m_event_filter(event_code event_id, core_window_t * wd, thread_context * thrd) void bedrock::_m_event_filter(event_code event_id, basic_window * wd, thread_context * thrd)
{ {
auto not_state_cur = (wd->root_widget->other.attribute.root->state_cursor == nana::cursor::arrow); auto not_state_cur = (wd->root_widget->other.attribute.root->state_cursor == nana::cursor::arrow);

View File

@ -141,9 +141,9 @@ namespace detail
delete impl_; delete impl_;
} }
void bedrock::flush_surface(core_window_t* wd, bool forced, const rectangle* update_area) void bedrock::flush_surface(basic_window* wd, bool forced, const rectangle* update_area)
{ {
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area); wd->drawer.map(wd, forced, update_area);
} }
//inc_window //inc_window
@ -248,14 +248,14 @@ namespace detail
return impl_->estore; return impl_->estore;
} }
void bedrock::map_through_widgets(core_window_t*, native_drawable_type) void bedrock::map_through_widgets(basic_window*, native_drawable_type)
{ {
//No implementation for Linux //No implementation for Linux
} }
void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt) void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt)
{ {
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.button = ::nana::mouse::any_button; arg.button = ::nana::mouse::any_button;
int mask_state = 0; int mask_state = 0;
@ -308,7 +308,7 @@ namespace detail
void assign_arg(arg_focus& arg, basic_window* wd, native_window_type recv, bool getting) void assign_arg(arg_focus& arg, basic_window* wd, native_window_type recv, bool getting)
{ {
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.receiver = recv; arg.receiver = recv;
arg.getting = getting; arg.getting = getting;
arg.focus_reason = arg_focus::reason::general; arg.focus_reason = arg_focus::reason::general;
@ -317,7 +317,7 @@ namespace detail
void assign_arg(arg_wheel& arg, basic_window* wd, const XEvent& evt) void assign_arg(arg_wheel& arg, basic_window* wd, const XEvent& evt)
{ {
arg.evt_code = event_code::mouse_wheel; arg.evt_code = event_code::mouse_wheel;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
if (ButtonRelease == evt.type && (evt.xbutton.button == Button4 || evt.xbutton.button == Button5)) if (ButtonRelease == evt.type && (evt.xbutton.button == Button4 || evt.xbutton.button == Button5))
{ {
arg.evt_code = event_code::mouse_wheel; arg.evt_code = event_code::mouse_wheel;
@ -371,12 +371,12 @@ namespace detail
if(msgwd) if(msgwd)
{ {
arg_dropfiles arg; arg_dropfiles arg;
arg.window_handle = reinterpret_cast<window>(msgwd); arg.window_handle = msgwd;
arg.files.swap(*msg.u.mouse_drop.files); arg.files.swap(*msg.u.mouse_drop.files);
delete msg.u.mouse_drop.files; delete msg.u.mouse_drop.files;
arg.pos.x = msg.u.mouse_drop.x - msgwd->pos_root.x; arg.pos.x = msg.u.mouse_drop.x - msgwd->pos_root.x;
arg.pos.y = msg.u.mouse_drop.y - msgwd->pos_root.y; arg.pos.y = msg.u.mouse_drop.y - msgwd->pos_root.y;
msgwd->annex.events_ptr->mouse_dropfiles.emit(arg, reinterpret_cast<window>(msgwd)); msgwd->annex.events_ptr->mouse_dropfiles.emit(arg, msgwd);
brock.wd_manager().do_lazy_refresh(msgwd, false); brock.wd_manager().do_lazy_refresh(msgwd, false);
} }
break; break;
@ -512,11 +512,9 @@ namespace detail
auto const native_window = rruntime->window->root; auto const native_window = rruntime->window->root;
auto wstr = nana::to_wstring(std::string{keybuf, keybuf + keybuf_len});
nana::detail::charset_conv charset(NANA_UNICODE, "UTF-8"); auto const charbuf = wstr.c_str();
const std::string& str = charset.charset(std::string(keybuf, keybuf + keybuf_len)); auto const len = wstr.length();
auto const charbuf = reinterpret_cast<const wchar_t*>(str.c_str());
auto const len = str.size() / sizeof(wchar_t);
for(std::size_t i = 0; i < len; ++i) for(std::size_t i = 0; i < len; ++i)
{ {
@ -539,15 +537,15 @@ namespace detail
auto shr_wd = wd_manager.find_shortkey(native_window, arg.key); auto shr_wd = wd_manager.find_shortkey(native_window, arg.key);
if(shr_wd) if(shr_wd)
{ {
arg.window_handle = reinterpret_cast<window>(shr_wd); arg.window_handle = shr_wd;
brock.emit(event_code::shortkey, shr_wd, arg, true, &context); brock.emit(event_code::shortkey, shr_wd, arg, true, &context);
} }
continue; continue;
} }
arg.evt_code = event_code::key_char; arg.evt_code = event_code::key_char;
arg.window_handle = reinterpret_cast<window>(msgwd); arg.window_handle = msgwd;
msgwd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwd)); msgwd->annex.events_ptr->key_char.emit(arg, msgwd);
if(arg.ignore == false && wd_manager.available(msgwd)) if(arg.ignore == false && wd_manager.available(msgwd))
draw_invoker(&drawer::key_char, msgwd, arg, &context); draw_invoker(&drawer::key_char, msgwd, arg, &context);
} }
@ -556,36 +554,11 @@ namespace detail
context.is_alt_pressed = false; context.is_alt_pressed = false;
} }
#if 0
class window_proc_guard
{
public:
window_proc_guard(detail::basic_window* wd) :
root_wd_(wd)
{
root_wd_->other.attribute.root->lazy_update = true;
}
~window_proc_guard()
{
if (!bedrock::instance().wd_manager().available(root_wd_))
return;
root_wd_->other.attribute.root->lazy_update = false;
root_wd_->other.attribute.root->update_requesters.clear();
}
private:
detail::basic_window* const root_wd_;
};
#endif
void window_proc_for_xevent(Display* /*display*/, XEvent& xevent) void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
{ {
typedef detail::bedrock::core_window_t core_window_t;
static auto& brock = detail::bedrock::instance(); static auto& brock = detail::bedrock::instance();
static unsigned long last_mouse_down_time; static unsigned long last_mouse_down_time;
static core_window_t* last_mouse_down_window; static basic_window* last_mouse_down_window;
auto native_window = reinterpret_cast<native_window_type>(event_window(xevent)); auto native_window = reinterpret_cast<native_window_type>(event_window(xevent));
auto & wd_manager = brock.wd_manager(); auto & wd_manager = brock.wd_manager();
@ -789,7 +762,7 @@ namespace detail
{ {
msgwnd->set_action(mouse_action::hovered); msgwnd->set_action(mouse_action::hovered);
click_arg.window_handle = reinterpret_cast<window>(msgwnd); click_arg.window_handle = msgwnd;
draw_invoker(&drawer::click, msgwnd, click_arg, &context); draw_invoker(&drawer::click, msgwnd, click_arg, &context);
} }
} }
@ -807,16 +780,16 @@ namespace detail
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
if(click_arg.window_handle) if(click_arg.window_handle)
evt_ptr->click.emit(click_arg, reinterpret_cast<window>(msgwnd)); evt_ptr->click.emit(click_arg, msgwnd);
if (wd_manager.available(msgwnd)) if (wd_manager.available(msgwnd))
{ {
arg.evt_code = event_code::mouse_up; arg.evt_code = event_code::mouse_up;
evt_ptr->mouse_up.emit(arg, reinterpret_cast<window>(msgwnd)); evt_ptr->mouse_up.emit(arg, msgwnd);
} }
} }
else if(click_arg.window_handle) else if(click_arg.window_handle)
msgwnd->annex.events_ptr->click.emit(click_arg, reinterpret_cast<window>(msgwnd)); msgwnd->annex.events_ptr->click.emit(click_arg, msgwnd);
wd_manager.do_lazy_refresh(msgwnd, false); wd_manager.do_lazy_refresh(msgwnd, false);
} }
@ -940,7 +913,7 @@ namespace detail
//Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. //Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed.
::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); ::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height);
if (!update_area.empty()) if (!update_area.empty())
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area); msgwnd->drawer.map(msgwnd, true, &update_area);
} }
} }
break; break;
@ -1019,7 +992,7 @@ namespace detail
else if((keyboard::space == os_code) && msgwnd->flags.space_click_enabled) else if((keyboard::space == os_code) && msgwnd->flags.space_click_enabled)
{ {
//Clicked by spacebar //Clicked by spacebar
if((nullptr == pressed_wd) && (nullptr == pressed_wd_space)) if((nullptr == pressed_wd) && (nullptr == pressed_wd_space) && msgwnd->flags.enabled)
{ {
arg_mouse arg; arg_mouse arg;
arg.alt = modifiers_status.alt; arg.alt = modifiers_status.alt;
@ -1030,7 +1003,7 @@ namespace detail
arg.mid_button = false; arg.mid_button = false;
arg.pos.x = 0; arg.pos.x = 0;
arg.pos.y = 0; arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
msgwnd->set_action(mouse_action::pressed); msgwnd->set_action(mouse_action::pressed);
@ -1052,7 +1025,7 @@ namespace detail
bool focused = (brock.focus() == msgwnd); bool focused = (brock.focus() == msgwnd);
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_press; arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
arg.key = os_code; arg.key = os_code;
brock.get_key_state(arg); brock.get_key_state(arg);
@ -1074,7 +1047,7 @@ namespace detail
arg.ignore = false; arg.ignore = false;
arg.key = os_code; arg.key = os_code;
arg.evt_code = event_code::key_press; arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
brock.emit(event_code::key_press, msgwnd, arg, true, &context); brock.emit(event_code::key_press, msgwnd, arg, true, &context);
@ -1122,7 +1095,7 @@ namespace detail
msgwnd = brock.focus(); msgwnd = brock.focus();
if(msgwnd) if(msgwnd)
{ {
if(msgwnd == pressed_wd_space) if((msgwnd == pressed_wd_space) && msgwnd->flags.enabled)
{ {
msgwnd->set_action(mouse_action::normal); msgwnd->set_action(mouse_action::normal);
@ -1130,7 +1103,7 @@ namespace detail
arg_click click_arg; arg_click click_arg;
click_arg.mouse_args = nullptr; click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd); click_arg.window_handle = msgwnd;
arg_mouse arg; arg_mouse arg;
arg.alt = false; arg.alt = false;
@ -1141,7 +1114,7 @@ namespace detail
arg.mid_button = false; arg.mid_button = false;
arg.pos.x = 0; arg.pos.x = 0;
arg.pos.y = 0; arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
@ -1155,7 +1128,7 @@ namespace detail
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_release; arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
arg.key = os_code; arg.key = os_code;
brock.get_key_state(arg); brock.get_key_state(arg);
@ -1181,7 +1154,7 @@ namespace detail
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_release; arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
arg.key = os_code; arg.key = os_code;
brock.get_key_state(arg); brock.get_key_state(arg);
@ -1208,7 +1181,7 @@ namespace detail
if(msgwnd->flags.enabled && (atoms.wm_delete_window == static_cast<Atom>(xclient.data.l[0]))) if(msgwnd->flags.enabled && (atoms.wm_delete_window == static_cast<Atom>(xclient.data.l[0])))
{ {
arg_unload arg; arg_unload arg;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.cancel = false; arg.cancel = false;
brock.emit(event_code::unload, msgwnd, arg, true, &context); brock.emit(event_code::unload, msgwnd, arg, true, &context);
if(false == arg.cancel) if(false == arg.cancel)
@ -1259,10 +1232,10 @@ namespace detail
lock.revert(); lock.revert();
native_window_type owner_native{}; native_window_type owner_native{};
core_window_t * owner = 0; basic_window * owner = nullptr;
if(condition_wd && is_modal) if(condition_wd && is_modal)
{ {
native_window_type modal = reinterpret_cast<core_window_t*>(condition_wd)->root; native_window_type modal = condition_wd->root;
owner_native = native_interface::get_window(modal, window_relationship::owner); owner_native = native_interface::get_window(modal, window_relationship::owner);
if(owner_native) if(owner_native)
{ {
@ -1273,7 +1246,7 @@ namespace detail
} }
} }
nana::detail::platform_spec::instance().msg_dispatch(condition_wd ? reinterpret_cast<core_window_t*>(condition_wd)->root : 0); nana::detail::platform_spec::instance().msg_dispatch(condition_wd ? condition_wd->root : 0);
if(owner_native) if(owner_native)
{ {
@ -1301,7 +1274,7 @@ namespace detail
}//end bedrock::event_loop }//end bedrock::event_loop
//Dynamically set a cursor for a window //Dynamically set a cursor for a window
void bedrock::set_cursor(core_window_t* wd, nana::cursor cur, thread_context* thrd) void bedrock::set_cursor(basic_window* wd, nana::cursor cur, thread_context* thrd)
{ {
if (nullptr == thrd) if (nullptr == thrd)
thrd = get_thread_context(wd->thread_id); thrd = get_thread_context(wd->thread_id);
@ -1344,14 +1317,14 @@ namespace detail
} }
} }
void bedrock::define_state_cursor(core_window_t* wd, nana::cursor cur, thread_context* thrd) void bedrock::define_state_cursor(basic_window* wd, nana::cursor cur, thread_context* thrd)
{ {
wd->root_widget->other.attribute.root->state_cursor = cur; wd->root_widget->other.attribute.root->state_cursor = cur;
wd->root_widget->other.attribute.root->state_cursor_window = wd; wd->root_widget->other.attribute.root->state_cursor_window = wd;
set_cursor(wd, cur, thrd); set_cursor(wd, cur, thrd);
} }
void bedrock::undefine_state_cursor(core_window_t * wd, thread_context* thrd) void bedrock::undefine_state_cursor(basic_window * wd, thread_context* thrd)
{ {
if (!wd_manager().available(wd)) if (!wd_manager().available(wd))
return; return;

View File

@ -18,12 +18,12 @@ namespace nana
color_schemes scheme; color_schemes scheme;
events_operation evt_operation; events_operation evt_operation;
window_manager wd_manager; window_manager wd_manager;
std::set<core_window_t*> auto_form_set; std::set<basic_window*> auto_form_set;
bool shortkey_occurred{ false }; bool shortkey_occurred{ false };
struct menu_rep struct menu_rep
{ {
core_window_t* taken_window{ nullptr }; basic_window* taken_window{ nullptr };
bool delay_restore{ false }; bool delay_restore{ false };
native_window_type window{ nullptr }; native_window_type window{ nullptr };
native_window_type owner{ nullptr }; native_window_type owner{ nullptr };
@ -37,7 +37,7 @@ namespace nana
{ {
unsigned event_pump_ref_count{0}; unsigned event_pump_ref_count{0};
int window_count{0}; //The number of windows int window_count{0}; //The number of windows
core_window_t* event_window{nullptr}; basic_window* event_window{nullptr};
struct platform_detail_tag struct platform_detail_tag
{ {
@ -46,7 +46,7 @@ namespace nana
struct cursor_tag struct cursor_tag
{ {
core_window_t * window; basic_window * window;
native_window_type native_handle; native_window_type native_handle;
nana::cursor predef_cursor; nana::cursor predef_cursor;
HCURSOR handle; HCURSOR handle;
@ -66,7 +66,7 @@ namespace nana
unsigned event_pump_ref_count{0}; unsigned event_pump_ref_count{0};
int window_count{0}; //The number of windows int window_count{0}; //The number of windows
core_window_t* event_window{nullptr}; basic_window* event_window{nullptr};
bool is_alt_pressed{false}; bool is_alt_pressed{false};
bool is_ctrl_pressed{false}; bool is_ctrl_pressed{false};
@ -78,7 +78,7 @@ namespace nana
struct cursor_tag struct cursor_tag
{ {
core_window_t * window; basic_window * window;
native_window_type native_handle; native_window_type native_handle;
nana::cursor predef_cursor; nana::cursor predef_cursor;
Cursor handle; Cursor handle;

View File

@ -18,7 +18,8 @@
#include <nana/gui/detail/event_code.hpp> #include <nana/gui/detail/event_code.hpp>
#include <nana/system/platform.hpp> #include <nana/system/platform.hpp>
#include <nana/system/timepiece.hpp> #include <nana/system/timepiece.hpp>
#include <nana/gui.hpp> #include <nana/gui/compact.hpp>
#include <nana/gui/msgbox.hpp>
#include <nana/gui/detail/native_window_interface.hpp> #include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp> #include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/window_layout.hpp> #include <nana/gui/detail/window_layout.hpp>
@ -213,9 +214,9 @@ namespace detail
bedrock::~bedrock() bedrock::~bedrock()
{ {
if(wd_manager().number_of_core_window()) if(wd_manager().window_count())
{ {
std::string msg = "Nana.GUI detects a memory leaks in window_manager, " + std::to_string(wd_manager().number_of_core_window()) + " window(s) are not uninstalled."; std::string msg = "Nana.GUI detects a memory leaks in window_manager, " + std::to_string(wd_manager().window_count()) + " window(s) are not uninstalled.";
std::cerr << msg; /// \todo add list of cations of opening windows and if auto testing GUI do auto OK after 2 seconds. std::cerr << msg; /// \todo add list of cations of opening windows and if auto testing GUI do auto OK after 2 seconds.
::MessageBoxA(0, msg.c_str(), ("Nana C++ Library"), MB_OK); ::MessageBoxA(0, msg.c_str(), ("Nana C++ Library"), MB_OK);
} }
@ -290,7 +291,7 @@ namespace detail
return bedrock_object; return bedrock_object;
} }
void bedrock::flush_surface(core_window_t* wd, bool forced, const rectangle* update_area) void bedrock::flush_surface(basic_window* wd, bool forced, const rectangle* update_area)
{ {
if (nana::system::this_thread_id() != wd->thread_id) if (nana::system::this_thread_id() != wd->thread_id)
{ {
@ -311,7 +312,7 @@ namespace detail
} }
} }
else else
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area); wd->drawer.map(wd, forced, update_area);
} }
void interior_helper_for_menu(MSG& msg, native_window_type menu_window) void interior_helper_for_menu(MSG& msg, native_window_type menu_window)
@ -367,7 +368,7 @@ namespace detail
MSG msg; MSG msg;
if (condition_wd) if (condition_wd)
{ {
HWND native_handle = reinterpret_cast<HWND>(reinterpret_cast<core_window_t*>(condition_wd)->root); HWND native_handle = reinterpret_cast<HWND>(condition_wd->root);
if (is_modal) if (is_modal)
{ {
HWND owner = ::GetWindow(native_handle, GW_OWNER); HWND owner = ::GetWindow(native_handle, GW_OWNER);
@ -466,7 +467,7 @@ namespace detail
void assign_arg(nana::arg_mouse& arg, basic_window* wd, unsigned msg, const parameter_decoder& pmdec) void assign_arg(nana::arg_mouse& arg, basic_window* wd, unsigned msg, const parameter_decoder& pmdec)
{ {
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
bool set_key_state = true; bool set_key_state = true;
switch (msg) switch (msg)
@ -530,7 +531,7 @@ namespace detail
void assign_arg(arg_wheel& arg, basic_window* wd, const parameter_decoder& pmdec) void assign_arg(arg_wheel& arg, basic_window* wd, const parameter_decoder& pmdec)
{ {
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.evt_code = event_code::mouse_wheel; arg.evt_code = event_code::mouse_wheel;
POINT point = { pmdec.mouse.x, pmdec.mouse.y }; POINT point = { pmdec.mouse.x, pmdec.mouse.y };
@ -581,7 +582,7 @@ namespace detail
case nana::detail::messages::remote_flush_surface: case nana::detail::messages::remote_flush_surface:
{ {
auto stru = reinterpret_cast<detail::messages::map_thread*>(lParam); auto stru = reinterpret_cast<detail::messages::map_thread*>(lParam);
bedrock.wd_manager().map(reinterpret_cast<bedrock::core_window_t*>(wParam), stru->forced, (stru->ignore_update_area ? nullptr : &stru->update_area)); bedrock.wd_manager().map(reinterpret_cast<basic_window*>(wParam), stru->forced, (stru->ignore_update_area ? nullptr : &stru->update_area));
::UpdateWindow(wd); ::UpdateWindow(wd);
::HeapFree(::GetProcessHeap(), 0, stru); ::HeapFree(::GetProcessHeap(), 0, stru);
} }
@ -652,7 +653,7 @@ namespace detail
return true; return true;
} }
void adjust_sizing(bedrock::core_window_t* wd, ::RECT * const r, int edge, unsigned req_width, unsigned req_height) void adjust_sizing(basic_window* wd, ::RECT * const r, int edge, unsigned req_width, unsigned req_height)
{ {
unsigned width = static_cast<unsigned>(r->right - r->left) - wd->extra_width; unsigned width = static_cast<unsigned>(r->right - r->left) - wd->extra_width;
unsigned height = static_cast<unsigned>(r->bottom - r->top) - wd->extra_height; unsigned height = static_cast<unsigned>(r->bottom - r->top) - wd->extra_height;
@ -985,7 +986,7 @@ namespace detail
msgwnd->set_action(mouse_action::hovered); msgwnd->set_action(mouse_action::hovered);
if ((::nana::mouse::left_button == arg.button) && (pressed_wd == msgwnd)) if ((::nana::mouse::left_button == arg.button) && (pressed_wd == msgwnd))
{ {
click_arg.window_handle = reinterpret_cast<window>(msgwnd); click_arg.window_handle = msgwnd;
draw_invoker(&drawer::click, msgwnd, click_arg, &context); draw_invoker(&drawer::click, msgwnd, click_arg, &context);
} }
} }
@ -997,16 +998,16 @@ namespace detail
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
if (click_arg.window_handle) if (click_arg.window_handle)
retain->click.emit(click_arg, reinterpret_cast<window>(msgwnd)); retain->click.emit(click_arg, msgwnd);
if (wd_manager.available(msgwnd)) if (wd_manager.available(msgwnd))
{ {
arg.evt_code = event_code::mouse_up; arg.evt_code = event_code::mouse_up;
retain->mouse_up.emit(arg, reinterpret_cast<window>(msgwnd)); retain->mouse_up.emit(arg, msgwnd);
} }
} }
else if (click_arg.window_handle) else if (click_arg.window_handle)
retain->click.emit(click_arg, reinterpret_cast<window>(msgwnd)); retain->click.emit(click_arg, msgwnd);
wd_manager.do_lazy_refresh(msgwnd, false); wd_manager.do_lazy_refresh(msgwnd, false);
} }
@ -1176,9 +1177,9 @@ namespace detail
dropfiles.pos = pos; dropfiles.pos = pos;
wd_manager.calc_window_point(msgwnd, dropfiles.pos); wd_manager.calc_window_point(msgwnd, dropfiles.pos);
dropfiles.window_handle = reinterpret_cast<window>(msgwnd); dropfiles.window_handle = msgwnd;
msgwnd->annex.events_ptr->mouse_dropfiles.emit(dropfiles, reinterpret_cast<window>(msgwnd)); msgwnd->annex.events_ptr->mouse_dropfiles.emit(dropfiles, msgwnd);
wd_manager.do_lazy_refresh(msgwnd, false); wd_manager.do_lazy_refresh(msgwnd, false);
} }
} }
@ -1232,7 +1233,7 @@ namespace detail
static_cast<unsigned>(r->bottom - r->top - msgwnd->extra_height)); static_cast<unsigned>(r->bottom - r->top - msgwnd->extra_height));
arg_resizing arg; arg_resizing arg;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.width = size_before.width; arg.width = size_before.width;
arg.height = size_before.height; arg.height = size_before.height;
@ -1285,7 +1286,7 @@ namespace detail
//Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. //Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed.
::nana::rectangle update_area(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); ::nana::rectangle update_area(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
if (!update_area.empty()) if (!update_area.empty())
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area); msgwnd->drawer.map(msgwnd, true, &update_area);
} }
::EndPaint(root_window, &ps); ::EndPaint(root_window, &ps);
} }
@ -1300,7 +1301,7 @@ namespace detail
arg.evt_code = event_code::shortkey; arg.evt_code = event_code::shortkey;
arg.key = static_cast<wchar_t>(wParam < 0x61 ? wParam + 0x61 - 0x41 : wParam); arg.key = static_cast<wchar_t>(wParam < 0x61 ? wParam + 0x61 - 0x41 : wParam);
arg.ctrl = arg.shift = false; arg.ctrl = arg.shift = false;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
brock.emit(event_code::shortkey, msgwnd, arg, true, &context); brock.emit(event_code::shortkey, msgwnd, arg, true, &context);
def_window_proc = false; def_window_proc = false;
@ -1316,7 +1317,7 @@ namespace detail
bool focused = (brock.focus() == msgwnd); bool focused = (brock.focus() == msgwnd);
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_press; arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
arg.key = static_cast<wchar_t>(wParam); arg.key = static_cast<wchar_t>(wParam);
brock.get_key_state(arg); brock.get_key_state(arg);
@ -1344,7 +1345,7 @@ namespace detail
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_release; arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
arg.key = static_cast<wchar_t>(wParam); arg.key = static_cast<wchar_t>(wParam);
brock.get_key_state(arg); brock.get_key_state(arg);
@ -1386,7 +1387,7 @@ namespace detail
else if ((VK_SPACE == wParam) && msgwnd->flags.space_click_enabled) else if ((VK_SPACE == wParam) && msgwnd->flags.space_click_enabled)
{ {
//Clicked by spacebar //Clicked by spacebar
if (nullptr == pressed_wd && nullptr == pressed_wd_space) if ((nullptr == pressed_wd) && (nullptr == pressed_wd_space) && msgwnd->flags.enabled)
{ {
arg_mouse arg; arg_mouse arg;
arg.alt = false; arg.alt = false;
@ -1397,7 +1398,7 @@ namespace detail
arg.mid_button = false; arg.mid_button = false;
arg.pos.x = 0; arg.pos.x = 0;
arg.pos.y = 0; arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
msgwnd->set_action(mouse_action::pressed); msgwnd->set_action(mouse_action::pressed);
@ -1412,7 +1413,7 @@ namespace detail
{ {
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_press; arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.ignore = false; arg.ignore = false;
arg.key = translate_virtual_key(wParam); arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg); brock.get_key_state(arg);
@ -1443,12 +1444,12 @@ namespace detail
{ {
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_char; arg.evt_code = event_code::key_char;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.key = static_cast<wchar_t>(wParam); arg.key = static_cast<wchar_t>(wParam);
brock.get_key_state(arg); brock.get_key_state(arg);
arg.ignore = false; arg.ignore = false;
msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwnd)); msgwnd->annex.events_ptr->key_char.emit(arg, msgwnd);
if ((false == arg.ignore) && wd_manager.available(msgwnd)) if ((false == arg.ignore) && wd_manager.available(msgwnd))
draw_invoker(&drawer::key_char, msgwnd, arg, &context); draw_invoker(&drawer::key_char, msgwnd, arg, &context);
@ -1468,7 +1469,7 @@ namespace detail
msgwnd = brock.focus(); msgwnd = brock.focus();
if (msgwnd) if (msgwnd)
{ {
if (msgwnd == pressed_wd_space) if ((msgwnd == pressed_wd_space) && msgwnd->flags.enabled)
{ {
msgwnd->set_action(mouse_action::normal); msgwnd->set_action(mouse_action::normal);
@ -1476,7 +1477,7 @@ namespace detail
arg_click click_arg; arg_click click_arg;
click_arg.mouse_args = nullptr; click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd); click_arg.window_handle = msgwnd;
arg_mouse arg; arg_mouse arg;
arg.alt = false; arg.alt = false;
@ -1487,7 +1488,7 @@ namespace detail
arg.mid_button = false; arg.mid_button = false;
arg.pos.x = 0; arg.pos.x = 0;
arg.pos.y = 0; arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
@ -1500,7 +1501,7 @@ namespace detail
{ {
arg_keyboard keyboard_arg; arg_keyboard keyboard_arg;
keyboard_arg.evt_code = event_code::key_release; keyboard_arg.evt_code = event_code::key_release;
keyboard_arg.window_handle = reinterpret_cast<window>(msgwnd); keyboard_arg.window_handle = msgwnd;
keyboard_arg.key = translate_virtual_key(wParam); keyboard_arg.key = translate_virtual_key(wParam);
brock.get_key_state(keyboard_arg); brock.get_key_state(keyboard_arg);
keyboard_arg.ignore = false; keyboard_arg.ignore = false;
@ -1521,7 +1522,7 @@ namespace detail
case WM_CLOSE: case WM_CLOSE:
{ {
arg_unload arg; arg_unload arg;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = msgwnd;
arg.cancel = false; arg.cancel = false;
brock.emit(event_code::unload, msgwnd, arg, true, &context); brock.emit(event_code::unload, msgwnd, arg, true, &context);
if (!arg.cancel) if (!arg.cancel)
@ -1638,7 +1639,7 @@ namespace detail
return impl_->estore; return impl_->estore;
} }
void bedrock::map_through_widgets(core_window_t* wd, native_drawable_type drawable) void bedrock::map_through_widgets(basic_window* wd, native_drawable_type drawable)
{ {
auto graph_context = reinterpret_cast<HDC>(wd->root_graph->handle()->context); auto graph_context = reinterpret_cast<HDC>(wd->root_graph->handle()->context);
@ -1685,7 +1686,7 @@ namespace detail
} }
//Dynamically set a cursor for a window //Dynamically set a cursor for a window
void bedrock::set_cursor(core_window_t* wd, nana::cursor cur, thread_context* thrd) void bedrock::set_cursor(basic_window* wd, nana::cursor cur, thread_context* thrd)
{ {
if (nullptr == thrd) if (nullptr == thrd)
thrd = get_thread_context(wd->thread_id); thrd = get_thread_context(wd->thread_id);
@ -1730,7 +1731,7 @@ namespace detail
} }
} }
void bedrock::define_state_cursor(core_window_t* wd, nana::cursor cur, thread_context* thrd) void bedrock::define_state_cursor(basic_window* wd, nana::cursor cur, thread_context* thrd)
{ {
wd->root_widget->other.attribute.root->state_cursor = cur; wd->root_widget->other.attribute.root->state_cursor = cur;
wd->root_widget->other.attribute.root->state_cursor_window = wd; wd->root_widget->other.attribute.root->state_cursor_window = wd;
@ -1740,11 +1741,8 @@ namespace detail
::ShowCursor(TRUE); ::ShowCursor(TRUE);
} }
void bedrock::undefine_state_cursor(core_window_t * wd, thread_context* thrd) void bedrock::undefine_state_cursor(basic_window * wd, thread_context* thrd)
{ {
if (nullptr == thrd)
thrd = get_thread_context(wd->thread_id);
HCURSOR rev_handle = ::LoadCursor(nullptr, IDC_ARROW); HCURSOR rev_handle = ::LoadCursor(nullptr, IDC_ARROW);
if (!wd_manager().available(wd)) if (!wd_manager().available(wd))
{ {
@ -1753,6 +1751,9 @@ namespace detail
return; return;
} }
if (nullptr == thrd)
thrd = get_thread_context(wd->thread_id);
wd->root_widget->other.attribute.root->state_cursor = nana::cursor::arrow; wd->root_widget->other.attribute.root->state_cursor = nana::cursor::arrow;
wd->root_widget->other.attribute.root->state_cursor_window = nullptr; wd->root_widget->other.attribute.root->state_cursor_window = nullptr;

View File

@ -1,7 +1,7 @@
/* /*
* A Drawer Implementation * A Drawer Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -10,11 +10,11 @@
* @file: nana/gui/detail/drawer.cpp * @file: nana/gui/detail/drawer.cpp
*/ */
#include "basic_window.hpp"
#include "effects_renderer.hpp"
#include <nana/config.hpp> #include <nana/config.hpp>
#include <nana/gui/detail/bedrock.hpp> #include <nana/gui/detail/bedrock.hpp>
#include <nana/gui/detail/drawer.hpp> #include <nana/gui/detail/drawer.hpp>
#include <nana/gui/detail/effects_renderer.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include "dynamic_drawing_object.hpp" #include "dynamic_drawing_object.hpp"
#if defined(NANA_X11) #if defined(NANA_X11)
@ -23,8 +23,6 @@
namespace nana namespace nana
{ {
typedef detail::edge_nimbus_renderer<detail::bedrock::core_window_t> edge_nimbus_renderer_t;
//class drawer_trigger //class drawer_trigger
void drawer_trigger::attached(widget_reference, graph_reference){} void drawer_trigger::attached(widget_reference, graph_reference){}
void drawer_trigger::detached(){} //none-const void drawer_trigger::detached(){} //none-const
@ -344,8 +342,7 @@ namespace nana
{ {
if(wd) if(wd)
{ {
auto iwd = reinterpret_cast<bedrock_type::core_window_t*>(wd); bool owns_caret = (wd->annex.caret_ptr) && (wd->annex.caret_ptr->visible());
bool owns_caret = (iwd->annex.caret_ptr) && (iwd->annex.caret_ptr->visible());
//The caret in X11 is implemented by Nana, it is different from Windows' //The caret in X11 is implemented by Nana, it is different from Windows'
//the caret in X11 is asynchronous, it is hard to hide and show the caret //the caret in X11 is asynchronous, it is hard to hide and show the caret
@ -354,20 +351,20 @@ namespace nana
if(owns_caret) if(owns_caret)
{ {
#ifndef NANA_X11 #ifndef NANA_X11
iwd->annex.caret_ptr->visible(false); wd->annex.caret_ptr->visible(false);
#else #else
owns_caret = nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, false); owns_caret = nana::detail::platform_spec::instance().caret_update(wd->root, *wd->root_graph, false);
#endif #endif
} }
edge_nimbus_renderer_t::instance().render(iwd, forced, update_area); edge_nimbus_renderer::instance().render(wd, forced, update_area);
if(owns_caret) if(owns_caret)
{ {
#ifndef NANA_X11 #ifndef NANA_X11
iwd->annex.caret_ptr->visible(true); wd->annex.caret_ptr->visible(true);
#else #else
nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, true); nana::detail::platform_spec::instance().caret_update(wd->root, *wd->root_graph, true);
#endif #endif
} }
} }
@ -475,4 +472,192 @@ namespace nana
return data_impl_->mth_state[pos]; return data_impl_->mth_state[pos];
} }
}//end namespace detail }//end namespace detail
namespace detail
{
//class edge_nimbus_renderer
edge_nimbus_renderer& edge_nimbus_renderer::instance()
{
static edge_nimbus_renderer object;
return object;
}
void edge_nimbus_renderer::erase(basic_window* wd)
{
if (effects::edge_nimbus::none == wd->effect.edge_nimbus)
return;
auto root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
for (auto i = nimbus.begin(); i != nimbus.end(); ++i)
{
if (i->window == wd)
{
auto pixels = weight();
rectangle r{ wd->pos_root, wd->dimension };
r.x -= static_cast<int>(pixels);
r.y -= static_cast<int>(pixels);
r.width += static_cast<unsigned>(pixels << 1);
r.height += static_cast<unsigned>(pixels << 1);
root_wd->root_graph->paste(root_wd->root, r, r.x, r.y);
nimbus.erase(i);
break;
}
}
}
void edge_nimbus_renderer::render(basic_window* wd, bool forced, const rectangle* update_area)
{
bool copy_separately = true;
std::vector<std::pair<rectangle, basic_window*>> rd_set;
if (wd->root_widget->other.attribute.root->effects_edge_nimbus.size())
{
auto root_wd = wd->root_widget;
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
auto focused = root_wd->other.attribute.root->focus;
const unsigned pixels = weight();
auto graph = root_wd->root_graph;
nana::rectangle r;
for (auto & action : nimbus)
{
if (_m_edge_nimbus(action.window, focused) && window_layer::read_visual_rectangle(action.window, r))
{
if (action.window == wd)
{
if (update_area)
::nana::overlap(*update_area, rectangle(r), r);
copy_separately = false;
}
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == basic_window::update_state::refreshed))
{
rd_set.emplace_back(r, action.window);
action.rendered = true;
}
}
else if (action.rendered)
{
action.rendered = false;
if (action.window == wd)
copy_separately = false;
::nana::rectangle erase_r(
action.window->pos_root.x - static_cast<int>(pixels),
action.window->pos_root.y - static_cast<int>(pixels),
static_cast<unsigned>(action.window->dimension.width + (pixels << 1)),
static_cast<unsigned>(action.window->dimension.height + (pixels << 1))
);
graph->paste(root_wd->root, erase_r, erase_r.x, erase_r.y);
}
}
}
if (copy_separately)
{
rectangle vr;
if (window_layer::read_visual_rectangle(wd, vr))
{
if (update_area)
::nana::overlap(*update_area, rectangle(vr), vr);
wd->root_graph->paste(wd->root, vr, vr.x, vr.y);
}
}
rectangle wd_r{ wd->pos_root, wd->dimension };
wd_r.pare_off(-static_cast<int>(this->weight()));
//Render
for (auto & rd : rd_set)
{
auto other_wd = rd.second;
if (other_wd != wd)
{
rectangle other_r{ other_wd->pos_root, other_wd->dimension };
other_r.pare_off(-static_cast<int>(this->weight()));
if (!overlapped(wd_r, other_r))
continue;
}
_m_render_edge_nimbus(other_wd, rd.first);
}
}
/// Determines whether the effect will be rendered for the given window.
bool edge_nimbus_renderer::_m_edge_nimbus(basic_window * const wd, basic_window * const focused_wd)
{
// Don't render the effect if the window is disabled.
if (wd->flags.enabled)
{
if ((focused_wd == wd) && (static_cast<unsigned>(wd->effect.edge_nimbus) & static_cast<unsigned>(effects::edge_nimbus::active)))
return true;
else if ((static_cast<unsigned>(wd->effect.edge_nimbus) & static_cast<unsigned>(effects::edge_nimbus::over)) && (wd->flags.action == mouse_action::hovered))
return true;
}
return false;
}
void edge_nimbus_renderer::_m_render_edge_nimbus(basic_window* wd, const nana::rectangle & visual)
{
wd->flags.action_before = wd->flags.action;
auto r = visual;
r.pare_off(-static_cast<int>(weight()));
rectangle good_r;
if (overlap(r, rectangle{ wd->root_graph->size() }, good_r))
{
if ((good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) ||
(good_r.right() > visual.right()) || (good_r.bottom() > visual.bottom()))
{
auto graph = wd->root_graph;
nana::paint::pixel_buffer pixbuf(graph->handle(), r);
pixel_argb_t px0, px1, px2, px3;
px0 = pixbuf.pixel(0, 0);
px1 = pixbuf.pixel(r.width - 1, 0);
px2 = pixbuf.pixel(0, r.height - 1);
px3 = pixbuf.pixel(r.width - 1, r.height - 1);
good_r.x = good_r.y = 1;
good_r.width = r.width - 2;
good_r.height = r.height - 2;
pixbuf.rectangle(good_r, wd->annex.scheme->activated.get_color(), 0.95, false);
good_r.x = good_r.y = 0;
good_r.width = r.width;
good_r.height = r.height;
pixbuf.rectangle(good_r, wd->annex.scheme->activated.get_color(), 0.4, false);
pixbuf.pixel(0, 0, px0);
pixbuf.pixel(r.width - 1, 0, px1);
pixbuf.pixel(0, r.height - 1, px2);
pixbuf.pixel(r.width - 1, r.height - 1, px3);
pixbuf.paste(wd->root, { r.x, r.y });
std::vector<typename window_layer::wd_rectangle> overlaps;
if (window_layer::read_overlaps(wd, visual, overlaps))
{
for (auto & wdr : overlaps)
graph->paste(wd->root, wdr.r, wdr.r.x, wdr.r.y);
}
}
else
wd->root_graph->paste(wd->root, visual, visual.x, visual.y);
}
}
//end class edge_nimbus_renderer
}//end namespace detail
}//end namespace nana }//end namespace nana

View File

@ -0,0 +1,52 @@
/*
* Effects Renderer
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2019 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/effects_renderer.cpp
*/
#ifndef NANA_GUI_DETAIL_EFFECTS_RENDERER_HPP
#define NANA_GUI_DETAIL_EFFECTS_RENDERER_HPP
#include "basic_window.hpp"
#include <nana/gui/effects.hpp>
#include <nana/paint/graphics.hpp>
#include <nana/paint/pixel_buffer.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/window_layout.hpp>
namespace nana{
namespace detail
{
/// Effect edige nimbus renderer
class edge_nimbus_renderer
{
edge_nimbus_renderer() = default;
public:
using window_layer = ::nana::detail::window_layout;
using graph_reference = ::nana::paint::graphics&;
static edge_nimbus_renderer& instance();
constexpr unsigned weight() const
{
return 2;
}
void erase(basic_window* wd);
void render(basic_window* wd, bool forced, const rectangle* update_area = nullptr);
private:
/// Determines whether the effect will be rendered for the given window.
static bool _m_edge_nimbus(basic_window * const wd, basic_window * const focused_wd);
void _m_render_edge_nimbus(basic_window* wd, const nana::rectangle & visual);
};
}
}//end namespace nana
#endif

View File

@ -26,9 +26,7 @@ namespace nana
auto i = handles_.find(evt); auto i = handles_.find(evt);
if (i != handles_.end()) if (i != handles_.end())
{ reinterpret_cast<detail::event_docker_interface*>(evt)->get_event()->remove(evt);
reinterpret_cast<detail::docker_interface*>(evt)->get_event()->remove(evt);
}
} }
//end namespace events_operation //end namespace events_operation
@ -80,11 +78,10 @@ namespace nana
void event_base::remove(event_handle evt) void event_base::remove(event_handle evt)
{ {
internal_scope_guard lock; internal_scope_guard lock;
if (dockers_)
{
for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i) for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
{ {
if (reinterpret_cast<detail::docker_interface*>(evt) == *i) if (reinterpret_cast<detail::event_docker_interface*>(evt) == *i)
{ {
//Checks whether this event is working now. //Checks whether this event is working now.
if (emitting_count_) if (emitting_count_)
@ -96,19 +93,18 @@ namespace nana
{ {
bedrock::instance().evt_operation().cancel(evt); bedrock::instance().evt_operation().cancel(evt);
dockers_->erase(i); dockers_->erase(i);
delete reinterpret_cast<detail::docker_interface*>(evt); delete reinterpret_cast<detail::event_docker_interface*>(evt);
}
break;
} }
return;
} }
} }
} }
event_handle event_base::_m_emplace(detail::docker_interface* docker_ptr, bool in_front) event_handle event_base::_m_emplace(detail::event_docker_interface* docker_ptr, bool in_front)
{ {
internal_scope_guard lock; internal_scope_guard lock;
if (nullptr == dockers_) if (nullptr == dockers_)
dockers_ = new std::vector<detail::docker_interface*>; dockers_ = new std::vector<detail::event_docker_interface*>;
auto evt = reinterpret_cast<event_handle>(docker_ptr); auto evt = reinterpret_cast<event_handle>(docker_ptr);

View File

@ -15,8 +15,8 @@
#define NANA_GUI_INNER_FWD_IMPLEMENT_HPP #define NANA_GUI_INNER_FWD_IMPLEMENT_HPP
#include <nana/push_ignore_diagnostic> #include <nana/push_ignore_diagnostic>
#include "basic_window.hpp"
#include <nana/gui/detail/inner_fwd.hpp> #include <nana/gui/detail/inner_fwd.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include <nana/paint/graphics.hpp> #include <nana/paint/graphics.hpp>
#include <map> #include <map>

View File

@ -11,8 +11,8 @@
* *
*/ */
#include "basic_window.hpp"
#include <nana/gui/detail/window_layout.hpp> #include <nana/gui/detail/window_layout.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include <nana/gui/detail/native_window_interface.hpp> #include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp> #include <nana/gui/layout_utility.hpp>
#include <algorithm> #include <algorithm>
@ -22,7 +22,7 @@ namespace nana
namespace detail namespace detail
{ {
//class window_layout //class window_layout
void window_layout::paint(core_window_t* wd, paint_operation operation, bool req_refresh_children) void window_layout::paint(basic_window* wd, paint_operation operation, bool req_refresh_children)
{ {
if (wd->flags.refreshing && (paint_operation::try_refresh == operation)) if (wd->flags.refreshing && (paint_operation::try_refresh == operation))
return; return;
@ -41,7 +41,7 @@ namespace nana
_m_paint_glass_window(wd, (paint_operation::try_refresh == operation), req_refresh_children, 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 req_refresh_children) bool window_layout::maproot(basic_window* wd, bool have_refreshed, bool req_refresh_children)
{ {
auto check_opaque = wd->seek_non_lite_widget_ancestor(); auto check_opaque = wd->seek_non_lite_widget_ancestor();
if (check_opaque && check_opaque->flags.refreshing) if (check_opaque && check_opaque->flags.refreshing)
@ -80,7 +80,7 @@ namespace nana
return false; return false;
} }
void window_layout::paste_children_to_graphics(core_window_t* wd, nana::paint::graphics& graph) void window_layout::paste_children_to_graphics(basic_window* wd, nana::paint::graphics& graph)
{ {
_m_paste_children(wd, false, false, rectangle{ wd->pos_root, wd->dimension }, graph, wd->pos_root); _m_paste_children(wd, false, false, rectangle{ wd->pos_root, wd->dimension }, graph, wd->pos_root);
} }
@ -89,7 +89,7 @@ namespace nana
///@brief Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget, ///@brief Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget,
/// the visual rectangle is a rectangular block that a window should be displayed on screen. /// the visual rectangle is a rectangular block that a window should be displayed on screen.
/// The result is a rectangle that is a visible area for its ancestors. /// The result is a rectangle that is a visible area for its ancestors.
bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual) bool window_layout::read_visual_rectangle(basic_window* wd, nana::rectangle& visual)
{ {
if (! wd->displayed()) return false; if (! wd->displayed()) return false;
@ -139,7 +139,7 @@ namespace nana
//read_overlaps //read_overlaps
// reads the overlaps that are overlapped a rectangular block // reads the overlaps that are overlapped a rectangular block
bool window_layout::read_overlaps(core_window_t* wd, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks) bool window_layout::read_overlaps(basic_window* wd, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks)
{ {
auto const is_wd_root = (category::flags::root == wd->other.category); auto const is_wd_root = (category::flags::root == wd->other.category);
wd_rectangle block; wd_rectangle block;
@ -150,7 +150,7 @@ namespace nana
{ {
for (++i; i != wd->parent->children.cend(); ++i) for (++i; i != wd->parent->children.cend(); ++i)
{ {
core_window_t* cover = *i; basic_window* cover = *i;
if (!cover->visible) if (!cover->visible)
continue; continue;
@ -182,7 +182,7 @@ namespace nana
return (!blocks.empty()); return (!blocks.empty());
} }
bool window_layout::enable_effects_bground(core_window_t * wd, bool enabled) bool window_layout::enable_effects_bground(basic_window * wd, bool enabled)
{ {
if (category::flags::widget != wd->other.category) if (category::flags::widget != wd->other.category)
return false; return false;
@ -220,15 +220,15 @@ namespace nana
//make_bground //make_bground
// update the glass buffer of a glass window. // update the glass buffer of a glass window.
void window_layout::make_bground(core_window_t* const wd) void window_layout::make_bground(basic_window* const wd)
{ {
nana::point rpos{ wd->pos_root }; nana::point rpos{ wd->pos_root };
auto & glass_buffer = wd->other.glass_buffer; auto & glass_buffer = wd->other.glass_buffer;
if (category::flags::lite_widget == wd->parent->other.category) if (category::flags::lite_widget == wd->parent->other.category)
{ {
std::vector<core_window_t*> layers; std::vector<basic_window*> layers;
core_window_t * beg = wd->parent; auto beg = wd->parent;
while (beg && (category::flags::lite_widget == beg->other.category)) while (beg && (category::flags::lite_widget == beg->other.category))
{ {
layers.push_back(beg); layers.push_back(beg);
@ -240,11 +240,11 @@ namespace nana
nana::rectangle r(wd->pos_owner, wd->dimension); nana::rectangle r(wd->pos_owner, wd->dimension);
for (auto i = layers.rbegin(), layers_rend = layers.rend(); i != layers_rend; ++i) for (auto i = layers.rbegin(), layers_rend = layers.rend(); i != layers_rend; ++i)
{ {
core_window_t * pre = *i; auto pre = *i;
if (false == pre->visible) if (false == pre->visible)
continue; continue;
core_window_t * term = ((i + 1 != layers_rend) ? *(i + 1) : wd); auto term = ((i + 1 != layers_rend) ? *(i + 1) : wd);
r.position(wd->pos_root - pre->pos_root); r.position(wd->pos_root - pre->pos_root);
for (auto child : pre->children) for (auto child : pre->children)
@ -286,10 +286,10 @@ namespace nana
} }
if (wd->effect.bground) if (wd->effect.bground)
wd->effect.bground->take_effect(reinterpret_cast<window>(wd), glass_buffer); wd->effect.bground->take_effect(wd, glass_buffer);
} }
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) void window_layout::_m_paste_children(basic_window* 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; nana::rectangle rect;
for (auto child : wd->children) for (auto child : wd->children)
@ -333,7 +333,7 @@ namespace nana
} }
} }
void window_layout::_m_paint_glass_window(core_window_t* wd, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other) void window_layout::_m_paint_glass_window(basic_window* wd, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other)
{ {
//A window which has an empty graphics(and lite-widget) does not notify //A window which has an empty graphics(and lite-widget) does not notify
//glass windows for updating their background. //glass windows for updating their background.
@ -381,7 +381,7 @@ namespace nana
/// Notify the glass windows that are overlapped with the specified visual rectangle. /// 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. /// 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) void window_layout::_m_notify_glasses(basic_window* const sigwd)
{ {
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension); nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
for (auto wd : data_sect.effects_bground_windows) for (auto wd : data_sect.effects_bground_windows)
@ -420,7 +420,7 @@ namespace nana
else else
{ {
//test if sigwnd is a parent of glass window x, or a slibing of the glass window, or a child of the slibing of the glass window. //test if sigwnd is a parent of glass window x, or a slibing of the glass window, or a child of the slibing of the glass window.
core_window_t *p = wd->parent, *signode = sigwd; basic_window *p = wd->parent, *signode = sigwd;
while (signode->parent && (signode->parent != p)) while (signode->parent && (signode->parent != p))
signode = signode->parent; signode = signode->parent;

View File

@ -18,7 +18,8 @@
#include <nana/gui/detail/window_layout.hpp> #include <nana/gui/detail/window_layout.hpp>
#include <nana/gui/detail/native_window_interface.hpp> #include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp> #include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/effects_renderer.hpp>
#include "effects_renderer.hpp"
#include "window_register.hpp" #include "window_register.hpp"
#include "inner_fwd_implement.hpp" #include "inner_fwd_implement.hpp"
@ -281,7 +282,7 @@ namespace detail
paint::image default_icon_big; paint::image default_icon_big;
paint::image default_icon_small; paint::image default_icon_small;
lite_map<core_window_t*, std::vector<std::function<void()>>> safe_place; lite_map<basic_window*, std::vector<std::function<void()>>> safe_place;
}; };
//end struct wdm_private_impl //end struct wdm_private_impl
@ -454,7 +455,7 @@ namespace detail
delete impl_; delete impl_;
} }
std::size_t window_manager::number_of_core_window() const std::size_t window_manager::window_count() const
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -467,14 +468,14 @@ namespace detail
return mutex_; return mutex_;
} }
void window_manager::all_handles(std::vector<core_window_t*> &v) const void window_manager::all_handles(std::vector<basic_window*> &v) const
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
v = impl_->wd_register.queue(); v = impl_->wd_register.queue();
} }
void window_manager::event_filter(core_window_t* wd, bool is_make, event_code evtid) void window_manager::event_filter(basic_window* wd, bool is_make, event_code evtid)
{ {
switch(evtid) switch(evtid)
{ {
@ -486,21 +487,21 @@ namespace detail
} }
} }
bool window_manager::available(core_window_t* wd) bool window_manager::available(basic_window* wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
return impl_->wd_register.available(wd); return impl_->wd_register.available(wd);
} }
bool window_manager::available(core_window_t * a, core_window_t* b) bool window_manager::available(basic_window * a, basic_window* b)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
return (impl_->wd_register.available(a) && impl_->wd_register.available(b)); return (impl_->wd_register.available(a) && impl_->wd_register.available(b));
} }
window_manager::core_window_t* window_manager::create_root(core_window_t* owner, bool nested, rectangle r, const appearance& app, widget* wdg) basic_window* window_manager::create_root(basic_window* owner, bool nested, rectangle r, const appearance& app, widget* wdg)
{ {
native_window_type native = nullptr; native_window_type native = nullptr;
if (owner) if (owner)
@ -524,7 +525,7 @@ namespace detail
auto result = native_interface::create_window(native, nested, r, app); auto result = native_interface::create_window(native, nested, r, app);
if (result.native_handle) if (result.native_handle)
{ {
auto wd = new core_window_t(owner, widget_notifier_interface::get_notifier(wdg), (category::root_tag**)nullptr); auto wd = new basic_window(owner, widget_notifier_interface::get_notifier(wdg), (category::root_tag**)nullptr);
if (nested) if (nested)
{ {
wd->owner = nullptr; wd->owner = nullptr;
@ -552,7 +553,7 @@ namespace detail
return nullptr; return nullptr;
} }
window_manager::core_window_t* window_manager::create_widget(core_window_t* parent, const rectangle& r, bool is_lite, widget* wdg) basic_window* window_manager::create_widget(basic_window* parent, const rectangle& r, bool is_lite, widget* wdg)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -564,17 +565,17 @@ namespace detail
auto wdg_notifier = widget_notifier_interface::get_notifier(wdg); auto wdg_notifier = widget_notifier_interface::get_notifier(wdg);
core_window_t * wd; basic_window * wd;
if (is_lite) if (is_lite)
wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::lite_widget_tag**)nullptr); wd = new basic_window(parent, std::move(wdg_notifier), r, (category::lite_widget_tag**)nullptr);
else else
wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::widget_tag**)nullptr); wd = new basic_window(parent, std::move(wdg_notifier), r, (category::widget_tag**)nullptr);
impl_->wd_register.insert(wd); impl_->wd_register.insert(wd);
return wd; return wd;
} }
void window_manager::close(core_window_t *wd) void window_manager::close(basic_window *wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -587,7 +588,7 @@ namespace detail
{ {
auto &brock = bedrock::instance(); auto &brock = bedrock::instance();
arg_unload arg; arg_unload arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.cancel = false; arg.cancel = false;
brock.emit(event_code::unload, wd, arg, true, brock.get_thread_context()); brock.emit(event_code::unload, wd, arg, true, brock.get_thread_context());
if (false == arg.cancel) if (false == arg.cancel)
@ -616,7 +617,7 @@ namespace detail
//destroy //destroy
//@brief: Delete the window handle //@brief: Delete the window handle
void window_manager::destroy(core_window_t* wd) void window_manager::destroy(basic_window* wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -640,7 +641,7 @@ namespace detail
update(parent, false, false, &update_area); update(parent, false, false, &update_area);
} }
void window_manager::destroy_handle(core_window_t* wd) void window_manager::destroy_handle(basic_window* wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -653,7 +654,7 @@ namespace detail
} }
} }
void window_manager::icon(core_window_t* wd, const paint::image& small_icon, const paint::image& big_icon) void window_manager::icon(basic_window* wd, const paint::image& small_icon, const paint::image& big_icon)
{ {
if(!big_icon.empty() || !small_icon.empty()) if(!big_icon.empty() || !small_icon.empty())
{ {
@ -676,7 +677,7 @@ namespace detail
//show //show
//@brief: show or hide a window //@brief: show or hide a window
bool window_manager::show(core_window_t* wd, bool visible) bool window_manager::show(basic_window* wd, bool visible)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -701,7 +702,7 @@ namespace detail
return true; return true;
} }
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos, bool ignore_captured) basic_window* window_manager::find_window(native_window_type root, const point& pos, bool ignore_captured)
{ {
if (nullptr == root) if (nullptr == root)
return nullptr; return nullptr;
@ -739,7 +740,7 @@ namespace detail
} }
//move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window //move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window
bool window_manager::move(core_window_t* wd, int x, int y, bool passive) bool window_manager::move(basic_window* wd, int x, int y, bool passive)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -758,7 +759,7 @@ namespace detail
auto &brock = bedrock::instance(); auto &brock = bedrock::instance();
arg_move arg; arg_move arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.x = x; arg.x = x;
arg.y = y; arg.y = y;
@ -788,7 +789,7 @@ namespace detail
return false; return false;
} }
bool window_manager::move(core_window_t* wd, const rectangle& r) bool window_manager::move(basic_window* wd, const rectangle& r)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -812,7 +813,7 @@ namespace detail
wd->other.upd_state = basic_window::update_state::request_refresh; wd->other.upd_state = basic_window::update_state::request_refresh;
arg_move arg; arg_move arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.x = r.x; arg.x = r.x;
arg.y = r.y; arg.y = r.y;
brock.emit(event_code::move, wd, arg, true, brock.get_thread_context()); brock.emit(event_code::move, wd, arg, true, brock.get_thread_context());
@ -846,7 +847,7 @@ namespace detail
native_interface::move_window(wd->root, root_r); native_interface::move_window(wd->root, root_r);
arg_resized arg; arg_resized arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.width = root_r.width; arg.width = root_r.width;
arg.height = root_r.height; arg.height = root_r.height;
brock.emit(event_code::resized, wd, arg, true, brock.get_thread_context()); brock.emit(event_code::resized, wd, arg, true, brock.get_thread_context());
@ -864,7 +865,7 @@ namespace detail
// e.g, when the size of window is changed by OS/user, the function should not resize the // e.g, when the size of window is changed by OS/user, the function should not resize the
// window again, otherwise, it causes an infinite loop, because when a root_widget is resized, // window again, otherwise, it causes an infinite loop, because when a root_widget is resized,
// window_manager will call the function. // window_manager will call the function.
bool window_manager::size(core_window_t* wd, nana::size sz, bool passive, bool ask_update) bool window_manager::size(basic_window* wd, nana::size sz, bool passive, bool ask_update)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -875,7 +876,7 @@ namespace detail
if (sz != wd->dimension) if (sz != wd->dimension)
{ {
arg_resizing arg; arg_resizing arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.border = window_border::none; arg.border = window_border::none;
arg.width = sz.width; arg.width = sz.width;
arg.height = sz.height; arg.height = sz.height;
@ -902,7 +903,7 @@ namespace detail
if (wd->dimension == sz) if (wd->dimension == sz)
return false; return false;
std::vector<core_window_t*> presence; std::vector<basic_window*> presence;
if (wd->dimension.width < sz.width || wd->dimension.height < sz.height) if (wd->dimension.width < sz.width || wd->dimension.height < sz.height)
{ {
@ -970,16 +971,16 @@ namespace detail
} }
arg_resized arg; arg_resized arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.width = sz.width; arg.width = sz.width;
arg.height = sz.height; arg.height = sz.height;
brock.emit(event_code::resized, wd, arg, ask_update, brock.get_thread_context()); brock.emit(event_code::resized, wd, arg, ask_update, brock.get_thread_context());
return true; return true;
} }
window_manager::core_window_t* window_manager::root(native_window_type wd) const basic_window* window_manager::root(native_window_type wd) const
{ {
static std::pair<native_window_type, core_window_t*> cache; static std::pair<native_window_type, basic_window*> cache;
if(cache.first == wd) return cache.second; if(cache.first == wd) return cache.second;
//Thread-Safe Required! //Thread-Safe Required!
@ -996,7 +997,7 @@ namespace detail
} }
//Copy the root buffer that wnd specified into DeviceContext //Copy the root buffer that wnd specified into DeviceContext
void window_manager::map(core_window_t* wd, bool forced, const rectangle* update_area) void window_manager::map(basic_window* wd, bool forced, const rectangle* update_area)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1008,7 +1009,7 @@ namespace detail
//@brief: update is used for displaying the screen-off buffer. //@brief: update is used for displaying the screen-off buffer.
// Because of a good efficiency, if it is called in an event procedure and the event procedure window is the // Because of a good efficiency, if it is called in an event procedure and the event procedure window is the
// same as update's, update would not map the screen-off buffer and just set the window for lazy refresh // same as update's, update would not map the screen-off buffer and just set the window for lazy refresh
bool window_manager::update(core_window_t* wd, bool redraw, bool forced, const rectangle* update_area) bool window_manager::update(basic_window* wd, bool redraw, bool forced, const rectangle* update_area)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1045,13 +1046,13 @@ namespace detail
else if (redraw) else if (redraw)
window_layer::paint(wd, paint_operation::try_refresh, false); window_layer::paint(wd, paint_operation::try_refresh, false);
if (wd->other.upd_state == core_window_t::update_state::lazy) if (wd->other.upd_state == basic_window::update_state::lazy)
wd->other.upd_state = core_window_t::update_state::refreshed; wd->other.upd_state = basic_window::update_state::refreshed;
} }
return true; return true;
} }
void window_manager::update_requesters(core_window_t* root_wd) void window_manager::update_requesters(basic_window* root_wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1074,7 +1075,7 @@ namespace detail
} }
void window_manager::refresh_tree(core_window_t* wd) void window_manager::refresh_tree(basic_window* wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1086,7 +1087,7 @@ namespace detail
//do_lazy_refresh //do_lazy_refresh
//@brief: defined a behavior of flush the screen //@brief: defined a behavior of flush the screen
void window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree) void window_manager::do_lazy_refresh(basic_window* wd, bool force_copy_to_screen, bool refresh_tree)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1100,11 +1101,11 @@ namespace detail
using paint_operation = window_layer::paint_operation; using paint_operation = window_layer::paint_operation;
if (wd->visible_parents()) if (wd->visible_parents())
{ {
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) if ((wd->other.upd_state == basic_window::update_state::refreshed) || (wd->other.upd_state == basic_window::update_state::request_refresh) || force_copy_to_screen)
{ {
if (!wd->try_lazy_update(wd->other.upd_state == core_window_t::update_state::request_refresh)) if (!wd->try_lazy_update(wd->other.upd_state == basic_window::update_state::request_refresh))
{ {
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); window_layer::paint(wd, (wd->other.upd_state == basic_window::update_state::request_refresh ? paint_operation::try_refresh : paint_operation::have_refreshed), refresh_tree);
this->map(wd, force_copy_to_screen); this->map(wd, force_copy_to_screen);
} }
} }
@ -1123,10 +1124,10 @@ namespace detail
window_layer::paint(wd, paint_operation::try_refresh, 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; wd->other.upd_state = basic_window::update_state::none;
} }
bool window_manager::set_parent(core_window_t* wd, core_window_t* newpa) bool window_manager::set_parent(basic_window* wd, basic_window* newpa)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1153,7 +1154,7 @@ namespace detail
//set_focus //set_focus
//@brief: set a keyboard focus to a window. this may fire a focus event. //@brief: set a keyboard focus to a window. this may fire a focus event.
window_manager::core_window_t* window_manager::set_focus(core_window_t* wd, bool root_has_been_focused, arg_focus::reason reason) basic_window* window_manager::set_focus(basic_window* wd, bool root_has_been_focused, arg_focus::reason reason)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1177,7 +1178,7 @@ namespace detail
prev_focus->annex.caret_ptr->activate(false); prev_focus->annex.caret_ptr->activate(false);
arg.getting = false; arg.getting = false;
arg.window_handle = reinterpret_cast<window>(prev_focus); arg.window_handle = prev_focus;
arg.receiver = wd->root; arg.receiver = wd->root;
arg.focus_reason = arg_focus::reason::general; arg.focus_reason = arg_focus::reason::general;
brock.emit(event_code::focus, prev_focus, arg, true, brock.get_thread_context()); brock.emit(event_code::focus, prev_focus, arg, true, brock.get_thread_context());
@ -1194,7 +1195,7 @@ namespace detail
if(wd->annex.caret_ptr) if(wd->annex.caret_ptr)
wd->annex.caret_ptr->activate(true); wd->annex.caret_ptr->activate(true);
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
arg.getting = true; arg.getting = true;
arg.receiver = wd->root; arg.receiver = wd->root;
arg.focus_reason = reason; arg.focus_reason = reason;
@ -1217,7 +1218,7 @@ namespace detail
return prev_focus; return prev_focus;
} }
window_manager::core_window_t* window_manager::capture_redirect(core_window_t* wd) basic_window* window_manager::capture_redirect(basic_window* wd)
{ {
if(attr_.capture.window && (attr_.capture.ignore_children == false) && (attr_.capture.window != wd)) if(attr_.capture.window && (attr_.capture.ignore_children == false) && (attr_.capture.window != wd))
{ {
@ -1244,12 +1245,12 @@ namespace detail
return false; return false;
} }
window_manager::core_window_t * window_manager::capture_window() const basic_window * window_manager::capture_window() const
{ {
return attr_.capture.window; return attr_.capture.window;
} }
void window_manager::capture_window(core_window_t* wd, bool captured, bool ignore_children) void window_manager::capture_window(basic_window* wd, bool captured, bool ignore_children)
{ {
if (!this->available(wd)) if (!this->available(wd))
return; return;
@ -1285,7 +1286,7 @@ namespace detail
wd->flags.captured = false; wd->flags.captured = false;
if(attr_cap.size()) if(attr_cap.size())
{ {
std::pair<core_window_t*, bool> last = attr_cap.back(); std::pair<basic_window*, bool> last = attr_cap.back();
attr_cap.pop_back(); attr_cap.pop_back();
if (impl_->wd_register.available(last.first)) if (impl_->wd_register.available(last.first))
@ -1320,7 +1321,7 @@ namespace detail
// this method insert a window which catches an user TAB into a TAB window container // this method insert a window which catches an user TAB into a TAB window container
// the TAB window container is held by a wd's root widget. Not every widget has a TAB window container, // the TAB window container is held by a wd's root widget. Not every widget has a TAB window container,
// the container is created while a first Tab Window is setting // the container is created while a first Tab Window is setting
void window_manager::enable_tabstop(core_window_t* wd) void window_manager::enable_tabstop(basic_window* wd)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1332,7 +1333,7 @@ namespace detail
} }
// preconditions of get_tabstop: tabstop is not empty and at least one window is visible // preconditions of get_tabstop: tabstop is not empty and at least one window is visible
window_manager::core_window_t* get_tabstop(window_manager::core_window_t* wd, bool forward) basic_window* get_tabstop(basic_window* wd, bool forward)
{ {
auto & tabs = wd->root_widget->other.attribute.root->tabstop; auto & tabs = wd->root_widget->other.attribute.root->tabstop;
@ -1347,7 +1348,7 @@ namespace detail
if (i != end) if (i != end)
{ {
++i; ++i;
window_manager::core_window_t* ts = (i != end ? (*i) : tabs.front()); basic_window* ts = (i != end ? (*i) : tabs.front());
return (ts != wd ? ts : 0); return (ts != wd ? ts : 0);
} }
else else
@ -1363,7 +1364,7 @@ namespace detail
return nullptr; return nullptr;
} }
auto window_manager::tabstop(core_window_t* wd, bool forward) const -> core_window_t* auto window_manager::tabstop(basic_window* wd, bool forward) const -> basic_window*
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1407,7 +1408,7 @@ namespace detail
impl_->wd_register.delete_trash(tid); impl_->wd_register.delete_trash(tid);
} }
bool window_manager::enable_effects_bground(core_window_t* wd, bool enabled) bool window_manager::enable_effects_bground(basic_window* wd, bool enabled)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1417,7 +1418,7 @@ namespace detail
return false; return false;
} }
bool window_manager::calc_window_point(core_window_t* wd, nana::point& pos) bool window_manager::calc_window_point(basic_window* wd, nana::point& pos)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1437,19 +1438,19 @@ namespace detail
return impl_->misc_register.find(native_wd); return impl_->misc_register.find(native_wd);
} }
bool window_manager::register_shortkey(core_window_t* wd, unsigned long key) bool window_manager::register_shortkey(basic_window* wd, unsigned long key)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
if (impl_->wd_register.available(wd)) if (impl_->wd_register.available(wd))
{ {
//the root runtime must exist, because the wd is valid. Otherse, it's bug of library //the root runtime must exist, because the wd is valid. Otherse, it's bug of library
return root_runtime(wd->root)->shortkeys.make(reinterpret_cast<window>(wd), key); return root_runtime(wd->root)->shortkeys.make(wd, key);
} }
return false; return false;
} }
void window_manager::unregister_shortkey(core_window_t* wd, bool with_children) void window_manager::unregister_shortkey(basic_window* wd, bool with_children)
{ {
//Thread-Safe Required! //Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
@ -1458,7 +1459,7 @@ namespace detail
auto root_rt = root_runtime(wd->root); auto root_rt = root_runtime(wd->root);
if (root_rt) if (root_rt)
{ {
root_rt->shortkeys.umake(reinterpret_cast<window>(wd)); root_rt->shortkeys.umake(wd);
if (with_children) if (with_children)
{ {
for (auto child : wd->children) for (auto child : wd->children)
@ -1467,7 +1468,7 @@ namespace detail
} }
} }
window_manager::core_window_t* window_manager::find_shortkey(native_window_type native_window, unsigned long key) basic_window* window_manager::find_shortkey(native_window_type native_window, unsigned long key)
{ {
if(native_window) if(native_window)
{ {
@ -1475,12 +1476,12 @@ namespace detail
std::lock_guard<mutex_type> lock(mutex_); std::lock_guard<mutex_type> lock(mutex_);
auto object = root_runtime(native_window); auto object = root_runtime(native_window);
if(object) if(object)
return reinterpret_cast<core_window_t*>(object->shortkeys.find(key)); return object->shortkeys.find(key);
} }
return nullptr; return nullptr;
} }
void window_manager::set_safe_place(core_window_t* wd, std::function<void()>&& fn) void window_manager::set_safe_place(basic_window* wd, std::function<void()>&& fn)
{ {
if (fn) if (fn)
{ {
@ -1522,7 +1523,7 @@ namespace detail
return false; return false;
} }
void window_manager::_m_disengage(core_window_t* wd, core_window_t* for_new) void window_manager::_m_disengage(basic_window* wd, basic_window* for_new)
{ {
auto * const wdpa = wd->parent; auto * const wdpa = wd->parent;
@ -1536,7 +1537,7 @@ namespace detail
//Holds the shortkeys of wd and its children, and then //Holds the shortkeys of wd and its children, and then
//register these shortkeys for establishing. //register these shortkeys for establishing.
std::vector<std::pair<core_window_t*,unsigned long>> sk_holder; std::vector<std::pair<basic_window*,unsigned long>> sk_holder;
if ((!established) || (pa_root_attr != root_attr)) if ((!established) || (pa_root_attr != root_attr))
{ {
@ -1598,10 +1599,8 @@ namespace detail
if (!established) if (!established)
{ {
using effect_renderer = detail::edge_nimbus_renderer<basic_window>;
//remove the window from edge nimbus effect when it is destroying //remove the window from edge nimbus effect when it is destroying
effect_renderer::instance().erase(wd); edge_nimbus_renderer::instance().erase(wd);
} }
else if (pa_root_attr != root_attr) else if (pa_root_attr != root_attr)
{ {
@ -1657,8 +1656,8 @@ namespace detail
auto delta_pos = wd->pos_root - for_new->pos_root; auto delta_pos = wd->pos_root - for_new->pos_root;
std::function<void(core_window_t*, const nana::point&)> set_pos_root; std::function<void(basic_window*, const nana::point&)> set_pos_root;
set_pos_root = [&set_pos_root](core_window_t* wd, const nana::point& delta_pos) set_pos_root = [&set_pos_root](basic_window* wd, const nana::point& delta_pos)
{ {
for (auto child : wd->children) for (auto child : wd->children)
{ {
@ -1689,7 +1688,7 @@ namespace detail
} }
} }
void window_manager::_m_destroy(core_window_t* wd) void window_manager::_m_destroy(basic_window* wd)
{ {
if(wd->flags.destroying) return; if(wd->flags.destroying) return;
@ -1705,13 +1704,11 @@ namespace detail
wd->annex.caret_ptr = nullptr; wd->annex.caret_ptr = nullptr;
} }
using effect_renderer = detail::edge_nimbus_renderer<basic_window>;
//remove the window from edge nimbus effect when it is destroying //remove the window from edge nimbus effect when it is destroying
effect_renderer::instance().erase(wd); edge_nimbus_renderer::instance().erase(wd);
arg_destroy arg; arg_destroy arg;
arg.window_handle = reinterpret_cast<window>(wd); arg.window_handle = wd;
brock.emit(event_code::destroy, wd, arg, true, brock.get_thread_context()); brock.emit(event_code::destroy, wd, arg, true, brock.get_thread_context());
//Delete the children widgets. //Delete the children widgets.
@ -1741,7 +1738,7 @@ namespace detail
wd->drawer.graphics.release(); wd->drawer.graphics.release();
} }
void window_manager::_m_move_core(core_window_t* wd, const point& delta) void window_manager::_m_move_core(basic_window* wd, const point& delta)
{ {
if(category::flags::root != wd->other.category) //A root widget always starts at (0, 0) and its children are not to be changed if(category::flags::root != wd->other.category) //A root widget always starts at (0, 0) and its children are not to be changed
{ {
@ -1763,14 +1760,14 @@ namespace detail
} }
} }
void window_manager::_m_shortkeys(core_window_t* wd, bool with_children, std::vector<std::pair<core_window_t*, unsigned long>>& keys) const void window_manager::_m_shortkeys(basic_window* wd, bool with_children, std::vector<std::pair<basic_window*, unsigned long>>& keys) const
{ {
if (impl_->wd_register.available(wd)) if (impl_->wd_register.available(wd))
{ {
//The root_rt must exist, because wd is valid. Otherwise, it's a bug of the library. //The root_rt must exist, because wd is valid. Otherwise, it's a bug of the library.
auto root_rt = root_runtime(wd->root); auto root_rt = root_runtime(wd->root);
auto pkeys = root_rt->shortkeys.keys(reinterpret_cast<window>(wd)); auto pkeys = root_rt->shortkeys.keys(wd);
if (pkeys) if (pkeys)
{ {
for (auto key : *pkeys) for (auto key : *pkeys)
@ -1788,7 +1785,7 @@ namespace detail
//_m_find //_m_find
//@brief: find a window on root window through a given root coordinate. //@brief: find a window on root window through a given root coordinate.
// the given root coordinate must be in the rectangle of wnd. // the given root coordinate must be in the rectangle of wnd.
window_manager::core_window_t* window_manager::_m_find(core_window_t* wd, const point& pos) basic_window* window_manager::_m_find(basic_window* wd, const point& pos)
{ {
if(!wd->visible) if(!wd->visible)
return nullptr; return nullptr;
@ -1812,7 +1809,7 @@ namespace detail
} }
//_m_effective, test if the window is a handle of window that specified by (root_x, root_y) //_m_effective, test if the window is a handle of window that specified by (root_x, root_y)
bool window_manager::_m_effective(core_window_t* wd, const point& root_pos) bool window_manager::_m_effective(basic_window* wd, const point& root_pos)
{ {
if(wd == nullptr || false == wd->visible) return false; if(wd == nullptr || false == wd->visible) return false;
return rectangle{ wd->pos_root, wd->dimension }.is_hit(root_pos); return rectangle{ wd->pos_root, wd->dimension }.is_hit(root_pos);

View File

@ -1,7 +1,7 @@
#ifndef NANA_WINDOW_REGISTER_HEADER_INCLUDED #ifndef NANA_WINDOW_REGISTER_HEADER_INCLUDED
#define NANA_WINDOW_REGISTER_HEADER_INCLUDED #define NANA_WINDOW_REGISTER_HEADER_INCLUDED
#include <nana/gui/detail/basic_window.hpp> #include "basic_window.hpp"
#include <set> #include <set>
#include <vector> #include <vector>
#include <algorithm> //std::find #include <algorithm> //std::find

View File

@ -1,7 +1,7 @@
/** /**
* Drag and Drop Implementation * Drag and Drop Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2018 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -13,9 +13,9 @@
#include <nana/gui/dragdrop.hpp> #include <nana/gui/dragdrop.hpp>
#include <nana/gui/programming_interface.hpp> #include <nana/gui/programming_interface.hpp>
#include <nana/gui/detail/bedrock.hpp> #include <nana/gui/detail/bedrock.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include "detail/basic_window.hpp"
#include <map> #include <map>
#include <set> #include <set>
@ -157,10 +157,16 @@ namespace nana
}; };
#ifdef NANA_WINDOWS #ifdef NANA_WINDOWS
template<typename Interface, const IID& iid> template<typename Interface, const IID& iid>
class win32com_iunknown : public Interface class win32com_iunknown final: public Interface
{ {
public: public:
template<typename ...Args>
win32com_iunknown(Args&& ... args) :
Interface(std::forward<Args>(args)...)
{}
//Implements IUnknown //Implements IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{ {
@ -188,6 +194,7 @@ namespace nana
LONG ref_count_{ 1 }; LONG ref_count_{ 1 };
}; };
class win32com_drop_target : public IDropTarget, public dragdrop_session class win32com_drop_target : public IDropTarget, public dragdrop_session
{ {
public: public:
@ -273,10 +280,10 @@ namespace nana
DWORD effect_{ DROPEFFECT_NONE }; DWORD effect_{ DROPEFFECT_NONE };
}; };
class drop_source : public win32com_iunknown<IDropSource, IID_IDropSource> class drop_source_impl : public IDropSource
{ {
public: public:
drop_source(window wd) : drop_source_impl(window wd) :
window_handle_(wd) window_handle_(wd)
{} {}
@ -305,8 +312,10 @@ namespace nana
private: private:
window const window_handle_; window const window_handle_;
}; };
using drop_source = win32com_iunknown<drop_source_impl, IID_IDropSource>;
class win32_dropdata : public win32com_iunknown<IDataObject, IID_IDataObject>
class win32_dropdata_impl: public IDataObject
{ {
public: public:
struct data_entry struct data_entry
@ -563,6 +572,8 @@ namespace nana
std::vector<std::unique_ptr<data_entry>> entries_; std::vector<std::unique_ptr<data_entry>> entries_;
}; };
using win32_dropdata = win32com_iunknown<win32_dropdata_impl, IID_IDataObject>;
#elif defined(NANA_X11) #elif defined(NANA_X11)
class x11_dropdata class x11_dropdata
@ -710,7 +721,7 @@ namespace nana
i->second->set_current_source(drag_wd); i->second->set_current_source(drag_wd);
DWORD result_effect{ DROPEFFECT_NONE }; DWORD result_effect{ DROPEFFECT_NONE };
auto status = ::DoDragDrop(dropdata, drop_src, DROPEFFECT_COPY, &result_effect); ::DoDragDrop(dropdata, drop_src, DROPEFFECT_COPY, &result_effect);
i->second->set_current_source(nullptr); i->second->set_current_source(nullptr);
@ -961,8 +972,7 @@ namespace nana
if (API::is_window(window_handle)) if (API::is_window(window_handle))
{ {
dragging = true; dragging = true;
auto real_wd = reinterpret_cast<detail::basic_window*>(window_handle); window_handle->other.dnd_state = dragdrop_status::not_ready;
real_wd->other.dnd_state = dragdrop_status::not_ready;
} }
API::release_capture(window_handle); API::release_capture(window_handle);
@ -1000,9 +1010,7 @@ namespace nana
if (arg.is_left_button() && API::is_window(impl_->window_handle)) if (arg.is_left_button() && API::is_window(impl_->window_handle))
{ {
impl_->dragging = ((!impl_->predicate) || impl_->predicate()); impl_->dragging = ((!impl_->predicate) || impl_->predicate());
impl_->window_handle->other.dnd_state = dragdrop_status::ready;
auto real_wd = reinterpret_cast<detail::basic_window*>(impl_->window_handle);
real_wd->other.dnd_state = dragdrop_status::ready;
} }
}); });
@ -1010,14 +1018,13 @@ namespace nana
if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle))) if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle)))
return; return;
auto real_wd = reinterpret_cast<detail::basic_window*>(arg.window_handle); arg.window_handle->other.dnd_state = dragdrop_status::in_progress;
real_wd->other.dnd_state = dragdrop_status::in_progress;
std::unique_ptr<dragdrop_service::dropdata_type> dropdata{new dragdrop_service::dropdata_type}; std::unique_ptr<dragdrop_service::dropdata_type> dropdata{new dragdrop_service::dropdata_type};
auto has_dropped = dragdrop_service::instance().dragdrop(arg.window_handle, dropdata.get(), nullptr); auto has_dropped = dragdrop_service::instance().dragdrop(arg.window_handle, dropdata.get(), nullptr);
real_wd->other.dnd_state = dragdrop_status::not_ready; arg.window_handle->other.dnd_state = dragdrop_status::not_ready;
impl_->dragging = false; impl_->dragging = false;
if (has_dropped) if (has_dropped)
@ -1116,9 +1123,7 @@ namespace nana
if (arg.is_left_button() && API::is_window(impl_->source_handle)) if (arg.is_left_button() && API::is_window(impl_->source_handle))
{ {
impl_->dragging = ((!impl_->predicate) || impl_->predicate()); impl_->dragging = ((!impl_->predicate) || impl_->predicate());
impl_->source_handle->other.dnd_state = dragdrop_status::ready;
auto real_wd = reinterpret_cast<detail::basic_window*>(impl_->source_handle);
real_wd->other.dnd_state = dragdrop_status::ready;
} }
}); });
@ -1126,13 +1131,9 @@ namespace nana
if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle))) if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle)))
return; return;
auto real_wd = reinterpret_cast<detail::basic_window*>(arg.window_handle); arg.window_handle->other.dnd_state = dragdrop_status::in_progress;
real_wd->other.dnd_state = dragdrop_status::in_progress;
impl_->make_drop(); impl_->make_drop();
arg.window_handle->other.dnd_state = dragdrop_status::not_ready;
real_wd->other.dnd_state = dragdrop_status::not_ready;
impl_->dragging = false; impl_->dragging = false;
}); });
} }

View File

@ -10,9 +10,9 @@
* @file: nana/gui/drawing.cpp * @file: nana/gui/drawing.cpp
*/ */
#include "detail/basic_window.hpp"
#include <nana/gui/drawing.hpp> #include <nana/gui/drawing.hpp>
#include <nana/gui/programming_interface.hpp> #include <nana/gui/programming_interface.hpp>
#include <nana/gui/detail/basic_window.hpp>
namespace nana namespace nana
{ {
@ -22,11 +22,9 @@ namespace nana
{ {
namespace namespace
{ {
using core_window_t = detail::basic_window;
inline detail::drawer& get_drawer(window wd) inline detail::drawer& get_drawer(window wd)
{ {
return reinterpret_cast<core_window_t*>(wd)->drawer; return wd->drawer;
} }
} }
} }
@ -38,7 +36,7 @@ namespace nana
if (!API::is_window(wd)) if (!API::is_window(wd))
throw std::invalid_argument("drawing: invalid window parameter"); throw std::invalid_argument("drawing: invalid window parameter");
if (reinterpret_cast<restrict::core_window_t*>(wd)->is_draw_through()) if (wd->is_draw_through())
throw std::invalid_argument("drawing: the window is draw_through enabled"); throw std::invalid_argument("drawing: the window is draw_through enabled");
} }
@ -46,7 +44,7 @@ namespace nana
bool drawing::empty() const bool drawing::empty() const
{ {
return API::empty_window(handle_) || reinterpret_cast<restrict::core_window_t*>(handle_)->root_graph->empty(); return API::empty_window(handle_) || handle_->root_graph->empty();
} }
void drawing::update() const void drawing::update() const

View File

@ -1062,6 +1062,8 @@ namespace nana
{ {
if(text.length() == start_pos) if(text.length() == start_pos)
return files; return files;
else if(0 == start_pos) //single selection
return {text};
return {}; return {};
} }

View File

@ -12,7 +12,10 @@
* James Bremner * James Bremner
*/ */
#include <nana/gui.hpp> #include <nana/gui/compact.hpp>
#include <nana/gui/msgbox.hpp>
#include <nana/gui/drawing.hpp>
#include <nana/gui/widgets/form.hpp>
#include <nana/gui/widgets/label.hpp> #include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp> #include <nana/gui/widgets/button.hpp>
#include <nana/gui/widgets/spinbox.hpp> #include <nana/gui/widgets/spinbox.hpp>

View File

@ -617,7 +617,7 @@ namespace nana
: std::invalid_argument{ what + " from place implementation " }, : std::invalid_argument{ what + " from place implementation " },
pos{ pos }, pos{ pos },
field { field.empty() ? "unnamed" : field } field(field.empty() ? "unnamed" : field)
{} {}
std::string::size_type pos; std::string::size_type pos;
std::string field; std::string field;
@ -3674,18 +3674,18 @@ namespace nana
std::string field, std::string field,
std::string::size_type pos) std::string::size_type pos)
: std::invalid_argument{ "from widget '" : std::invalid_argument( "from widget '"
+ API::window_caption(plc.window_handle()).substr(0,80) + API::window_caption(plc.window_handle()).substr(0,80)
+ "'; nana::place error " + "'; nana::place error "
+ what + what
+ "' in field '" + field + "' in field '" + field
+ (pos == std::string::npos ? "' " : "' at position " + std::to_string(pos)) + (pos == std::string::npos ? "' " : "' at position " + std::to_string(pos))
+ " in div_text:\n" + plc.div() }, + " in div_text:\n" + plc.div() ),
base_what{ what }, base_what( what ),
owner_caption{ API::window_caption(plc.window_handle()).substr(0,80) }, owner_caption( API::window_caption(plc.window_handle()).substr(0,80) ),
div_text{ plc.div() }, div_text( plc.div() ),
field{ field }, field( field ),
pos{ pos } pos( pos )
{} {}
//end class place //end class place

View File

@ -126,6 +126,12 @@ namespace nana
{ {
close_fn_ = std::move(fn); close_fn_ = std::move(fn);
} }
bool hit_close() const
{
return x_pointed_;
}
private: private:
virtual void attached(widget_reference wdg, graph_reference graph) override virtual void attached(widget_reference wdg, graph_reference graph) override
{ {
@ -140,7 +146,7 @@ namespace nana
//draw caption //draw caption
auto text = to_wstring(API::window_caption(window_handle_)); auto text = to_wstring(API::window_caption(window_handle_));
text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, true); text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, paint::text_renderer::mode::truncate_with_ellipsis);
//draw x button //draw x button
auto r = _m_button_area(); auto r = _m_button_area();
@ -310,6 +316,8 @@ namespace nana
{ {
move_pos += moves_.start_container_pos; move_pos += moves_.start_container_pos;
API::move_window(container_->handle(), move_pos); API::move_window(container_->handle(), move_pos);
if(!caption_.get_drawer_trigger().hit_close())
notifier_->notify_move(); notifier_->notify_move();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -9,18 +9,18 @@
* *
* @file: nana/gui/state_cursor.cpp * @file: nana/gui/state_cursor.cpp
*/ */
#include "detail/basic_window.hpp"
#include <nana/gui/state_cursor.hpp> #include <nana/gui/state_cursor.hpp>
#include <nana/gui/detail/bedrock.hpp> #include <nana/gui/detail/bedrock.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include <nana/gui/detail/window_manager.hpp> #include <nana/gui/detail/window_manager.hpp>
namespace nana namespace nana
{ {
state_cursor::state_cursor(window handle, cursor cur) state_cursor::state_cursor(window wd, cursor cur)
: handle_(handle) : handle_(wd)
{ {
auto & brock = detail::bedrock::instance(); auto & brock = detail::bedrock::instance();
auto wd = reinterpret_cast<detail::basic_window*>(handle);
if (brock.wd_manager().available(wd)) if (brock.wd_manager().available(wd))
brock.define_state_cursor(wd, cur, nullptr); brock.define_state_cursor(wd, cur, nullptr);
else else
@ -39,10 +39,9 @@ namespace nana
{ {
if (handle_) if (handle_)
{ {
nana::internal_scope_guard lock;
auto & brock = detail::bedrock::instance(); auto & brock = detail::bedrock::instance();
auto wd = reinterpret_cast<detail::basic_window*>(handle_); brock.undefine_state_cursor(handle_, nullptr);
if (brock.wd_manager().available(wd))
brock.undefine_state_cursor(wd, nullptr);
} }
handle_ = rhs.handle_; handle_ = rhs.handle_;
rhs.handle_ = nullptr; rhs.handle_ = nullptr;
@ -54,10 +53,9 @@ namespace nana
{ {
if (handle_) if (handle_)
{ {
nana::internal_scope_guard lock;
auto & brock = detail::bedrock::instance(); auto & brock = detail::bedrock::instance();
auto wd = reinterpret_cast<detail::basic_window*>(handle_); brock.undefine_state_cursor(handle_, nullptr);
if (brock.wd_manager().available(wd))
brock.undefine_state_cursor(wd, nullptr);
} }
} }
} }

View File

@ -28,24 +28,26 @@
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
#include <windows.h> #include <windows.h>
#elif defined(NANA_POSIX) #elif defined(NANA_POSIX)
#include "../detail/platform_spec_selector.hpp" #include "../detail/posix/platform_spec.hpp"
#include <nana/system/platform.hpp> #include <nana/system/platform.hpp>
#endif #endif
namespace nana namespace nana
{
namespace detail
{ {
class timer_core; class timer_core;
}
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
typedef UINT_PTR timer_identifier; typedef UINT_PTR timer_identifier;
#else #else
typedef timer_core* timer_identifier; typedef const detail::timer_core* timer_identifier;
#endif #endif
class timer_driver class timer_driver
{ {
typedef std::lock_guard<std::recursive_mutex> lock_guard; friend class detail::timer_core;
friend class timer_core;
timer_driver() = default; timer_driver() = default;
public: public:
@ -56,7 +58,7 @@ namespace nana
} }
template<typename Factory> template<typename Factory>
timer_core* create(unsigned ms, Factory && factory) detail::timer_core* create(unsigned ms, Factory && factory)
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
auto tmid = ::SetTimer(nullptr, 0, ms, &timer_driver::_m_timer_proc); auto tmid = ::SetTimer(nullptr, 0, ms, &timer_driver::_m_timer_proc);
@ -68,9 +70,9 @@ namespace nana
#else #else
auto p = factory(); auto p = factory();
auto tmid = p; auto tmid = p;
::nana::detail::platform_spec::instance().set_timer(reinterpret_cast<std::size_t>(tmid), ms, &timer_driver::_m_timer_proc); ::nana::detail::platform_spec::instance().set_timer(tmid, ms, &timer_driver::_m_timer_proc);
#endif #endif
lock_guard lock(mutex_); ::nana::internal_scope_guard lock;
timer_table_[tmid].reset(p); timer_table_[tmid].reset(p);
return p; return p;
} }
@ -80,16 +82,17 @@ namespace nana
return nullptr; return nullptr;
} }
void destroy(timer_identifier tid) void destroy(timer_identifier handle)
{ {
lock_guard lock(mutex_); ::nana::internal_scope_guard lock;
auto i = timer_table_.find(tid);
auto i = timer_table_.find(handle);
if (i != timer_table_.end()) if (i != timer_table_.end())
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
::KillTimer(nullptr, tid); ::KillTimer(nullptr, handle);
#else #else
::nana::detail::platform_spec::instance().kill_timer(reinterpret_cast<std::size_t>(tid)); ::nana::detail::platform_spec::instance().kill_timer(handle);
#endif #endif
timer_table_.erase(i); timer_table_.erase(i);
} }
@ -98,23 +101,26 @@ namespace nana
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
static void __stdcall _m_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime); static void __stdcall _m_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime);
#else #else
static void _m_timer_proc(std::size_t id); static void _m_timer_proc(timer_identifier id);
#endif #endif
private: private:
std::recursive_mutex mutex_; std::map<timer_identifier, std::unique_ptr<detail::timer_core>> timer_table_;
std::map<timer_identifier, std::unique_ptr<timer_core>> timer_table_;
}; };
class timer_core class detail::timer_core
{ {
public: public:
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
timer_core(timer_identifier tmid, basic_event<arg_elapse>& evt_elapse) timer_core(timer* sender, timer_identifier tmid, basic_event<arg_elapse>& evt_elapse):
: timer_(tmid), evt_elapse_(evt_elapse) sender_(sender),
timer_(tmid),
evt_elapse_(evt_elapse)
{} {}
#else #else
timer_core(basic_event<arg_elapse>& evt_elapse) timer_core(timer* sender, basic_event<arg_elapse>& evt_elapse):
: timer_(this), evt_elapse_(evt_elapse) sender_(sender),
timer_(this),
evt_elapse_(evt_elapse)
{} {}
#endif #endif
@ -128,45 +134,44 @@ namespace nana
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
::SetTimer(nullptr, timer_, ms, &timer_driver::_m_timer_proc); ::SetTimer(nullptr, timer_, ms, &timer_driver::_m_timer_proc);
#else #else
::nana::detail::platform_spec::instance().set_timer(reinterpret_cast<std::size_t>(timer_), ms, &timer_driver::_m_timer_proc); ::nana::detail::platform_spec::instance().set_timer(timer_, ms, &timer_driver::_m_timer_proc);
#endif #endif
} }
void emit(const arg_elapse& arg) void emit()
{ {
arg_elapse arg;
arg.sender = sender_;
evt_elapse_.emit(arg, nullptr); evt_elapse_.emit(arg, nullptr);
} }
private: private:
timer * const sender_;
const timer_identifier timer_; const timer_identifier timer_;
nana::basic_event<arg_elapse> & evt_elapse_; nana::basic_event<arg_elapse> & evt_elapse_;
}; //end class timer_core }; //end class timer_core
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
void __stdcall timer_driver::_m_timer_proc(HWND /*hwnd*/, UINT /*uMsg*/, UINT_PTR id, DWORD /*dwTime*/) void __stdcall timer_driver::_m_timer_proc(HWND /*hwnd*/, UINT /*uMsg*/, UINT_PTR handle, DWORD /*dwTime*/)
#else #else
void timer_driver::_m_timer_proc(std::size_t id) void timer_driver::_m_timer_proc(timer_identifier handle)
#endif #endif
{ {
auto & driver = instance(); auto & time_tbl = instance().timer_table_;
lock_guard lock(driver.mutex_); ::nana::internal_scope_guard lock;
#if defined(NANA_WINDOWS)
auto i = driver.timer_table_.find(id); auto i = time_tbl.find(handle);
#else if (i == time_tbl.end())
auto i = driver.timer_table_.find(reinterpret_cast<timer_identifier>(id));
#endif
if (i == driver.timer_table_.end())
return; return;
arg_elapse arg; i->second->emit();
arg.id = id;
i->second->emit(arg);
} }
struct timer::implement struct timer::implement
{ {
unsigned interval = 1000; //Defaultly 1 second. unsigned interval{ 1000 }; //1 second in default
timer_core * tm_core = nullptr; detail::timer_core * tm_core{ nullptr };
}; };
//class timer //class timer
@ -183,8 +188,7 @@ namespace nana
timer::~timer() timer::~timer()
{ {
if (impl_->tm_core) stop();
timer_driver::instance().destroy(impl_->tm_core->id());
delete impl_; delete impl_;
} }
@ -201,12 +205,12 @@ namespace nana
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
impl_->tm_core = timer_driver::instance().create(impl_->interval, [this](timer_identifier id) impl_->tm_core = timer_driver::instance().create(impl_->interval, [this](timer_identifier id)
{ {
return new timer_core(id, elapse_); return new detail::timer_core(this, id, elapse_);
}); });
#else #else
impl_->tm_core = timer_driver::instance().create(impl_->interval, [this] impl_->tm_core = timer_driver::instance().create(impl_->interval, [this]
{ {
return new timer_core(elapse_); return new detail::timer_core(this, elapse_);
}); });
#endif #endif
} }

View File

@ -261,7 +261,7 @@ namespace nana{ namespace drawerbase
graph.palette(true, text_color); graph.palette(true, text_color);
if (attr_.omitted) if (attr_.omitted)
tr.render(pos, txtptr, txtlen, omitted_pixels, true); tr.render(pos, txtptr, txtlen, omitted_pixels, paint::text_renderer::mode::truncate_with_ellipsis);
else else
#ifdef _nana_std_has_string_view #ifdef _nana_std_has_string_view
graph.bidi_string(pos, { txtptr, txtlen }); graph.bidi_string(pos, { txtptr, txtlen });
@ -276,9 +276,9 @@ namespace nana{ namespace drawerbase
graph.palette(true, color{ colors::white }); graph.palette(true, color{ colors::white });
if(attr_.omitted) if(attr_.omitted)
{ {
tr.render(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen, omitted_pixels, true); tr.render(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen, omitted_pixels, paint::text_renderer::mode::truncate_with_ellipsis);
graph.palette(true, color{ colors::gray }); graph.palette(true, color{ colors::gray });
tr.render(pos, txtptr, txtlen, omitted_pixels, true); tr.render(pos, txtptr, txtlen, omitted_pixels, paint::text_renderer::mode::truncate_with_ellipsis);
} }
else else
{ {

View File

@ -1,7 +1,7 @@
/** /**
* A Categorize Implementation * A Categorize Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -10,7 +10,7 @@
* @file nana/gui/widgets/categorize.cpp * @file nana/gui/widgets/categorize.cpp
*/ */
#include <nana/gui/wvl.hpp> #include <nana/gui/compact.hpp>
#include <nana/gui/widgets/categorize.hpp> #include <nana/gui/widgets/categorize.hpp>
#include <nana/gui/widgets/float_listbox.hpp> #include <nana/gui/widgets/float_listbox.hpp>
#include <nana/gui/element.hpp> #include <nana/gui/element.hpp>

View File

@ -70,13 +70,13 @@ namespace nana{ namespace drawerbase
if (!wdg->enabled()) if (!wdg->enabled())
{ {
graph.palette(true, colors::white); graph.palette(true, colors::white);
tr.render({ 17 + interval, 2 }, title.c_str(), title.length(), pixels); tr.render({ 17 + interval, 2 }, title.c_str(), title.length(), pixels, paint::text_renderer::mode::word_wrap);
graph.palette(true, static_cast<color_rgb>(0x808080)); graph.palette(true, static_cast<color_rgb>(0x808080));
} }
else else
graph.palette(true, wdg->fgcolor()); graph.palette(true, wdg->fgcolor());
tr.render({ 16 + interval, 1 }, title.c_str(), title.length(), pixels); tr.render({ 16 + interval, 1 }, title.c_str(), title.length(), pixels, paint::text_renderer::mode::word_wrap);
} }
//draw crook //draw crook

View File

@ -10,9 +10,9 @@
* @file: nana/gui/widgets/combox.cpp * @file: nana/gui/widgets/combox.cpp
*/ */
#include <nana/gui.hpp> #include <nana/gui/compact.hpp>
#include <nana/gui/widgets/combox.hpp>
#include <nana/gui/element.hpp> #include <nana/gui/element.hpp>
#include <nana/gui/widgets/combox.hpp>
#include <nana/system/dataexch.hpp> #include <nana/system/dataexch.hpp>
#include <nana/gui/widgets/float_listbox.hpp> #include <nana/gui/widgets/float_listbox.hpp>
#include <nana/gui/widgets/skeletons/text_editor.hpp> #include <nana/gui/widgets/skeletons/text_editor.hpp>

View File

@ -15,7 +15,7 @@
* Benjamin Navarro(pr#81) * Benjamin Navarro(pr#81)
* besh81(pr#130) * besh81(pr#130)
* dankan1890(pr#158) * dankan1890(pr#158)
* ErrorFlynn(pr#418) * ErrorFlynn(pr#418,pr#448,pr#454)
* *
*/ */
#include <algorithm> #include <algorithm>
@ -2059,6 +2059,11 @@ namespace nana
}; };
} }
unsigned suspension_width() const
{
return (graph ? graph->text_extent_size(L"...").width : 0);
}
bool cs_status(index_pair abs_pos, bool for_selection) const bool cs_status(index_pair abs_pos, bool for_selection) const
{ {
if (abs_pos.is_category()) if (abs_pos.is_category())
@ -3352,7 +3357,7 @@ namespace nana
else else
{ {
//Default scheme //Default scheme
new_w = (std::max)(new_w, essence_->scheme_ptr->suspension_width + essence_->scheme_ptr->min_column_width); new_w = (std::max)(new_w, essence_->suspension_width() + essence_->scheme_ptr->min_column_width);
} }
if(col.width_px != new_w) if(col.width_px != new_w)
@ -3997,6 +4002,7 @@ namespace nana
if (draw_column) if (draw_column)
{ {
//Draw item text
paint::aligner text_aligner{*graph, col.alignment}; paint::aligner text_aligner{*graph, col.alignment};
unsigned text_margin_right = 0; unsigned text_margin_right = 0;
@ -4142,7 +4148,6 @@ namespace nana
if (graph.text_metrics(as, ds, il)) if (graph.text_metrics(as, ds, il))
essence_->text_height = as + ds; essence_->text_height = as + ds;
essence_->scheme_ptr->suspension_width = graph.text_extent_size("...").width;
essence_->calc_content_size(true); essence_->calc_content_size(true);
} }
@ -4337,7 +4342,7 @@ namespace nana
else else
{ {
auto selected = lister.pick_items(true); auto selected = lister.pick_items(true);
if (selected.cend() != std::find(selected.cbegin(), selected.cend(), item_pos)) if (selected.cend() != std::find(selected.cbegin(), selected.cend(), abs_item_pos))
{ {
//If the current selected one has been selected before selecting, remains the selection states for all //If the current selected one has been selected before selecting, remains the selection states for all
//selected items. But these items will be unselected when the mouse is released. //selected items. But these items will be unselected when the mouse is released.
@ -6114,6 +6119,12 @@ namespace nana
_m_ess().pred_msup_deselect = std::move(predicate); _m_ess().pred_msup_deselect = std::move(predicate);
} }
unsigned listbox::suspension_width() const
{
nana::internal_scope_guard lock;
return _m_ess().suspension_width();
}
drawerbase::listbox::essence & listbox::_m_ess() const drawerbase::listbox::essence & listbox::_m_ess() const
{ {
return get_drawer_trigger().ess(); return get_drawer_trigger().ess();

View File

@ -13,12 +13,13 @@
* dankan1890(pr#158) * dankan1890(pr#158)
*/ */
#include <nana/gui/compact.hpp>
#include <nana/gui/screen.hpp>
#include <nana/gui/widgets/menu.hpp> #include <nana/gui/widgets/menu.hpp>
#include <nana/gui/timer.hpp> #include <nana/gui/timer.hpp>
#include <nana/system/platform.hpp> #include <nana/system/platform.hpp>
#include <nana/gui/element.hpp> #include <nana/gui/element.hpp>
#include <nana/gui/wvl.hpp>
#include <nana/paint/text_renderer.hpp> #include <nana/paint/text_renderer.hpp>
#include <cctype> //introduces tolower #include <cctype> //introduces tolower
#include <vector> #include <vector>
@ -147,7 +148,7 @@ namespace nana
nana::paint::text_renderer tr(graph); nana::paint::text_renderer tr(graph);
auto wstr = to_wstring(text); auto wstr = to_wstring(text);
tr.render(pos, wstr.c_str(), wstr.length(), text_pixels, true); tr.render(pos, wstr.c_str(), wstr.length(), text_pixels, paint::text_renderer::mode::truncate_with_ellipsis);
} }
void sub_arrow(graph_reference graph, const nana::point& pos, unsigned pixels, const attr&) void sub_arrow(graph_reference graph, const nana::point& pos, unsigned pixels, const attr&)

View File

@ -1050,7 +1050,7 @@ namespace nana
std::wstring wtext = to_wstring(item.text); std::wstring wtext = to_wstring(item.text);
tr.render({ m.r.x + 24, m.r.y + static_cast<int>(m.r.height - ts.height) / 2 }, tr.render({ m.r.x + 24, m.r.y + static_cast<int>(m.r.height - ts.height) / 2 },
wtext.c_str(), wtext.length(), basis_.item_pixels - 24 - 18, true); wtext.c_str(), wtext.length(), basis_.item_pixels - 24 - 18, paint::text_renderer::mode::truncate_with_ellipsis);
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Nana GUI Library Definition * Nana GUI Library Definition
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -11,7 +11,8 @@
* the file contains the files required for running of Nana.GUI * the file contains the files required for running of Nana.GUI
*/ */
#include <nana/gui/wvl.hpp> #include <nana/gui/compact.hpp>
#include <nana/gui/widgets/widget.hpp>
#include <nana/gui/detail/bedrock.hpp> #include <nana/gui/detail/bedrock.hpp>
#include <nana/std_thread.hpp> #include <nana/std_thread.hpp>
#include <iostream> #include <iostream>
@ -29,7 +30,7 @@ namespace nana
{ {
void form_loader_private::insert_form(::nana::widget* p) void form_loader_private::insert_form(::nana::widget* p)
{ {
bedrock::instance().manage_form_loader(reinterpret_cast<basic_window*>(p->handle()), true); bedrock::instance().manage_form_loader(p->handle(), true);
} }
} }

View File

@ -260,24 +260,8 @@ namespace detail
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
::TextOut(dw->context, pos.x, pos.y, str, static_cast<int>(len)); ::TextOut(dw->context, pos.x, pos.y, str, static_cast<int>(len));
#elif defined(NANA_X11) #elif defined(NANA_X11)
auto disp = ::nana::detail::platform_spec::instance().open_display();
#if defined(NANA_USE_XFT) #if defined(NANA_USE_XFT)
#if 0
auto fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
//Fixed missing array declaration by dareg
std::unique_ptr<FT_UInt[]> glyphs_ptr(new FT_UInt[len]);
auto glyphs = glyphs_ptr.get();
const auto endstr = str + len;
for(auto chr = str; chr != endstr; ++chr)
{
(*glyphs++) = XftCharIndex(disp, fs, *chr);
}
XftDrawGlyphs(dw->xftdraw, &(dw->xft_fgcolor), fs, pos.x, pos.y + fs->ascent, glyphs_ptr.get(), len);
#else
nana_xft_draw_string(dw->xftdraw, &(dw->xft_fgcolor), dw->font.get(), pos, str, len); nana_xft_draw_string(dw->xftdraw, &(dw->xft_fgcolor), dw->font.get(), pos, str, len);
#endif
#else #else
XFontSet fs = reinterpret_cast<XFontSet>(dw->font->native_handle()); XFontSet fs = reinterpret_cast<XFontSet>(dw->font->native_handle());
XFontSetExtents * ext = ::XExtentsOfFontSet(fs); XFontSetExtents * ext = ::XExtentsOfFontSet(fs);

View File

@ -506,8 +506,8 @@ namespace paint
if (!text.empty()) if (!text.empty())
{ {
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
int * dx = new int[text.size()]; int * dx = new int[text.size()];
SIZE extents; SIZE extents;
::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast<int>(text.size()), 0, 0, dx, &extents); ::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast<int>(text.size()), 0, 0, dx, &extents);
@ -520,27 +520,8 @@ namespace paint
} }
delete[] dx; delete[] dx;
#elif defined(NANA_X11) && defined(NANA_USE_XFT) #elif defined(NANA_X11) && defined(NANA_USE_XFT)
#if 0
auto disp = nana::detail::platform_spec::instance().open_display();
auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
XGlyphInfo extents;
for (std::size_t i = 0; i < text.size(); ++i)
{
if (text[i] != '\t')
{
FT_UInt glyphs = ::XftCharIndex(disp, xft, text[i]);
::XftGlyphExtents(disp, xft, &glyphs, 1, &extents);
pxbuf[i] = extents.xOff;
}
else
pxbuf[i] = tab_pixels;
}
#else
return nana_xft_glyph_pixels(impl_->handle->font.get(), text.data(), text.size()); return nana_xft_glyph_pixels(impl_->handle->font.get(), text.data(), text.size());
#endif #endif
#endif
} }
return pxbuf; return pxbuf;
} }
@ -1108,7 +1089,7 @@ namespace paint
::nana::color graphics::palette(bool for_text) const ::nana::color graphics::palette(bool for_text) const
{ {
if (impl_->handle) if (impl_->handle)
return static_cast<color_rgb>(for_text ? impl_->handle->get_text_color() : impl_->handle->get_color()); return static_cast<color_rgb>(for_text ? impl_->handle->fgcolor_rgb : impl_->handle->bgcolor_rgb);
return{}; return{};
} }
@ -1140,7 +1121,7 @@ namespace paint
if (impl_->handle) if (impl_->handle)
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
::SetPixel(impl_->handle->context, x, y, NANA_RGB(impl_->handle->get_color())); ::SetPixel(impl_->handle->context, x, y, impl_->handle->bgcolor_native);
#elif defined(NANA_X11) #elif defined(NANA_X11)
Display* disp = nana::detail::platform_spec::instance().open_display(); Display* disp = nana::detail::platform_spec::instance().open_display();
impl_->handle->update_color(); impl_->handle->update_color();
@ -1336,14 +1317,14 @@ namespace paint
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
if (pos1 != pos2) if (pos1 != pos2)
{ {
auto prv_pen = ::SelectObject(impl_->handle->context, ::CreatePen(PS_SOLID, 1, NANA_RGB(impl_->handle->get_color()))); auto prv_pen = ::SelectObject(impl_->handle->context, ::CreatePen(PS_SOLID, 1, impl_->handle->bgcolor_native));
::MoveToEx(impl_->handle->context, pos1.x, pos1.y, 0); ::MoveToEx(impl_->handle->context, pos1.x, pos1.y, 0);
::LineTo(impl_->handle->context, pos2.x, pos2.y); ::LineTo(impl_->handle->context, pos2.x, pos2.y);
::DeleteObject(::SelectObject(impl_->handle->context, prv_pen)); ::DeleteObject(::SelectObject(impl_->handle->context, prv_pen));
} }
::SetPixel(impl_->handle->context, pos2.x, pos2.y, NANA_RGB(impl_->handle->get_color())); ::SetPixel(impl_->handle->context, pos2.x, pos2.y, impl_->handle->bgcolor_native);
#elif defined(NANA_X11) #elif defined(NANA_X11)
Display* disp = nana::detail::platform_spec::instance().open_display(); Display* disp = nana::detail::platform_spec::instance().open_display();
impl_->handle->update_color(); impl_->handle->update_color();
@ -1369,7 +1350,7 @@ namespace paint
{ {
if (!impl_->handle) return; if (!impl_->handle) return;
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
auto prv_pen = ::SelectObject(impl_->handle->context, ::CreatePen(PS_SOLID, 1, NANA_RGB(impl_->handle->get_color()))); auto prv_pen = ::SelectObject(impl_->handle->context, ::CreatePen(PS_SOLID, 1, impl_->handle->bgcolor_native));
::LineTo(impl_->handle->context, pos.x, pos.y); ::LineTo(impl_->handle->context, pos.x, pos.y);
@ -1402,7 +1383,7 @@ namespace paint
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
auto brush = ::CreateSolidBrush(NANA_RGB(impl_->handle->get_color())); auto brush = ::CreateSolidBrush(impl_->handle->bgcolor_native);
::RECT native_r = { r.x, r.y, r.right(), r.bottom()}; ::RECT native_r = { r.x, r.y, r.right(), r.bottom()};
@ -1527,6 +1508,7 @@ namespace paint
if (impl_->changed == false) impl_->changed = true; if (impl_->changed == false) impl_->changed = true;
} }
#define NANA_WINDOWS_RGB(a) (((DWORD)(a) & 0xFF)<<16) | ((DWORD)(a) & 0xFF00) | (((DWORD)(a) & 0xFF0000) >> 16 )
void graphics::round_rectangle(const ::nana::rectangle& r, unsigned radius_x, unsigned radius_y, const color& clr, bool solid, const color& solid_clr) void graphics::round_rectangle(const ::nana::rectangle& r, unsigned radius_x, unsigned radius_y, const color& clr, bool solid, const color& solid_clr)
{ {
if (impl_->handle) if (impl_->handle)
@ -1536,8 +1518,8 @@ namespace paint
if (solid) if (solid)
{ {
auto prv_pen = ::SelectObject(impl_->handle->context, ::CreatePen(PS_SOLID, 1, NANA_RGB(impl_->handle->get_color()))); auto prv_pen = ::SelectObject(impl_->handle->context, ::CreatePen(PS_SOLID, 1, impl_->handle->bgcolor_native));
auto prv_brush = ::SelectObject(impl_->handle->context, ::CreateSolidBrush(NANA_RGB(solid_clr.px_color().value))); auto prv_brush = ::SelectObject(impl_->handle->context, ::CreateSolidBrush(NANA_WINDOWS_RGB(solid_clr.px_color().value)));
::RoundRect(impl_->handle->context, r.x, r.y, r.right(), r.bottom(), static_cast<int>(radius_x * 2), static_cast<int>(radius_y * 2)); ::RoundRect(impl_->handle->context, r.x, r.y, r.right(), r.bottom(), static_cast<int>(radius_x * 2), static_cast<int>(radius_y * 2));
@ -1546,7 +1528,7 @@ namespace paint
} }
else else
{ {
auto brush = ::CreateSolidBrush(NANA_RGB(impl_->handle->get_color())); auto brush = ::CreateSolidBrush(impl_->handle->bgcolor_native);
auto region = ::CreateRoundRectRgn(r.x, r.y, r.x + static_cast<int>(r.width) + 1, r.y + static_cast<int>(r.height) + 1, static_cast<int>(radius_x + 1), static_cast<int>(radius_y + 1)); auto region = ::CreateRoundRectRgn(r.x, r.y, r.x + static_cast<int>(r.width) + 1, r.y + static_cast<int>(r.height) + 1, static_cast<int>(radius_x + 1), static_cast<int>(radius_y + 1));

View File

@ -16,7 +16,7 @@ namespace nana
auto const end = str + len; auto const end = str + len;
for(auto i = str; i != end; ++i) for(auto i = str; i != end; ++i)
{ {
if(*i == '\n') if('\n' == *i)
{ {
top += static_cast<int>(f(top, str, i - str)); top += static_cast<int>(f(top, str, i - str));
str = i + 1; str = i + 1;
@ -26,212 +26,180 @@ namespace nana
f(top, str, end - str); f(top, str, end - str);
} }
struct draw_string
{
drawable_type dw;
const int x, endpos;
align text_align;
draw_string(drawable_type dw, int x, int endpos, align ta) class string_drawer
: dw(dw), x(x), endpos(endpos), text_align(ta) {
{} public:
string_drawer(graphics& graph, int left, int right, align ta, bool use_ellipsis):
graph_(graph),
left_(left),
right_(right),
text_align_(ta)
{
if (use_ellipsis)
{
#ifdef _nana_std_has_string_view
ellipsis_px_ = graph.text_extent_size(std::string_view{ "...", 3 }).width;
#else
ellipsis_px_ = graph.text_extent_size("...", 3).width;
#endif
}
}
unsigned operator()(const int top, const wchar_t * buf, std::size_t bufsize) unsigned operator()(const int top, const wchar_t * buf, std::size_t bufsize)
{ {
auto const drawable = graph_.handle();
auto const reordered = unicode_reorder(buf, bufsize); auto const reordered = unicode_reorder(buf, bufsize);
if (reordered.empty())
return 0;
nana::point pos{ x, top }; unsigned return_max_height = 0;
unsigned pixels = 0; unsigned string_px = 0;
std::vector<nana::size> word_metrics;
for (auto & ent : reordered)
{
auto word_sz = detail::text_extent_size(drawable, ent.begin, ent.end - ent.begin);
word_metrics.push_back(word_sz);
string_px += word_sz.width;
if (word_sz.height > return_max_height)
return_max_height = word_sz.height;
}
auto text_align = text_align_;
// Checks if ellipsis is enabled and the total pixels of string is larger than the space.
if (ellipsis_px_ && (static_cast<int>(string_px) > right_ - left_))
{
//The string should be drawn from left most point no matter what text align is.
text_align = align::left;
}
nana::point pos{ left_, top };
auto wdm = word_metrics.data();
switch (text_align) switch (text_align)
{ {
case align::left: case align::left:
for (auto & ent : reordered) for (auto & ent : reordered)
{ {
std::size_t len = ent.end - ent.begin; if (pos.x + static_cast<int>(wdm->width) > 0)
nana::size ts = detail::text_extent_size(dw, ent.begin, len); {
if (pos.x + static_cast<int>(wdm->width) <= right_ - static_cast<int>(ellipsis_px_))
{
//This word can be fully painted.
detail::draw_string(drawable, pos, ent.begin, ent.end - ent.begin);
}
else
{
//This word is painted partially. Firstly, paints the word on a dummy graphics buffer.
if(ts.height > pixels) pixels = ts.height; nana::rectangle r{ nana::size{ static_cast<unsigned>(right_ - ellipsis_px_) - pos.x, wdm->height } };
if(pos.x + static_cast<int>(ts.width) > 0) nana::paint::graphics dummy({ r.width, r.height });
detail::draw_string(dw, pos, ent.begin, len); dummy.typeface(graph_.typeface());
pos.x += static_cast<int>(ts.width); dummy.bitblt(r, graph_, pos);
if(pos.x >= endpos)
#ifdef _nana_std_has_string_view
dummy.string({}, { ent.begin, static_cast<unsigned>(ent.end - ent.begin) }, graph_.palette(true));
#else
dummy.palette(true, graph_.palette(true));
dummy.string({}, ent.begin, ent.end - ent.begin);
#endif
r.x = pos.x;
r.y = top;
graph_.bitblt(r, dummy);
if (ellipsis_px_)
detail::draw_string(drawable, point{ right_ - static_cast<int>(ellipsis_px_), top }, L"...", 3);
break; break;
} }
}
pos.x += static_cast<int>(wdm->width);
if (pos.x > right_ - static_cast<int>(ellipsis_px_))
break;
++wdm;
}
break; break;
case align::center: case align::center:
{ pos.x = (right_ - left_ - string_px) / 2;
unsigned lenpx = 0;
std::unique_ptr<unsigned[]> entity_pxs(new unsigned[reordered.size()]);
auto ent_px = entity_pxs.get();
for (auto & ent : reordered) for (auto & ent : reordered)
{ {
auto ts = detail::text_extent_size(dw, ent.begin, ent.end - ent.begin); detail::draw_string(drawable, pos, ent.begin, ent.end - ent.begin);
if(ts.height > pixels) pixels = ts.height; pos.x += (wdm++)->width;
lenpx += ts.width;
*ent_px++ = ts.width;
}
pos.x += (endpos - pos.x - static_cast<int>(lenpx))/2;
ent_px = entity_pxs.get();
for(auto & ent : reordered)
{
if (pos.x + static_cast<int>(*ent_px) > 0)
detail::draw_string(dw, pos, ent.begin, ent.end - ent.begin);
pos.x += static_cast<int>(*ent_px++);
if(pos.x >= endpos)
break;
}
} }
break; break;
case align::right: case align::right:
{ wdm = word_metrics.data() + word_metrics.size() - 1;
int xend = endpos; pos.x = right_;
std::swap(pos.x, xend);
for (auto i = reordered.crbegin(); i != reordered.crend(); ++i) for (auto i = reordered.crbegin(); i != reordered.crend(); ++i)
{ {
auto & ent = *i; pos.x -= (wdm--)->width;
std::size_t len = ent.end - ent.begin; detail::draw_string(drawable, pos, i->begin, i->end - i->begin);
nana::size ts = detail::text_extent_size(dw, ent.begin, len);
if(ts.height > pixels) pixels = ts.height;
if(pos.x > xend)
{
pos.x -= static_cast<int>(ts.width);
detail::draw_string(dw, pos, i->begin, len);
}
if(pos.x <= xend || pos.x <= 0)
break;
}
} }
break; break;
} }
return pixels; return return_max_height;
}
};
struct draw_string_omitted
{
graphics & graph;
int x, endpos;
unsigned omitted_pixels;
draw_string_omitted(graphics& graph, int x, int endpos, bool omitted)
: graph(graph), x(x), endpos(endpos)
{
#ifdef _nana_std_has_string_view
omitted_pixels = (omitted ? graph.text_extent_size(std::string_view{ "...", 3 }).width : 0);
#else
omitted_pixels = (omitted ? graph.text_extent_size("...", 3).width : 0);
#endif
if (endpos - x > static_cast<int>(omitted_pixels))
this->endpos -= omitted_pixels;
else
this->endpos = x;
}
unsigned operator()(const int top, const wchar_t * buf, std::size_t bufsize)
{
drawable_type dw = graph.handle();
::nana::point pos{ x, top };
unsigned pixels = 0;
auto const reordered = unicode_reorder(buf, bufsize);
for(auto & i : reordered)
{
std::size_t len = i.end - i.begin;
nana::size ts = detail::text_extent_size(dw, i.begin, len);
if(ts.height > pixels) pixels = ts.height;
if(pos.x + static_cast<int>(ts.width) <= endpos)
{
detail::draw_string(dw, pos, i.begin, len);
pos.x += static_cast<int>(ts.width);
}
else
{
nana::rectangle r;
r.width = endpos - pos.x;
r.height = ts.height;
nana::paint::graphics dum_graph({ r.width, r.height });
dum_graph.bitblt(r, graph, pos);
#ifdef _nana_std_has_string_view
dum_graph.string({}, { i.begin, len }, graph.palette(true));
#else
dum_graph.palette(true, graph.palette(true));
dum_graph.string({}, i.begin, len);
#endif
r.x = pos.x;
r.y = top;
graph.bitblt(r, dum_graph);
if(omitted_pixels)
detail::draw_string(dw, point{ endpos, top }, L"...", 3);
break;
}
}
return pixels;
} }
private:
graphics& graph_;
const int left_, right_; //the range of rendering area in x-axis
const align text_align_;
unsigned ellipsis_px_{ 0 };
}; };
struct draw_string_auto_changing_lines struct draw_string_auto_changing_lines
{ {
graphics & graph; graphics & graph;
int x, endpos; const int left, right;
align text_align; const align text_align;
draw_string_auto_changing_lines(graphics& graph, int x, int endpos, align ta) draw_string_auto_changing_lines(graphics& graph, int left, int right, align ta):
: graph(graph), x(x), endpos(endpos), text_align(ta) graph(graph),
left(left),
right(right),
text_align(ta)
{} {}
unsigned operator()(const int top, const wchar_t * buf, std::size_t bufsize) unsigned operator()(const int top, const wchar_t * buf, std::size_t bufsize)
{ {
unsigned pixels = 0; unsigned return_max_height = 0;
auto const dw = graph.handle(); auto const drawable = graph.handle();
unsigned str_w = 0; unsigned string_px = 0;
std::vector<nana::size> ts_keeper; std::vector<nana::size> word_metrics;
auto const reordered = unicode_reorder(buf, bufsize); auto const reordered = unicode_reorder(buf, bufsize);
for(auto & i : reordered) for(auto & i : reordered)
{ {
nana::size ts = detail::text_extent_size(dw, i.begin, i.end - i.begin); auto word_sz = detail::text_extent_size(drawable, i.begin, i.end - i.begin);
if(ts.height > pixels) pixels = ts.height;
ts_keeper.emplace_back(ts); word_metrics.emplace_back(word_sz);
str_w += ts.width; string_px += word_sz.width;
if (return_max_height < word_sz.height)
return_max_height = word_sz.height;
} }
const nana::size* wdm = word_metrics.data();
//Test whether the text needs the new line. //Test whether the text needs the new line.
if(x + static_cast<int>(str_w) > endpos) if(left + static_cast<int>(string_px) > right)
{ {
pixels = 0; unsigned max_height = 0;
unsigned line_pixels = 0;
nana::point pos{ x, top }; nana::point pos{ left, top };
int orig_top = top; const int orig_top = top;
auto i_ts_keeper = ts_keeper.cbegin();
for(auto & i : reordered) for(auto & i : reordered)
{ {
if(line_pixels < i_ts_keeper->height) if(max_height < wdm->height)
line_pixels = i_ts_keeper->height; max_height = wdm->height;
bool beyond_edge = (pos.x + static_cast<int>(i_ts_keeper->width) > endpos); bool beyond_edge = (pos.x + static_cast<int>(wdm->width) > right);
if(beyond_edge) if(beyond_edge)
{ {
const std::size_t len = i.end - i.begin; const std::size_t len = i.end - i.begin;
@ -251,10 +219,10 @@ namespace nana
{ {
auto pxbuf = pixel_buf.get(); auto pxbuf = pixel_buf.get();
idx_splitted = find_splitted(idx_head, len, pos.x, endpos, pxbuf); idx_splitted = find_splitted(idx_head, len, pos.x, right, pxbuf);
if(idx_splitted == len) if(idx_splitted == len)
{ {
detail::draw_string(dw, pos, i.begin + idx_head, idx_splitted - idx_head); detail::draw_string(drawable, pos, i.begin + idx_head, idx_splitted - idx_head);
for(std::size_t i = idx_head; i < len; ++i) for(std::size_t i = idx_head; i < len; ++i)
pos.x += static_cast<int>(pxbuf[i]); pos.x += static_cast<int>(pxbuf[i]);
@ -264,17 +232,16 @@ namespace nana
//Check the word whether it is splittable. //Check the word whether it is splittable.
if(splittable(i.begin, idx_splitted)) if(splittable(i.begin, idx_splitted))
{ {
detail::draw_string(dw, pos, i.begin + idx_head, idx_splitted - idx_head); detail::draw_string(drawable, pos, i.begin + idx_head, idx_splitted - idx_head);
idx_head = idx_splitted; idx_head = idx_splitted;
pos.x = x; pos.x = left;
pos.y += static_cast<int>(line_pixels); pos.y += static_cast<int>(max_height);
line_pixels = i_ts_keeper->height;
} }
else else
{ {
//Search the splittable character from idx_head to idx_splitted //Search the splittable character from idx_head to idx_splitted
const wchar_t * u = i.begin + idx_splitted; const wchar_t * u = i.begin + idx_splitted;
const wchar_t * head = i.begin + idx_head; const wchar_t * const head = i.begin + idx_head;
for(; head < u; --u) for(; head < u; --u)
{ {
@ -284,112 +251,102 @@ namespace nana
if(u != head) if(u != head)
{ {
detail::draw_string(dw, pos, head, u - head); detail::draw_string(drawable, pos, head, u - head);
idx_head += u - head; idx_head += u - head;
pos.x = x; pos.x = left;
pos.y += static_cast<int>(line_pixels); pos.y += static_cast<int>(max_height);
line_pixels = i_ts_keeper->height;
} }
else else
{ {
u = i.begin + idx_splitted; u = i.begin + idx_splitted;
const wchar_t * end = i.begin + len; for(; u < i.begin + len; ++u)
for(; u < end; ++u)
{ {
if(splittable(head, u - head)) if(splittable(head, u - head))
break; break;
} }
std::size_t splen = u - head; std::size_t splen = u - head;
pos.y += static_cast<int>(line_pixels); pos.y += static_cast<int>(max_height);
pos.x = x; pos.x = left;
detail::draw_string(dw, pos, head, splen); detail::draw_string(drawable, pos, head, splen);
line_pixels = i_ts_keeper->height;
for(std::size_t k = idx_head; k < idx_head + splen; ++k) for(std::size_t k = idx_head; k < idx_head + splen; ++k)
pos.x += static_cast<int>(pxbuf[k]); pos.x += static_cast<int>(pxbuf[k]);
if (pos.x >= endpos) if (pos.x >= right)
{ {
pos.x = x; pos.x = left;
pos.y += static_cast<int>(line_pixels); pos.y += static_cast<int>(wdm->height);
} }
idx_head += splen; idx_head += splen;
} }
} }
max_height = wdm->height;
}while(idx_head < len); }while(idx_head < len);
} }
else else
{ {
pos.x = x; pos.x = left;
pos.y += static_cast<int>(line_pixels); pos.y += static_cast<int>(max_height);
detail::draw_string(dw, pos, i.begin, 1); detail::draw_string(drawable, pos, i.begin, 1);
pos.x += static_cast<int>(i_ts_keeper->width); pos.x += static_cast<int>(wdm->width);
} }
line_pixels = 0; max_height = 0;
} }
else else
{ {
detail::draw_string(dw, pos, i.begin, i.end - i.begin); detail::draw_string(drawable, pos, i.begin, i.end - i.begin);
pos.x += static_cast<int>(i_ts_keeper->width); pos.x += static_cast<int>(wdm->width);
} }
++i_ts_keeper; ++wdm;
} }
pixels = (top - orig_top) + line_pixels; return_max_height = (top - orig_top) + max_height;
} }
else else
{ {
point pos{ left, top };
//The text could be drawn in a line. //The text could be drawn in a line.
if((align::left == text_align) || (align::center == text_align)) if((align::left == text_align) || (align::center == text_align))
{ {
point pos{ x, top };
if(align::center == text_align) if(align::center == text_align)
pos.x += (endpos - x - static_cast<int>(str_w)) / 2; pos.x += (right - left - static_cast<int>(string_px)) / 2;
auto i_ts_keeper = ts_keeper.cbegin();
for(auto & ent : reordered) for(auto & ent : reordered)
{ {
const nana::size & ts = *i_ts_keeper; if (pos.x + static_cast<int>(wdm->width) > 0)
detail::draw_string(drawable, pos, ent.begin, ent.end - ent.begin);
if (pos.x + static_cast<int>(ts.width) > 0) pos.x += static_cast<int>(wdm->width);
detail::draw_string(dw, pos, ent.begin, ent.end - ent.begin); ++wdm;
pos.x += static_cast<int>(ts.width);
++i_ts_keeper;
} }
} }
else if(align::right == text_align) else if(align::right == text_align)
{ {
point pos{ endpos, top }; pos.x = right;
auto i_ts_keeper = ts_keeper.crbegin();
for(auto i = reordered.crbegin(); i != reordered.crend(); ++i) for(auto i = reordered.crbegin(); i != reordered.crend(); ++i)
{ {
if (pos.x < 0)
break;
auto & ent = *i; auto & ent = *i;
std::size_t len = ent.end - ent.begin; std::size_t len = ent.end - ent.begin;
const nana::size & ts = *i_ts_keeper;
pos.x -= static_cast<int>(ts.width); pos.x -= static_cast<int>(wdm->width);
if (pos.x >= 0) detail::draw_string(drawable, pos, ent.begin, len);
detail::draw_string(dw, pos, ent.begin, len); ++wdm;
++i_ts_keeper;
} }
} }
} }
return pixels; return return_max_height;
} }
static std::size_t find_splitted(std::size_t begin, std::size_t end, int x, int endpos, unsigned * pxbuf) static std::size_t find_splitted(std::size_t begin, std::size_t end, int x, int endpos, unsigned * pxbuf)
{ {
unsigned acc_width = 0;
for (std::size_t i = begin; i < end; ++i) for (std::size_t i = begin; i < end; ++i)
{ {
if(x + static_cast<int>(acc_width + pxbuf[i]) > endpos) if ((x += static_cast<int>(pxbuf[i])) > endpos)
{ return (begin == i ? i + 1 : i);
if(i == begin)
++i;
return i;
}
acc_width += pxbuf[i];
} }
return end; return end;
} }
@ -399,12 +356,11 @@ namespace nana
wchar_t ch = str[index]; wchar_t ch = str[index];
if(('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) if(('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
{ {
wchar_t prch;
if(index) if(index)
{ {
prch = str[index - 1]; auto prch = str[index - 1];
if('0' <= ch && ch <= '9') if('0' <= ch && ch <= '9')
return !(('0' <= prch && prch <= '9') || (str[index - 1] == '-')); return !(('0' <= prch && prch <= '9') || (prch == '-'));
return (('z' < prch || prch < 'a') && ('Z' < prch || prch < 'A')); return (('z' < prch || prch < 'a') && ('Z' < prch || prch < 'A'));
} }
@ -418,44 +374,53 @@ namespace nana
struct extent_auto_changing_lines struct extent_auto_changing_lines
{ {
graphics & graph; graphics & graph;
int x, endpos; const int left, right;
unsigned extents; unsigned extents;
extent_auto_changing_lines(graphics& graph, int x, int endpos) extent_auto_changing_lines(graphics& graph, int left, int right):
: graph(graph), x(x), endpos(endpos), extents(0) graph(graph),
left(left),
right(right),
extents(0)
{} {}
unsigned operator()(int top, const wchar_t * buf, std::size_t bufsize) unsigned operator()(int top, const wchar_t * buf, std::size_t bufsize)
{ {
unsigned pixels = 0; unsigned return_max_height = 0;
drawable_type dw = graph.handle(); auto drawable = graph.handle();
unsigned str_w = 0;
std::vector<nana::size> ts_keeper;
std::vector<nana::size> word_metrics;
unsigned string_px = 0;
auto const reordered = unicode_reorder(buf, bufsize); auto const reordered = unicode_reorder(buf, bufsize);
for(auto & i : reordered) for(auto & i : reordered)
{ {
nana::size ts = detail::text_extent_size(dw, i.begin, i.end - i.begin); auto word_sz = detail::text_extent_size(drawable, i.begin, i.end - i.begin);
ts_keeper.emplace_back(ts); word_metrics.emplace_back(word_sz);
str_w += ts.width; string_px += word_sz.width;
if (return_max_height < word_sz.height)
return_max_height = word_sz.height;
} }
auto i_ts_keeper = ts_keeper.cbegin();
//Test whether the text needs the new line. //Test whether the text needs the new line.
if(x + static_cast<int>(str_w) > endpos) if(left + static_cast<int>(string_px) > right)
{ {
unsigned line_pixels = 0; unsigned max_height = 0;
int xpos = x; int xpos = left;
int orig_top = top; const int orig_top = top;
auto wdm = word_metrics.data();
for(auto & i : reordered) for(auto & i : reordered)
{ {
if(line_pixels < i_ts_keeper->height) if(max_height < wdm->height)
line_pixels = i_ts_keeper->height; max_height = wdm->height;
bool beyond_edge = (xpos + static_cast<int>(i_ts_keeper->width) > endpos); bool beyond_edge = (xpos + static_cast<int>(wdm->width) > right);
if(beyond_edge) if(beyond_edge)
{ {
std::size_t len = i.end - i.begin; std::size_t len = i.end - i.begin;
@ -475,21 +440,22 @@ namespace nana
do do
{ {
idx_splitted = draw_string_auto_changing_lines::find_splitted(idx_head, len, xpos, endpos, pxbuf); idx_splitted = draw_string_auto_changing_lines::find_splitted(idx_head, len, xpos, right, pxbuf);
if(idx_splitted == len) if(idx_splitted == len)
{ {
for(std::size_t i = idx_head; i < len; ++i) for(std::size_t i = idx_head; i < len; ++i)
xpos += static_cast<int>(pxbuf[i]); xpos += static_cast<int>(pxbuf[i]);
break; break;
} }
//Check the word whether it is splittable. //Check the word whether it is splittable.
if(draw_string_auto_changing_lines::splittable(i.begin, idx_splitted)) if(draw_string_auto_changing_lines::splittable(i.begin, idx_splitted))
{ {
idx_head = idx_splitted; idx_head = idx_splitted;
xpos = x; xpos = left;
top += line_pixels; top += max_height;
line_pixels = i_ts_keeper->height; max_height = wdm->height;
} }
else else
{ {
@ -503,14 +469,11 @@ namespace nana
break; break;
} }
if(u != head) xpos = left;
{ top += max_height;
idx_head += u - head; max_height = wdm->height;
xpos = x;
top += line_pixels; if(u == head)
line_pixels = i_ts_keeper->height;
}
else
{ {
u = i.begin + idx_splitted; u = i.begin + idx_splitted;
const wchar_t * end = i.begin + len; const wchar_t * end = i.begin + len;
@ -520,52 +483,45 @@ namespace nana
break; break;
} }
std::size_t splen = u - head; std::size_t splen = u - head;
top += line_pixels;
xpos = x;
line_pixels = i_ts_keeper->height;
for(std::size_t k = idx_head; k < idx_head + splen; ++k) for(std::size_t k = idx_head; k < idx_head + splen; ++k)
xpos += static_cast<int>(pxbuf[k]); xpos += static_cast<int>(pxbuf[k]);
if(xpos >= endpos) if(xpos >= right)
{ {
xpos = x; xpos = left;
top += line_pixels; top += max_height;
} }
idx_head += splen; idx_head += splen;
} }
else
idx_head += u - head;
} }
}while(idx_head < len); }while(idx_head < len);
} }
else else
xpos = x + static_cast<int>(i_ts_keeper->width); xpos = left + static_cast<int>(wdm->width);
line_pixels = 0; max_height = 0;
} }
else else
xpos += static_cast<int>(i_ts_keeper->width); xpos += static_cast<int>(wdm->width);
++i_ts_keeper; ++wdm;
} }
pixels = (top - orig_top) + line_pixels; return_max_height = (top - orig_top) + max_height;
} }
else
{ extents += return_max_height;
while(i_ts_keeper != ts_keeper.cend()) return return_max_height;
{
const nana::size & ts = *(i_ts_keeper++);
if(ts.height > pixels) pixels = ts.height;
}
}
extents += pixels;
return pixels;
} }
}; };
}//end namespace helper }//end namespace helper
//class text_renderer //class text_renderer
text_renderer::text_renderer(graph_reference graph, align ta) text_renderer::text_renderer(graph_reference graph, align ta):
: graph_(graph), text_align_(ta) graph_(graph),
text_align_(ta)
{} {}
nana::size text_renderer::extent_size(int x, int y, const wchar_t* str, std::size_t len, unsigned restricted_pixels) const nana::size text_renderer::extent_size(int x, int y, const wchar_t* str, std::size_t len, unsigned restricted_pixels) const
@ -585,28 +541,27 @@ namespace nana
{ {
if (graph_) if (graph_)
{ {
helper::draw_string ds(graph_.handle(), pos.x, static_cast<int>(graph_.width()), text_align_); helper::string_drawer sd{ graph_, pos.x, pos.x + static_cast<int>(graph_.width()), text_align_, false };
helper::for_each_line(str, len, pos.y, ds); helper::for_each_line(str, len, pos.y, sd);
} }
} }
void text_renderer::render(const point& pos, const wchar_t* str, std::size_t len, unsigned restricted_pixels, bool omitted) void text_renderer::render(const point& pos, const wchar_t* str, std::size_t len, unsigned space_pixels, mode rendering_mode)
{ {
if (graph_) if (graph_ && str && len && space_pixels)
{ {
helper::draw_string_omitted dso(graph_, pos.x, pos.x + static_cast<int>(restricted_pixels), omitted); if (mode::truncate_letter_with_ellipsis == rendering_mode || mode::truncate_with_ellipsis == rendering_mode)
helper::for_each_line(str, len, pos.y, dso); {
helper::string_drawer sd{ graph_, pos.x, pos.x + static_cast<int>(space_pixels), text_align_, true };
helper::for_each_line(str, len, pos.y, sd);
} }
} else if (mode::word_wrap == rendering_mode)
void text_renderer::render(const point& pos, const wchar_t * str, std::size_t len, unsigned restricted_pixels)
{ {
if (graph_) helper::draw_string_auto_changing_lines dsacl(graph_, pos.x, pos.x + static_cast<int>(space_pixels), text_align_);
{
helper::draw_string_auto_changing_lines dsacl(graph_, pos.x, pos.x + static_cast<int>(restricted_pixels), text_align_);
helper::for_each_line(str, len, pos.y, dsacl); helper::for_each_line(str, len, pos.y, dsacl);
} }
} }
}
//end class text_renderer //end class text_renderer
//class aligner //class aligner

View File

@ -15,15 +15,14 @@
#include <nana/paint/graphics.hpp> #include <nana/paint/graphics.hpp>
#include <nana/paint/pixel_buffer.hpp> #include <nana/paint/pixel_buffer.hpp>
#include <vector> #include <vector>
#include <cassert>
#include <cstring> #include <cstring>
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
# include <windows.h> # include <windows.h>
#elif defined(NANA_X11) #elif defined(NANA_X11)
# include "../detail/platform_spec_selector.hpp"
# include <nana/gui/detail/bedrock.hpp> # include <nana/gui/detail/bedrock.hpp>
# include <nana/gui/detail/basic_window.hpp> # include "../detail/platform_spec_selector.hpp"
# include "../gui/detail/basic_window.hpp"
#endif #endif
namespace nana{ namespace system{ namespace nana{ namespace system{
@ -71,7 +70,6 @@ namespace nana{ namespace system{
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
HDC hDC = ::GetDC(NULL); HDC hDC = ::GetDC(NULL);
if (::GetDIBits(hDC, (HBITMAP)g.pixmap(), 0, 1, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS) == 0) { if (::GetDIBits(hDC, (HBITMAP)g.pixmap(), 0, 1, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS) == 0) {
assert(false);
::ReleaseDC(NULL, hDC); ::ReleaseDC(NULL, hDC);
return false; return false;
} }
@ -109,7 +107,6 @@ namespace nana{ namespace system{
::CloseClipboard(); ::CloseClipboard();
} }
} }
assert(false);
::GlobalFree(h_gmem); ::GlobalFree(h_gmem);
return false; return false;
@ -266,8 +263,8 @@ namespace nana{ namespace system{
spec.lock_xlib(); spec.lock_xlib();
{ {
internal_scope_guard isg; internal_scope_guard lock;
detail::bedrock::core_window_t * wd = detail::bedrock::instance().focus(); auto wd = detail::bedrock::instance().focus();
if(wd) requester = wd->root; if(wd) requester = wd->root;
} }
spec.unlock_xlib(); spec.unlock_xlib();

View File

@ -141,6 +141,7 @@ namespace threads
::pthread_join(thr->handle, 0); ::pthread_join(thr->handle, 0);
::pthread_detach(thr->handle); ::pthread_detach(thr->handle);
#endif #endif
delete thr;
} }
std::lock_guard<decltype(mutex_)> lock(mutex_); std::lock_guard<decltype(mutex_)> lock(mutex_);

View File

@ -1,3 +1,17 @@
/*
* Unicode Bidi-Language Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2019 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/unicode_bidi.cpp
* @contributors:
* glavangeorge(pr#440)
*/
#include <nana/unicode_bidi.hpp> #include <nana/unicode_bidi.hpp>
#include <nana/c++defines.hpp> #include <nana/c++defines.hpp>