Merge branch 'hotfixes-1.0.2' into develop

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

View File

@ -123,7 +123,7 @@ execute_process(COMMAND ${CMAKE_COMMAND}
${CMAKE_CURRENT_SOURCE_DIR}/include/nana/)
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(NANA_SOURCE_DIR ${CMAKE_SOURCE_DIR}/source)
@ -161,3 +161,5 @@ install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include)
set_property( TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14 )

View File

@ -28,6 +28,10 @@ Run it! All dependencies will be resovled automatically by biicode! Amazing, isn
The best way to get help with Nana library is by visiting http://nanapro.org/help.htm
## Sending a Pull Request ?
This project is encourage you to contribute it through sending a pull request! There is a simple rule, please **don't** directly commit your contributions to the **master** branch. According to your commits, please choose the **hotfixes** branch or the **develop** branch. Thank you!
## Introduction to the Repository
There are two main branches with an infinite lifetime:

View File

@ -67,24 +67,32 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>../bin/vc2013/</OutDir>
<OutDir>../bin/</OutDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<OutDir>../bin/vc2013/</OutDir>
<OutDir>../bin/</OutDir>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>../bin/vc2013/</OutDir>
<OutDir>../bin/</OutDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<OutDir>../bin/vc2013/</OutDir>
<OutDir>../bin/</OutDir>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -102,7 +110,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -119,7 +127,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -141,7 +149,7 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -162,7 +170,7 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<OutputFile>$(OutDir)\nana_$(ConfigurationName)_$(PlatformShortName).lib</OutputFile>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
@ -177,6 +185,7 @@
<ClCompile Include="..\..\source\deploy.cpp" />
<ClCompile Include="..\..\source\detail\win32\platform_spec.cpp" />
<ClCompile Include="..\..\source\exceptions.cpp" />
<ClCompile Include="..\..\source\filesystem\filesystem.cpp" />
<ClCompile Include="..\..\source\filesystem\file_iterator.cpp" />
<ClCompile Include="..\..\source\filesystem\fs_utility.cpp" />
<ClCompile Include="..\..\source\gui\animation.cpp" />
@ -247,6 +256,9 @@
<ClCompile Include="..\..\source\traits.cpp" />
<ClCompile Include="..\..\source\unicode_bidi.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\nana\filesystem\filesystem.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -300,5 +300,18 @@
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\filesystem\filesystem.cpp">
<Filter>Source Files\nana\filesystem</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\nana\filesystem\filesystem.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\nana\filesystem\filesystem.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

28
build/vc2015/nana.sln Normal file
View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{25B21068-491B-4A9F-B99F-6C27BF31BAAD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x64.ActiveCfg = Debug|x64
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x64.Build.0 = Debug|x64
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x86.ActiveCfg = Debug|Win32
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x86.Build.0 = Debug|Win32
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x64.ActiveCfg = Release|x64
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x64.Build.0 = Release|x64
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x86.ActiveCfg = Release|Win32
{25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

266
build/vc2015/nana.vcxproj Normal file
View File

@ -0,0 +1,266 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{25B21068-491B-4A9F-B99F-6C27BF31BAAD}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>nana</RootNamespace>
<TargetPlatformVersion>8.1</TargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>../bin/</OutDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<OutDir>../bin/</OutDir>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>../bin/</OutDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<SourcePath>..\..\source;$(VC_SourcePath);</SourcePath>
<OutDir>../bin/</OutDir>
<TargetName>$(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName)</TargetName>
<IntDir>..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\</IntDir>
</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>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</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>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<OutputFile>$(TargetPath)</OutputFile>
</Lib>
</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\win32\platform_spec.cpp" />
<ClCompile Include="..\..\source\exceptions.cpp" />
<ClCompile Include="..\..\source\filesystem\filesystem.cpp" />
<ClCompile Include="..\..\source\filesystem\file_iterator.cpp" />
<ClCompile Include="..\..\source\filesystem\fs_utility.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\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\win32\bedrock.cpp" />
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp" />
<ClCompile Include="..\..\source\gui\detail\window_manager.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\frame.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\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\gadget.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\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\traits.cpp" />
<ClCompile Include="..\..\source\unicode_bidi.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\nana\filesystem\filesystem.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\nana">
<UniqueIdentifier>{b0bd11b1-bcbb-4e05-885e-44295bc1a7bb}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\audio">
<UniqueIdentifier>{aab16aa3-c8d4-4495-8606-1b21ae739ee5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\audio\detail">
<UniqueIdentifier>{c395f107-7102-415b-a019-54e7cf3575af}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\detail">
<UniqueIdentifier>{e2569be2-9e68-477d-8b59-e248595de6c7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\detail\win32">
<UniqueIdentifier>{52ed7f8e-fa48-495e-af1f-4df013205a35}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\filesystem">
<UniqueIdentifier>{87d14798-9015-4162-b9ab-72c741cff063}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\gui">
<UniqueIdentifier>{4f8e7d23-9fe1-4409-bb03-2bd0809e606b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\gui\detail">
<UniqueIdentifier>{85c9c1bb-d87b-4481-bf3c-7425f680a12d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\gui\detail\win32">
<UniqueIdentifier>{8058b530-86ec-4d72-890d-345aa30db056}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\gui\widgets">
<UniqueIdentifier>{87b124cb-408d-460b-a81b-8a788bbae0d9}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\gui\widgets\skeletons">
<UniqueIdentifier>{b10db2f1-0542-421a-9e1d-4357e3be5f68}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\paint">
<UniqueIdentifier>{59f186c8-f5f8-4499-8e19-f278d4754220}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\paint\detail">
<UniqueIdentifier>{5acf1733-47b2-4872-a105-66c7ad15cd39}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\system">
<UniqueIdentifier>{a81fa10e-1274-44e0-92a0-434fa28f89ae}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nana\threads">
<UniqueIdentifier>{e95b4a72-643f-4416-af95-b0bbaf7f0c57}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\source\audio\detail\audio_device.cpp">
<Filter>Source Files\nana\audio\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\detail\audio_stream.cpp">
<Filter>Source Files\nana\audio\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\detail\buffer_preparation.cpp">
<Filter>Source Files\nana\audio\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\audio\player.cpp">
<Filter>Source Files\nana\audio</Filter>
</ClCompile>
<ClCompile Include="..\..\source\detail\win32\platform_spec.cpp">
<Filter>Source Files\nana\detail\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\source\filesystem\file_iterator.cpp">
<Filter>Source Files\nana\filesystem</Filter>
</ClCompile>
<ClCompile Include="..\..\source\filesystem\fs_utility.cpp">
<Filter>Source Files\nana\filesystem</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\win32\bedrock.cpp">
<Filter>Source Files\nana\gui\detail\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\basic_window.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\drawer.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp">
<Filter>Source Files\nana\gui\widgets\skeletons</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\button.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\categorize.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\checkbox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\combox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\form.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\frame.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\label.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\menu.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\menubar.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\panel.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\picture.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\progress.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\slider.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\tabbar.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\textbox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\toolbar.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\treebox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\widget.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\animation.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\basis.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\dragger.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\drawing.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\effects.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\element.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\filebox.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\layout_utility.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\msgbox.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\place.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\programming_interface.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\timer.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\tooltip.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\wvl.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\detail\image_process_provider.cpp">
<Filter>Source Files\nana\paint\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\detail\native_paint_interface.cpp">
<Filter>Source Files\nana\paint\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\gadget.cpp">
<Filter>Source Files\nana\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\graphics.cpp">
<Filter>Source Files\nana\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\image.cpp">
<Filter>Source Files\nana\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\image_process_selector.cpp">
<Filter>Source Files\nana\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\pixel_buffer.cpp">
<Filter>Source Files\nana\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\paint\text_renderer.cpp">
<Filter>Source Files\nana\paint</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\dataexch.cpp">
<Filter>Source Files\nana\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\platform.cpp">
<Filter>Source Files\nana\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\shared_wrapper.cpp">
<Filter>Source Files\nana\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\system\timepiece.cpp">
<Filter>Source Files\nana\system</Filter>
</ClCompile>
<ClCompile Include="..\..\source\threads\pool.cpp">
<Filter>Source Files\nana\threads</Filter>
</ClCompile>
<ClCompile Include="..\..\source\any.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\basic_types.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\charset.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\datetime.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\deploy.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\exceptions.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\traits.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\unicode_bidi.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\element_store.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\bedrock_pi.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\events_operation.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\notifier.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\state_cursor.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\internationalization.cpp">
<Filter>Source Files\nana</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\detail\color_schemes.cpp">
<Filter>Source Files\nana\gui\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\screen.cpp">
<Filter>Source Files\nana\gui</Filter>
</ClCompile>
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp">
<Filter>Source Files\nana\gui\widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\source\filesystem\filesystem.cpp">
<Filter>Source Files\nana\filesystem</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\nana\filesystem\filesystem.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,8 @@ namespace nana{ namespace audio
//class audio_stream
bool audio_stream::open(const nana::string& file)
{
fs_.open(static_cast<std::string>(nana::charset(file)), std::ios::binary);
std::string fname{nana::charset(file)};//static_cast<std::string>()
fs_.open(fname, std::ios::binary);
if(fs_)
{
wave_spec::master_riff_chunk riff;

View File

@ -799,7 +799,7 @@ namespace nana
switch(utf_x_)
{
case unicode::utf8:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
strbuf = detail::utf8_to_utf16(data_, true);
detail::put_utf16char(strbuf, 0, true);
#else
@ -808,7 +808,7 @@ namespace nana
#endif
break;
case unicode::utf16:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
strbuf = data_;
detail::put_utf16char(strbuf, 0, true);
#else
@ -817,7 +817,7 @@ namespace nana
#endif
break;
case unicode::utf32:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
strbuf = detail::utf32_to_utf16(data_);
detail::put_utf16char(strbuf, 0, true);
#else
@ -907,21 +907,21 @@ namespace nana
switch(utf_x_)
{
case unicode::utf8:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
bytes = detail::utf8_to_utf16(data_, true);
#else
bytes = detail::utf8_to_utf32(data_, true);
#endif
break;
case unicode::utf16:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
bytes = data_;
#else
bytes = detail::utf16_to_utf32(data_);
#endif
break;
case unicode::utf32:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
bytes = detail::utf32_to_utf16(data_);
#else
bytes = data_;
@ -984,19 +984,19 @@ namespace nana
switch(encoding)
{
case unicode::utf8:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
return detail::utf16_to_utf8(std::string(reinterpret_cast<const char*>(data_.c_str()), data_.size() * sizeof(wchar_t)));
#else
return detail::utf32_to_utf8(std::string(reinterpret_cast<const char*>(data_.c_str()), data_.size() * sizeof(wchar_t)));
#endif
case unicode::utf16:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
return std::string(reinterpret_cast<const char*>(data_.c_str()), data_.size() * sizeof(wchar_t));
#else
return detail::utf32_to_utf16(std::string(reinterpret_cast<const char*>(data_.c_str()), data_.size() * sizeof(wchar_t)));
#endif
case unicode::utf32:
#if defined(NANA_MINGW)
#if defined(NANA_WINDOWS)
return detail::utf16_to_utf32(std::string(reinterpret_cast<const char*>(data_.c_str()), data_.size() * sizeof(wchar_t)));
#else
return std::string(reinterpret_cast<const char*>(data_.c_str()), data_.size() * sizeof(wchar_t));

View File

@ -44,7 +44,7 @@ namespace detail
bool conf::open(const char* file)
{
ifs_.open(file);
return static_cast<bool>(ifs_ != 0);
return static_cast<bool>(ifs_);
}
std::string conf::value(const char* key)

View File

@ -0,0 +1,444 @@
/*
* A FileSystem Utility Implementation
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/filesystem/filesystem.cpp
* @description:
* provide some interface for file managment
*/
#include <nana/filesystem/filesystem.hpp>
#include <vector>
#if defined(NANA_WINDOWS)
#include <windows.h>
#if defined(NANA_MINGW)
#ifndef _WIN32_IE
#define _WIN32_IE 0x0500
#endif
#endif
#include <shlobj.h>
#include <nana/datetime.hpp>
#elif defined(NANA_LINUX)
#include <nana/charset.hpp>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <cstdio>
#include <cstring>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#endif
namespace nana {
namespace experimental
{
namespace filesystem
{
//Because of No wide character version of POSIX
#if defined(NANA_LINUX)
typedef std::string string_t;
const char* splstr = "/\\";
#else
typedef nana::string string_t;
const nana::char_t* splstr = STR("/\\");
#endif
//class path
path::path() {}
path::path(const nana::string& text)
#if defined(NANA_WINDOWS)
: text_(text)
{
#else
:text_(nana::charset(text))
{
#endif
auto pos = text_.find_last_of(splstr);
for (; (pos != string_t::npos) && (pos + 1 == text_.size()); pos = text_.find_last_of(splstr))
text_.erase(pos);
}
bool path::empty() const
{
#if defined(NANA_WINDOWS)
return (::GetFileAttributes(text_.c_str()) == INVALID_FILE_ATTRIBUTES);
#elif defined(NANA_LINUX)
struct stat sta;
return (::stat(text_.c_str(), &sta) == -1);
#endif
}
path path::root() const
{
#if defined(NANA_WINDOWS)
return path(filesystem::root(text_));
#elif defined(NANA_LINUX)
return path(filesystem::root(nana::charset(text_)));
#endif
}
file_type path::what() const
{
#if defined(NANA_WINDOWS)
unsigned long attr = ::GetFileAttributes(text_.c_str());
if (INVALID_FILE_ATTRIBUTES == attr)
return file_type::not_found; //??
if (FILE_ATTRIBUTE_DIRECTORY & attr)
return file_type::directory;
return file_type::regular;
#elif defined(NANA_LINUX)
struct stat sta;
if (-1 == ::stat(text_.c_str(), &sta))
return file_type::not_found; //??
if ((S_IFDIR & sta.st_mode) == S_IFDIR)
return file_type::directory;
if ((S_IFREG & sta.st_mode) == S_IFREG)
return file_type::regular;
return file_type::none;
#endif
}
nana::string path::filename() const
{
string_t::size_type pos = text_.find_last_of(splstr);
#if defined(NANA_WINDOWS)
return text_.substr(pos + 1);
#else
return nana::charset(text_.substr(pos + 1));
#endif
}
//end class path
namespace detail
{
//rm_dir_recursive
//@brief: remove a directory, if it is not empty, recursively remove it's subfiles and sub directories
bool rm_dir_recursive(nana::string&& dir)
{
std::vector<directory_iterator::value_type> files;
nana::string path = dir;
path += '\\';
std::copy(directory_iterator(dir), directory_iterator(), std::back_inserter(files));
for (auto & f : files)
{
if (f.attr.directory)
rm_dir_recursive(path + f.path().filename());
else
rmfile((path + f.path().filename()).c_str());
}
return rmdir(dir.c_str(), true);
}
bool mkdir_helper(const nana::string& dir, bool & if_exist)
{
#if defined(NANA_WINDOWS)
if (::CreateDirectory(dir.c_str(), 0))
{
if_exist = false;
return true;
}
if_exist = (::GetLastError() == ERROR_ALREADY_EXISTS);
#elif defined(NANA_LINUX)
if (0 == ::mkdir(static_cast<std::string>(nana::charset(dir)).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
{
if_exist = false;
return true;
}
if_exist = (errno == EEXIST);
#endif
return false;
}
#if defined(NANA_WINDOWS)
void filetime_to_c_tm(FILETIME& ft, struct tm& t)
{
FILETIME local_file_time;
if (::FileTimeToLocalFileTime(&ft, &local_file_time))
{
SYSTEMTIME st;
::FileTimeToSystemTime(&local_file_time, &st);
t.tm_year = st.wYear - 1900;
t.tm_mon = st.wMonth - 1;
t.tm_mday = st.wDay;
t.tm_wday = st.wDayOfWeek - 1;
t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay);
t.tm_hour = st.wHour;
t.tm_min = st.wMinute;
t.tm_sec = st.wSecond;
}
}
#endif
}//end namespace detail
bool file_attrib(const nana::string& file, attribute& attr)
{
#if defined(NANA_WINDOWS)
WIN32_FILE_ATTRIBUTE_DATA fad;
if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &fad))
{
LARGE_INTEGER li;
li.u.LowPart = fad.nFileSizeLow;
li.u.HighPart = fad.nFileSizeHigh;
attr.size = li.QuadPart;
attr.directory = (0 != (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
detail::filetime_to_c_tm(fad.ftLastWriteTime, attr.modified);
return true;
}
#elif defined(NANA_LINUX)
struct stat fst;
if (0 == ::stat(static_cast<std::string>(nana::charset(file)).c_str(), &fst))
{
attr.bytes = fst.st_size;
attr.is_directory = (0 != (040000 & fst.st_mode));
attr.modified = *(::localtime(&fst.st_ctime));
return true;
}
#endif
return false;
}
uintmax_t file_size(const nana::string& file)
{
#if defined(NANA_WINDOWS)
//Some compilation environment may fail to link to GetFileSizeEx
typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER);
GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast<GetFileSizeEx_fptr_t>(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx"));
if (get_file_size_ex)
{
HANDLE handle = ::CreateFile(file.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (INVALID_HANDLE_VALUE != handle)
{
LARGE_INTEGER li;
if (!get_file_size_ex(handle, &li))
li.QuadPart = 0;
::CloseHandle(handle);
return li.QuadPart;
}
}
return 0;
#elif defined(NANA_LINUX)
FILE * stream = ::fopen(static_cast<std::string>(nana::charset(file)).c_str(), "rb");
long long size = 0;
if (stream)
{
fseeko64(stream, 0, SEEK_END);
size = ftello64(stream);
fclose(stream);
}
return size;
#endif
}
bool modified_file_time(const nana::string& file, struct tm& t)
{
#if defined(NANA_WINDOWS)
WIN32_FILE_ATTRIBUTE_DATA attr;
if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &attr))
{
FILETIME local_file_time;
if (::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time))
{
SYSTEMTIME st;
::FileTimeToSystemTime(&local_file_time, &st);
t.tm_year = st.wYear - 1900;
t.tm_mon = st.wMonth - 1;
t.tm_mday = st.wDay;
t.tm_wday = st.wDayOfWeek - 1;
t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay);
t.tm_hour = st.wHour;
t.tm_min = st.wMinute;
t.tm_sec = st.wSecond;
return true;
}
}
#elif defined(NANA_LINUX)
struct stat attr;
if (0 == ::stat(static_cast<std::string>(nana::charset(file)).c_str(), &attr))
{
t = *(::localtime(&attr.st_ctime));
return true;
}
#endif
return false;
}
bool create_directory(const nana::string& path, bool & if_exist)
{
if_exist = false;
if (path.size() == 0) return false;
nana::string root;
#if defined(NANA_WINDOWS)
if (path.size() > 3 && path[1] == STR(':'))
root = path.substr(0, 3);
#elif defined(NANA_LINUX)
if (path[0] == STR('/'))
root = '/';
#endif
bool mkstat = false;
std::size_t beg = root.size();
while (true)
{
beg = path.find_first_not_of(STR("/\\"), beg);
if (beg == path.npos)
break;
std::size_t pos = path.find_first_of(STR("/\\"), beg + 1);
if (pos != path.npos)
{
root += path.substr(beg, pos - beg);
mkstat = detail::mkdir_helper(root, if_exist);
if (mkstat == false && if_exist == false)
return false;
#if defined(NANA_WINDOWS)
root += STR('\\');
#elif defined(NANA_LINUX)
root += STR('/');
#endif
}
else
{
if (beg + 1 < path.size())
{
root += path.substr(beg);
mkstat = detail::mkdir_helper(root, if_exist);
}
break;
}
beg = pos + 1;
}
return mkstat;
}
bool rmfile(const nana::char_t* file)
{
#if defined(NANA_WINDOWS)
bool ret = false;
if (file)
{
ret = (::DeleteFile(file) == TRUE);
if (!ret)
ret = (ERROR_FILE_NOT_FOUND == ::GetLastError());
}
return ret;
#elif defined(NANA_LINUX)
if (std::remove(static_cast<std::string>(nana::charset(file)).c_str()))
return (errno == ENOENT);
return true;
#endif
}
bool rmdir(const nana::char_t* dir, bool fails_if_not_empty)
{
bool ret = false;
if (dir)
{
#if defined(NANA_WINDOWS)
ret = (::RemoveDirectory(dir) == TRUE);
if (!fails_if_not_empty && (::GetLastError() == ERROR_DIR_NOT_EMPTY))
ret = detail::rm_dir_recursive(dir);
#elif defined(NANA_LINUX)
std::string mbstr = nana::charset(dir);
if (::rmdir(mbstr.c_str()))
{
if (!fails_if_not_empty && (errno == EEXIST || errno == ENOTEMPTY))
ret = detail::rm_dir_recursive(dir);
}
else
ret = true;
#endif
}
return ret;
}
nana::string root(const nana::string& path)
{
std::size_t index = path.size();
if (index)
{
const nana::char_t * str = path.c_str();
for (--index; index > 0; --index)
{
nana::char_t c = str[index];
if (c != '\\' && c != '/')
break;
}
for (--index; index > 0; --index)
{
nana::char_t c = str[index];
if (c == '\\' || c == '/')
break;
}
}
return index ? path.substr(0, index + 1) : nana::string();
}
nana::string path_user()
{
#if defined(NANA_WINDOWS)
nana::char_t path[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, path)))
return path;
#elif defined(NANA_LINUX)
const char * s = ::getenv("HOME");
if (s)
return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8);
#endif
return nana::string();
}
path current_path()
{
#if defined(NANA_WINDOWS)
nana::char_t buf[MAX_PATH];
DWORD len = ::GetCurrentDirectory(MAX_PATH, buf);
if (len)
{
if (len > MAX_PATH)
{
nana::char_t * p = new nana::char_t[len + 1];
::GetCurrentDirectory(len + 1, p);
nana::string s = p;
delete[] p;
return s;
}
return buf;
}
#elif defined(NANA_LINUX)
const char * s = ::getenv("PWD");
if (s)
return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8);
#endif
return nana::string();
}
}//end namespace filesystem
} //end namespace experimental
}//end namespace nana

View File

@ -7,7 +7,7 @@ namespace nana
{
//class caret_descriptor
caret_descriptor::caret_descriptor(core_window_t* wd, unsigned width, unsigned height)
:wd_(wd), size_(width, height), visible_(false), real_visible_state_(false), out_of_range_(false)
:wd_(wd), size_(width, height), visible_state_(visible_state::invisible), out_of_range_(false)
{}
caret_descriptor::~caret_descriptor()
@ -22,8 +22,9 @@ namespace nana
if(active)
{
native_interface::caret_create(wd_->root, size_);
real_visible_state_ = false;
visible_ = false;
//real_visible_state_ = false;
//visible_ = false;
visible_state_ = visible_state::invisible;
this->position(point_.x, point_.y);
}
else
@ -76,19 +77,36 @@ namespace nana
return point_;
}
void caret_descriptor::visible(bool isshow)
void caret_descriptor::visible(bool is_show)
{
if(visible_ != isshow)
/*
if(visible_ != isshow) //deprecated
{
visible_ = isshow;
if(visible_ == false || false == out_of_range_)
_m_visible(isshow);
}
*/
auto pre_displayed = (visible_state::displayed == visible_state_);
if (is_show)
{
visible_state_ = visible_state::visible;
if (wd_->displayed() && (! out_of_range_))
visible_state_ = visible_state::displayed;
}
else
visible_state_ = visible_state::invisible;
if (pre_displayed != (visible_state::displayed == visible_state_))
native_interface::caret_visible(wd_->root, !pre_displayed);
}
bool caret_descriptor::visible() const
{
return visible_;
//return visible_; //deprecated
return (visible_state::invisible != visible_state_);
}
nana::size caret_descriptor::size() const
@ -101,17 +119,21 @@ namespace nana
size_ = s;
update();
if(visible_) this->visible(true);
//if(visible_) this->visible(true); //deprecated
if (visible_state::invisible != visible_state_)
visible(true);
}
/*
void caret_descriptor::_m_visible(bool isshow)
{
if(real_visible_state_ != isshow)
if(real_visible_state_ != isshow) //deprecated
{
real_visible_state_ = isshow;
native_interface::caret_visible(wd_->root, isshow);
native_interface::caret_visible(wd_->root, isshow && wd_->displayed());
}
}
*/
void caret_descriptor::update()
{
@ -138,8 +160,10 @@ namespace nana
{
out_of_range_ = true;
if(visible_)
_m_visible(false);
//if(visible_)
// _m_visible(false); //deprecated
if (visible_state::invisible != visible_state_)
visible(false);
}
}
else
@ -164,19 +188,27 @@ namespace nana
if(out_of_range_)
{
if(paint_size_ == size)
_m_visible(true);
//if(paint_size_ == size) //deprecated
// _m_visible(true);
if (paint_size_ == size)
visible(true);
out_of_range_ = false;
}
if(paint_size_ != size)
{
bool vs = (visible_state::invisible != visible_state_);
native_interface::caret_destroy(wd_->root);
native_interface::caret_create(wd_->root, size);
real_visible_state_ = false;
if(visible_)
_m_visible(true);
//real_visible_state_ = false; //deprecated
//if(visible_)
// _m_visible(true);
visible_state_ = visible_state::invisible;
if (vs)
visible(true);
paint_size_ = size;
}
@ -281,6 +313,11 @@ namespace nana
return true;
}
bool basic_window::displayed() const
{
return (visible && visible_parents());
}
bool basic_window::belong_to_lazy() const
{
for (auto wd = this; wd; wd = wd->parent)
@ -291,6 +328,26 @@ namespace nana
return false;
}
const basic_window* get_child_caret(const basic_window* wd, bool this_is_a_child)
{
if (this_is_a_child && wd->together.caret)
return wd;
for (auto child : wd->children)
{
auto caret_wd = get_child_caret(child, true);
if (caret_wd)
return caret_wd;
}
return nullptr;
}
const basic_window * basic_window::child_caret() const
{
return get_child_caret(this, false);
}
bool basic_window::is_draw_through() const
{
if (::nana::category::flags::root == this->other.category)

View File

@ -93,6 +93,18 @@ namespace nana
arg.window_handle = reinterpret_cast<window>(wd);
if (emit(event_code::expose, wd, arg, false, get_thread_context()))
{
const core_window_t * caret_wd = (wd->together.caret ? wd : wd->child_caret());
if (caret_wd)
{
if (exposed)
{
if (wd->root_widget->other.attribute.root->focus == caret_wd)
caret_wd->together.caret->visible(true);
}
else
caret_wd->together.caret->visible(false);
}
if (!exposed)
{
if (category::flags::root != wd->other.category)
@ -118,7 +130,7 @@ namespace nana
arg.x = x;
arg.y = y;
if (emit(event_code::move, wd, arg, false, get_thread_context()))
wd_manager.update(wd, true, true);
wd_manager.update(wd, false, true);
}
}

View File

@ -34,99 +34,99 @@ namespace nana
void drawer_trigger::resizing(graph_reference, const arg_resizing&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::resizing));
}
void drawer_trigger::resized(graph_reference graph, const arg_resized&)
{
overrided_ = true;
overrided_ |= (1 << static_cast<int>(event_code::resized));
this->refresh(graph);
detail::bedrock::instance().thread_context_lazy_refresh();
}
void drawer_trigger::move(graph_reference, const arg_move&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::move));
}
void drawer_trigger::click(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::click));
}
void drawer_trigger::dbl_click(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::dbl_click));
}
void drawer_trigger::mouse_enter(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_enter));
}
void drawer_trigger::mouse_move(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_move));
}
void drawer_trigger::mouse_leave(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_leave));
}
void drawer_trigger::mouse_down(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_down));
}
void drawer_trigger::mouse_up(graph_reference, const arg_mouse&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_up));
}
void drawer_trigger::mouse_wheel(graph_reference, const arg_wheel&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_wheel));
}
void drawer_trigger::mouse_dropfiles(graph_reference, const arg_dropfiles&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_drop));
}
void drawer_trigger::focus(graph_reference, const arg_focus&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::focus));
}
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::key_press));
}
void drawer_trigger::key_char(graph_reference, const arg_keyboard&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::key_char));
}
void drawer_trigger::key_release(graph_reference, const arg_keyboard&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::key_release));
}
void drawer_trigger::shortkey(graph_reference, const arg_keyboard&)
{
overrided_ = false;
overrided_ &= ~(1 << static_cast<int>(event_code::shortkey));
}
void drawer_trigger::_m_reset_overrided()
{
overrided_ = true;
overrided_ = 0xFFFFFFFF;
}
bool drawer_trigger::_m_overrided() const
bool drawer_trigger::_m_overrided(event_code evt_code) const
{
return overrided_;
return 0 != (overrided_ & (1 << static_cast<int>(evt_code)));
}
//end class drawer_trigger
@ -240,12 +240,12 @@ namespace nana
_m_emit(event_code::shortkey, arg, &drawer_trigger::shortkey);
}
void drawer::map(window wd, bool forced) //Copy the root buffer to screen
void drawer::map(window wd, bool forced, const rectangle* update_area) //Copy the root buffer to screen
{
if(wd)
{
bedrock_type::core_window_t* iwd = reinterpret_cast<bedrock_type::core_window_t*>(wd);
bedrock_type::core_window_t * caret_wd = iwd->root_widget->other.attribute.root->focus;
auto iwd = reinterpret_cast<bedrock_type::core_window_t*>(wd);
auto caret_wd = iwd->root_widget->other.attribute.root->focus;
bool owns_caret = (caret_wd && (caret_wd->together.caret) && (caret_wd->together.caret->visible()));
@ -262,12 +262,7 @@ namespace nana
#endif
}
if (false == edge_nimbus_renderer_t::instance().render(iwd, forced))
{
nana::rectangle vr;
if(bedrock_type::window_manager_t::wndlayout_type::read_visual_rectangle(iwd, vr))
iwd->root_graph->paste(iwd->root, vr, vr.x, vr.y);
}
edge_nimbus_renderer_t::instance().render(iwd, forced, update_area);
if(owns_caret)
{
@ -302,9 +297,10 @@ namespace nana
void drawer::attached(widget& wd, drawer_trigger& realizer)
{
for (auto i = std::begin(mth_state_), end = std::end(mth_state_); i != end; ++i)
*i = method_state::unknown;
*i = method_state::pending;
realizer_ = &realizer;
realizer._m_reset_overrided();
realizer.attached(wd, graphics);
}

View File

@ -152,7 +152,7 @@ namespace detail
delete impl_;
}
void bedrock::map_thread_root_buffer(core_window_t*, bool forced)
void bedrock::map_thread_root_buffer(core_window_t*, bool forced, const rectangle*)
{
//GUI in X11 is thread-independent, so no implementation.
}
@ -921,11 +921,10 @@ namespace detail
if(msgwnd->visible && (msgwnd->root_graph->empty() == false))
{
nana::detail::platform_scope_guard psg;
nana::detail::drawable_impl_type* drawer_impl = msgwnd->root_graph->handle();
::XCopyArea(display, drawer_impl->pixmap, reinterpret_cast<Window>(native_window), drawer_impl->context,
xevent.xexpose.x, xevent.xexpose.y,
xevent.xexpose.width, xevent.xexpose.height,
xevent.xexpose.x, xevent.xexpose.y);
//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);
if (!update_area.empty())
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area);
}
break;
case KeyPress:
@ -1011,13 +1010,11 @@ namespace detail
{
arg_keyboard argkey;
brock.get_key_state(argkey);
auto tstop_wd = brock.wd_manager.tabstop(msgwnd, argkey.shift);
auto tstop_wd = brock.wd_manager.tabstop(msgwnd, !argkey.shift);
if (tstop_wd)
{
brock.wd_manager.set_focus(tstop_wd, false);
brock.wd_manager.do_lazy_refresh(msgwnd, false);
brock.wd_manager.do_lazy_refresh(tstop_wd, true);
root_runtime->condition.tabstop_focus_changed = true;
}
}
else if(keyboard::alt == keychar)
@ -1066,6 +1063,7 @@ namespace detail
break;
}
case XLookupChars:
if (msgwnd->flags.enabled)
{
const ::nana::char_t* charbuf;
#if defined(NANA_UNICODE)
@ -1082,6 +1080,10 @@ namespace detail
arg.ignore = false;
arg.key = charbuf[i];
// When tab is pressed, only tab-eating mode is allowed
if ((keyboard::tab == arg.key) && !(msgwnd->flags.tab & tab_type::eating))
continue;
if(context.is_alt_pressed)
{
arg.ctrl = arg.shift = false;
@ -1130,7 +1132,9 @@ namespace detail
brock.get_key_state(arg);
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
}
brock.delay_restore(2); //Restores while key release
if (context.platform.keychar < keyboard::os_arrow_left || keyboard::os_arrow_down < wParam)
brock.delay_restore(2); //Restores while key release
}
else
{

View File

@ -328,9 +328,14 @@ namespace detail
return bedrock_object;
}
void bedrock::map_thread_root_buffer(core_window_t* wd, bool forced)
void bedrock::map_thread_root_buffer(core_window_t* wd, bool forced, const rectangle* update_area)
{
::PostMessage(reinterpret_cast<HWND>(wd->root), nana::detail::messages::map_thread_root_buffer, reinterpret_cast<WPARAM>(wd), static_cast<LPARAM>(forced ? TRUE : FALSE));
auto stru = reinterpret_cast<detail::messages::map_thread*>(::HeapAlloc(::GetProcessHeap(), 0, sizeof(detail::messages::map_thread)));
if (stru)
{
if (FALSE == ::PostMessage(reinterpret_cast<HWND>(wd->root), nana::detail::messages::map_thread_root_buffer, reinterpret_cast<WPARAM>(wd), reinterpret_cast<LPARAM>(stru)))
::HeapFree(::GetProcessHeap(), 0, stru);
}
}
void interior_helper_for_menu(MSG& msg, native_window_type menu_window)
@ -348,7 +353,7 @@ namespace detail
void bedrock::pump_event(window modal_window, bool is_modal)
{
const unsigned tid = ::GetCurrentThreadId();
thread_context * context = this->open_thread_context(tid);
auto context = this->open_thread_context(tid);
if(0 == context->window_count)
{
//test if there is not a window
@ -581,8 +586,12 @@ namespace detail
}
return true;
case nana::detail::messages::map_thread_root_buffer:
bedrock.wd_manager.map(reinterpret_cast<bedrock::core_window_t*>(wParam), (TRUE == lParam));
::UpdateWindow(wd);
{
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));
::UpdateWindow(wd);
::HeapFree(::GetProcessHeap(), 0, stru);
}
return true;
case nana::detail::messages::remote_thread_move_window:
{
@ -1282,13 +1291,11 @@ namespace detail
::PAINTSTRUCT ps;
::HDC dc = ::BeginPaint(root_window, &ps);
if((ps.rcPaint.left != ps.rcPaint.right) && (ps.rcPaint.bottom != ps.rcPaint.top))
{
::BitBlt(dc,
ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
reinterpret_cast<HDC>(msgwnd->root_graph->handle()->context),
ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
}
//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);
if (!update_area.empty())
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area);
::EndPaint(root_window, &ps);
}
break;
@ -1372,7 +1379,7 @@ namespace detail
if(msgwnd)
{
if((wParam == 9) && (false == (msgwnd->flags.tab & tab_type::eating))) //Tab
if((wParam == 9) && (!msgwnd->visible || (false == (msgwnd->flags.tab & tab_type::eating)))) //Tab
{
bool is_forward = (::GetKeyState(VK_SHIFT) >= 0);
@ -1382,7 +1389,6 @@ namespace detail
brock.wd_manager.set_focus(tstop_wd, false);
brock.wd_manager.do_lazy_refresh(msgwnd, false);
brock.wd_manager.do_lazy_refresh(tstop_wd, true);
root_runtime->condition.tabstop_focus_changed = true;
}
}
else
@ -1411,9 +1417,10 @@ namespace detail
break;
case WM_CHAR:
msgwnd = brock.focus();
if(false == root_runtime->condition.tabstop_focus_changed)
if (msgwnd && msgwnd->flags.enabled)
{
if(msgwnd && msgwnd->flags.enabled)
// When tab is pressed, only tab-eating mode is allowed
if ((9 != wParam) || (msgwnd->flags.tab & tab_type::eating))
{
arg_keyboard arg;
arg.evt_code = event_code::key_char;
@ -1429,8 +1436,6 @@ namespace detail
brock.wd_manager.do_lazy_refresh(msgwnd, false);
}
}
else
root_runtime->condition.tabstop_focus_changed = false;
return 0;
case WM_KEYUP:
if(wParam != 18) //MUST NOT BE AN ALT
@ -1450,7 +1455,10 @@ namespace detail
else
brock.set_keyboard_shortkey(false);
brock.delay_restore(2); //Restores while key release
//Do delay restore if key is not arrow_left/right/up/down, otherwise
//A menubar will be restored if the item is empty(not have a menu item)
if (wParam < 37 || 40 < wParam)
brock.delay_restore(2); //Restores while key release
break;
case WM_CLOSE:
{

View File

@ -24,7 +24,7 @@ namespace nana
//class window_layout
void window_layout::paint(core_window_t* wd, bool is_redraw, bool is_child_refreshed)
{
if (wd->flags.refreshing)
if (wd->flags.refreshing || wd->drawer.graphics.empty())
return;
if (nullptr == wd->effect.bground)
@ -61,7 +61,6 @@ namespace nana
if (wd->parent)
{
std::vector<wd_rectangle> blocks;
blocks.reserve(10);
if (read_overlaps(wd, vr, blocks))
{
nana::point p_src;
@ -101,7 +100,7 @@ namespace nana
// The result is a rectangle that is a visible area for its ancesters.
bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual)
{
if (false == wd->visible) return false;
if (! wd->displayed()) return false;
visual = rectangle{ wd->pos_root, wd->dimension };
@ -356,7 +355,7 @@ namespace nana
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
for (auto wd : data_sect.effects_bground_windows)
{
if (wd == sigwd || !wd->visible || !wd->visible_parents() ||
if (wd == sigwd || !wd->displayed() ||
(false == overlap(nana::rectangle{ wd->pos_root, wd->dimension }, r_of_sigwd)))
continue;

View File

@ -357,21 +357,26 @@ namespace detail
//@brief: Delete the window handle
void window_manager::destroy(core_window_t* wd)
{
core_window_t* parent = nullptr;
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (impl_->wd_register.available(wd) == false) return;
rectangle update_area(wd->pos_owner, wd->dimension);
auto parent = wd->parent;
if (parent)
utl::erase(parent->children, wd);
_m_destroy(wd);
while (parent && (parent->other.category == ::nana::category::flags::lite_widget))
{
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (impl_->wd_register.available(wd) == false) return;
if (wd->parent)
{
parent = wd->parent;
utl::erase(wd->parent->children, wd);
}
_m_destroy(wd);
update_area.x += parent->pos_owner.x;
update_area.y += parent->pos_owner.y;
parent = parent->parent;
}
update(parent, false, false);
update(parent, false, false, &update_area);
}
//destroy_handle
@ -408,35 +413,34 @@ namespace detail
{
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (impl_->wd_register.available(wd))
if (!impl_->wd_register.available(wd))
return false;
if(visible != wd->visible)
{
if(visible != wd->visible)
native_window_type nv = nullptr;
switch(wd->other.category)
{
native_window_type nv = nullptr;
switch(wd->other.category)
{
case category::root_tag::value:
nv = wd->root; break;
case category::frame_tag::value:
nv = wd->other.attribute.frame->container; break;
default: //category::widget_tag, category::lite_widget_tag
break;
}
if(visible && wd->effect.bground)
wndlayout_type::make_bground(wd);
//Don't set the visible attr of a window if it is a root.
//The visible attr of a root will be set in the expose event.
if(category::root_tag::value != wd->other.category)
bedrock::instance().event_expose(wd, visible);
if(nv)
native_interface::show_window(nv, visible, wd->flags.take_active);
case category::root_tag::value:
nv = wd->root; break;
case category::frame_tag::value:
nv = wd->other.attribute.frame->container; break;
default: //category::widget_tag, category::lite_widget_tag
break;
}
return true;
if(visible && wd->effect.bground)
window_layer::make_bground(wd);
//Don't set the visible attr of a window if it is a root.
//The visible attr of a root will be set in the expose event.
if(category::flags::root != wd->other.category)
bedrock::instance().event_expose(wd, visible);
if(nv)
native_interface::show_window(nv, visible, wd->flags.take_active);
}
return false;
return true;
}
window_manager::core_window_t* window_manager::find_window(native_window_type root, int x, int y)
@ -474,9 +478,6 @@ namespace detail
wd->pos_owner.y = y;
_m_move_core(wd, delta);
if(wd->together.caret && wd->together.caret->visible())
wd->together.caret->update();
auto &brock = bedrock::instance();
arg_move arg;
arg.window_handle = reinterpret_cast<window>(wd);
@ -503,7 +504,7 @@ namespace detail
auto & brock = bedrock::instance();
bool moved = false;
const bool size_changed = (r.width != wd->dimension.width || r.height != wd->dimension.height);
if(wd->other.category != category::root_tag::value)
if(category::flags::root != wd->other.category)
{
//Move child widgets
if(r.x != wd->pos_owner.x || r.y != wd->pos_owner.y)
@ -514,9 +515,6 @@ namespace detail
_m_move_core(wd, delta);
moved = true;
if(wd->together.caret && wd->together.caret->visible())
wd->together.caret->update();
arg_move arg;
arg.window_handle = reinterpret_cast<window>(wd);
arg.x = r.x;
@ -625,7 +623,7 @@ namespace detail
if(wd->effect.bground && wd->parent)
{
wd->other.glass_buffer.make(sz);
wndlayout_type::make_bground(wd);
window_layer::make_bground(wd);
}
}
}
@ -657,7 +655,7 @@ namespace detail
}
//Copy the root buffer that wnd specified into DeviceContext
void window_manager::map(core_window_t* wd, bool forced)
void window_manager::map(core_window_t* wd, bool forced, const rectangle* update_area)
{
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
@ -665,12 +663,12 @@ namespace detail
{
//Copy the root buffer that wd specified into DeviceContext
#if defined(NANA_LINUX)
wd->drawer.map(reinterpret_cast<window>(wd), forced);
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area);
#elif defined(NANA_WINDOWS)
if(nana::system::this_thread_id() == wd->thread_id)
wd->drawer.map(reinterpret_cast<window>(wd), forced);
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area);
else
bedrock::instance().map_thread_root_buffer(wd, forced);
bedrock::instance().map_thread_root_buffer(wd, forced, update_area);
#endif
}
}
@ -679,25 +677,25 @@ namespace detail
//@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
// 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)
bool window_manager::update(core_window_t* wd, bool redraw, bool forced, const rectangle* update_area)
{
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (impl_->wd_register.available(wd) == false) return false;
if (wd->visible && wd->visible_parents())
if (wd->displayed())
{
if(forced || (false == wd->belong_to_lazy()))
{
if (!wd->flags.refreshing)
{
wndlayout_type::paint(wd, redraw, false);
this->map(wd, forced);
window_layer::paint(wd, redraw, false);
this->map(wd, forced, update_area);
return true;
}
}
else if(redraw)
wndlayout_type::paint(wd, true, false);
else if (redraw)
window_layer::paint(wd, true, false);
if (wd->other.upd_state == core_window_t::update_state::lazy)
wd->other.upd_state = core_window_t::update_state::refresh;
@ -711,8 +709,8 @@ namespace detail
std::lock_guard<decltype(mutex_)> lock(mutex_);
//It's not worthy to redraw if visible is false
if (impl_->wd_register.available(wd) && wd->visible && wd->visible_parents())
wndlayout_type::paint(wd, true, true);
if (impl_->wd_register.available(wd) && wd->displayed())
window_layer::paint(wd, true, true);
}
//do_lazy_refresh
@ -733,18 +731,19 @@ namespace detail
{
if ((wd->other.upd_state == core_window_t::update_state::refresh) || force_copy_to_screen)
{
wndlayout_type::paint(wd, false, false);
window_layer::paint(wd, false, false);
this->map(wd, force_copy_to_screen);
}
else if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
{
//Update the nimbus effect
using nimbus_renderer = detail::edge_nimbus_renderer<core_window_t>;
nimbus_renderer::instance().render(wd, force_copy_to_screen);
//using nimbus_renderer = detail::edge_nimbus_renderer<core_window_t>; //deprecated
//nimbus_renderer::instance().render(wd, true);
this->map(wd, true);
}
}
else
wndlayout_type::paint(wd, true, false); //only refreshing if it has an invisible parent
window_layer::paint(wd, true, false); //only refreshing if it has an invisible parent
}
wd->other.upd_state = core_window_t::update_state::none;
return true;
@ -764,7 +763,7 @@ namespace detail
result.make(wd->drawer.graphics.size());
result.bitblt(0, 0, wd->drawer.graphics);
wndlayout_type::paste_children_to_graphics(wd, result);
window_layer::paste_children_to_graphics(wd, result);
return true;
}
@ -773,7 +772,7 @@ namespace detail
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
return (impl_->wd_register.available(wd) ?
wndlayout_type::read_visual_rectangle(wd, r) :
window_layer::read_visual_rectangle(wd, r) :
false);
}
@ -1002,6 +1001,39 @@ namespace detail
}
}
// 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)
{
auto & tabs = wd->root_widget->other.attribute.root->tabstop;
if (forward)
{
if (detail::tab_type::none == wd->flags.tab)
return (tabs.front());
else if (detail::tab_type::tabstop & wd->flags.tab)
{
auto end = tabs.cend();
auto i = std::find(tabs.cbegin(), end, wd);
if (i != end)
{
++i;
window_manager::core_window_t* ts = (i != end ? (*i) : tabs.front());
return (ts != wd ? ts : 0);
}
else
return tabs.front();
}
}
else if (tabs.size() > 1) //at least 2 elments in tabs are required when moving backward.
{
auto i = std::find(tabs.cbegin(), tabs.cend(), wd);
if (i != tabs.cend())
return (tabs.cbegin() == i ? tabs.back() : *(i - 1));
}
return nullptr;
}
auto window_manager::tabstop(core_window_t* wd, bool forward) const -> core_window_t*
{
//Thread-Safe Required!
@ -1013,21 +1045,30 @@ namespace detail
if (tabs.empty())
return nullptr;
if ((detail::tab_type::none == wd->flags.tab) || !(detail::tab_type::tabstop & wd->flags.tab))
return (forward ? tabs.front() : tabs.back());
auto i = std::find(tabs.cbegin(), tabs.cend(), wd);
if (tabs.cend() == i)
return (forward ? tabs.front() : tabs.back());
if (forward)
bool precondition = false;
for (auto & tab_wd : tabs)
{
++i;
core_window_t* ts = (i != tabs.cend() ? (*i) : tabs.front());
return (ts != wd ? ts : nullptr);
if (tab_wd->displayed())
{
precondition = true;
break;
}
}
return (tabs.cbegin() == i ? tabs.back() : *(i - 1));
if (precondition)
{
auto new_stop = get_tabstop(wd, forward);
while (new_stop && (wd != new_stop))
{
if (new_stop->flags.enabled && new_stop->displayed())
return new_stop;
new_stop = get_tabstop(new_stop, forward);
}
}
return nullptr;
}
void window_manager::remove_trash_handle(unsigned tid)
@ -1040,7 +1081,7 @@ namespace detail
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
if (impl_->wd_register.available(wd))
return wndlayout_type::enable_effects_bground(wd, enabled);
return window_layer::enable_effects_bground(wd, enabled);
return false;
}
@ -1224,18 +1265,9 @@ namespace detail
if (!established)
{
if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
{
auto & cont = root_attr->effects_edge_nimbus;
for (auto i = cont.begin(); i != cont.end(); ++i)
{
if (i->window == wd)
{
cont.erase(i);
break;
}
}
}
//remove the window from edge nimbus effect when it is destroying
using edge_nimbus = detail::edge_nimbus_renderer<core_window_t>;
edge_nimbus::instance().erase(wd);
}
else if (pa_root_attr != root_attr)
{
@ -1347,7 +1379,7 @@ namespace detail
_m_disengage(wd, nullptr);
wndlayout_type::enable_effects_bground(wd, false);
window_layer::enable_effects_bground(wd, false);
wd->drawer.detached();
wd->widget_notifier->destroy();
@ -1371,7 +1403,12 @@ namespace detail
if(wd->other.category != category::root_tag::value) //A root widget always starts at (0, 0) and its childs are not to be changed
{
wd->pos_root += delta;
if(wd->other.category == category::frame_tag::value)
if (category::flags::frame != wd->other.category)
{
if (wd->together.caret && wd->together.caret->visible())
wd->together.caret->update();
}
else
native_interface::move_window(wd->other.attribute.frame->container, wd->pos_root.x, wd->pos_root.y);
for (auto child : wd->children)

View File

@ -722,7 +722,7 @@ namespace API
if(restrict::window_manager.available(iwd) && (iwd->flags.enabled != enabled))
{
iwd->flags.enabled = enabled;
restrict::window_manager.update(iwd, true, false);
restrict::window_manager.update(iwd, true, true);
if(category::flags::root == iwd->other.category)
restrict::interface_type::enable_window(iwd->root, enabled);
}

View File

@ -151,7 +151,7 @@ namespace nana{ namespace drawerbase
void trigger::key_char(graph_reference, const arg_keyboard& arg)
{
if(arg.key == static_cast<char_t>(keyboard::enter))
if (static_cast<char_t>(keyboard::enter) == arg.key || static_cast<char_t>(keyboard::space) == arg.key)
emit_click();
}

View File

@ -18,6 +18,8 @@
#include <nana/gui/widgets/skeletons/text_editor.hpp>
#include <nana/gui/widgets/skeletons/textbase_export_interface.hpp>
#include <iterator>
namespace nana
{
arg_combox::arg_combox(combox& wdg): widget(wdg)

View File

@ -402,18 +402,20 @@ namespace nana
return{};
}
void create(nana::string&& text, unsigned pixels)
size_type create(nana::string&& text, unsigned pixels)
{
cont_.emplace_back(std::move(text), pixels, static_cast<size_type>(cont_.size()));
return cont_.back().index;
}
void item_width(size_type pos, unsigned width)
{
for(auto & m : cont_)
{
if(m.index == pos)
{
m.pixels = width;
}
return;
}
}
unsigned item_width(size_type pos) const
@ -1606,31 +1608,7 @@ namespace nana
}
/// set all items in cat to selection sel, emiting events, actualizing last_selected_abs, but not check for single_selection_
bool categ_selected(size_type cat, bool sel)
{
bool changed = false;
auto & items = _m_at(cat)->items;
index_pair pos(cat, 0);
for(auto & m : items)
{
if(m.flags.selected != sel)
{
m.flags.selected = sel;
arg_listbox arg{ item_proxy(ess_, pos), sel };
wd_ptr()->events().selected.emit(arg);
changed = true;
if (sel) // not check for single_selection_
last_selected_abs = pos;
else if (last_selected_abs == pos)
last_selected_abs.set_both(npos);
}
++pos.item;
}
return changed;
}
void categ_selected(size_type cat, bool sel);
void reverse_categ_selected(size_type categ)
{
@ -1658,9 +1636,22 @@ namespace nana
/// absolute position of the last displayed item
index_pair last_displ() const
{
return absolute ( last_displ() );
return absolute ( last() );
}
/// can be used as the absolute position of the first absolute item, or as the display pos of the first displayed item
index_pair first() const
{
index_pair fst{0,npos};
good_item(fst,fst);
return fst;
}
/// absolute position of the first displayed item
index_pair first_displ() const
{
return absolute ( first() );
}
bool good(size_type cat) const
{
return (cat < list_.size());
@ -1670,32 +1661,32 @@ namespace nana
{
return ((pos.cat < list_.size()) && (pos.item < size_item(pos.cat)));
}
/// if good return the same item (in arg item), or just the next cat and true, but If fail return false
bool good_item(index_pair pos, index_pair& item) const
{
if (!good(pos.cat))
return false;
return false; // cat out of range
if (pos.is_category())
{
item = pos;
if (0 == pos.cat)
item.item = 0;
return true;
item = pos; // return the cat self
if (0 == pos.cat) // but for cat 0 return first item
item.item = 0; // let check this is good
else
return true;
}
auto i = _m_at(pos.cat);
auto i = _m_at(pos.cat); // pos is not a cat and i point to it cat
if (pos.item < i->items.size())
{
item = pos;
item = pos; // good item, return it
return true;
}
if (++i == list_.end())
if (++i == list_.end()) // item out of range and no more cat
return false;
item.cat = pos.cat + 1;
item.cat = pos.cat + 1; // select the next cat
item.item = npos;
return true;
}
@ -1703,7 +1694,7 @@ namespace nana
///Translate relative position (position in display) into absolute position (original data order)
size_type absolute(const index_pair& display_pos) const
{
if(sorted_index_ == npos)
if(sorted_index_ == npos || display_pos.item == npos)
return display_pos.item ;
auto & catobj = *_m_at(display_pos.cat);
@ -2202,7 +2193,7 @@ namespace nana
}
else
{
new_where.second = (y - header_visible_px() + 1) / item_size;
new_where.second = ((y + 1) - header_visible_px()) / item_size; // y>1 !
new_where.first = parts::lister;
if(checkable)
{
@ -2324,6 +2315,27 @@ namespace nana
}
}
unsigned auto_width(size_type pos, unsigned max = 3000) /// \todo introduce parametr max_header_width
{
unsigned max_w{ 0 };
for (const auto &cat : lister.cat_container())
for (const auto &it : cat.items)
{
if (pos >= it.cells.size()) continue;
// precalcule text geometry
unsigned ts = static_cast<unsigned> (graph->text_extent_size(it.cells[pos].text).width);
if (max_w < ts)
max_w = ts;
}
if (!max_w) return 0;
unsigned ext_w = scheme_ptr->ext_w;
if (pos == 0 && checkable) // only before the first column (display_order=0 ?)
ext_w += 18;
header.item_width(pos, max_w + ext_w + 1 < max ? max_w + ext_w + 1 : max);
return max_w;
}
inline_pane * open_inline(pat::abstract_factory<inline_notifier_interface>* factory, inline_indicator* indicator)
{
std::unique_ptr<inline_pane> pane_ptr;
@ -2494,7 +2506,7 @@ namespace nana
}
}
nana::string es_lister::to_string(const export_options& exp_opt) const
nana::string es_lister::to_string(const export_options& exp_opt) const
{
nana::string list_str;
bool first{true};
@ -2515,6 +2527,17 @@ namespace nana
return list_str ;
}
void es_lister::categ_selected(size_type cat, bool sel)
{
cat_proxy cpx{ess_,cat};
for (item_proxy &it : cpx )
{
if (it.selected() != sel)
it.select(sel);
}
last_selected_abs = last_selected_dpl = index_pair {cat, npos};
}
class drawer_header_impl
{
@ -3450,6 +3473,14 @@ namespace nana
void trigger::dbl_click(graph_reference graph, const arg_mouse&)
{
if (essence_->pointer_where.first == essence_t::parts::header)
if (cursor::size_we == essence_->lister.wd_ptr()->cursor())
{
if (essence(). auto_width(drawer_header_->item_spliter() )) // ? in order
essence().update();
return;
}
if (essence_->pointer_where.first != essence_t::parts::lister)
return;
@ -3518,21 +3549,35 @@ namespace nana
if (! scrl.make_page_scroll(!up))
return;
essence_->lister.select_for_all(false);
if (up)
item_proxy {essence_, essence_->scroll_y_abs()}.select(true);
else
{
index_pair idx{essence_->scroll_y_dpl()};
index_pair idx{essence_->scroll_y_dpl()};
if (!up)
essence_->lister.forward(idx, scrl.range()-1, idx);
item_proxy::from_display(essence_,idx).select(true);
}
if (idx.is_item())
item_proxy::from_display(essence_, idx).select(true);
else
if(!essence_->lister.single_selection())
essence_->lister.categ_selected(idx.cat, true);
essence_->trace_last_selected_item ();
break;
}
case keyboard::os_home:
{
essence_->lister.select_for_all(false);
item_proxy::from_display(essence_, {0,0}).select(true);
index_pair frst{essence_->lister.first()};
if (frst.is_item())
item_proxy::from_display(essence_, frst).select(true);
else
if(!essence_->lister.single_selection())
essence_->lister.categ_selected(frst.cat, true);
essence_->trace_last_selected_item ();
break;
}
case keyboard::os_end:
essence_->lister.select_for_all(false);
item_proxy::from_display(essence_, essence_->lister.last()).select(true);
@ -3584,7 +3629,7 @@ namespace nana
{
auto i = ess_->lister.cat_container().begin();
std::advance(i, pos.cat);
cat_ = &(*i);
cat_ = &(*i); // what is pos is a cat?
}
}
@ -3617,6 +3662,7 @@ namespace nana
m.flags.checked = ck;
arg_listbox arg{*this, ck};
ess_->lister.wd_ptr()->events().checked.emit(arg);
ess_->update();
}
return *this;
}
@ -3629,7 +3675,7 @@ namespace nana
/// is ignored if no change (maybe set last_selected anyway??), but if change emit event, deselect others if need ans set/unset last_selected
item_proxy & item_proxy::select(bool s)
{
auto & m = cat_->items.at(pos_.item); // a ref to the real item
auto & m = cat_->items.at(pos_.item); // a ref to the real item // what is pos is a cat?
if(m.flags.selected == s) return *this; // ignore if no change
m.flags.selected = s; // actually change selection
@ -3646,6 +3692,7 @@ namespace nana
ess_->update();
ess_->update();
return *this;
}
@ -3865,6 +3912,24 @@ namespace nana
}
}
cat_proxy & cat_proxy::select(bool sel)
{
for (item_proxy &it : *this )
it.select(sel);
ess_->lister.last_selected_abs =
ess_->lister.last_selected_dpl = index_pair {this->pos_, npos};
return *this;
}
bool cat_proxy::selected() const
{
for (item_proxy &it : *this )
if (!it.selected())
return false;
return true;
}
auto cat_proxy::columns() const -> size_type
{
return ess_->header.cont().size();
@ -3907,6 +3972,11 @@ namespace nana
//Behavior of a container
item_proxy cat_proxy::begin() const
{
auto i = ess_->lister.cat_container().begin();
std::advance(i, pos_);
if (i->items.empty())
return end();
return item_proxy(ess_, index_pair(pos_, 0));
}
@ -4121,11 +4191,12 @@ namespace nana
_m_ess().set_auto_draw(ad);
}
void listbox::append_header(nana::string text, unsigned width)
listbox::size_type listbox::append_header(nana::string text, unsigned width)
{
auto & ess = _m_ess();
ess.header.create(std::move(text), width);
listbox::size_type index = ess.header.create(std::move(text), width);
ess.update();
return index;
}
listbox& listbox::header_width(size_type pos, unsigned pixels)
@ -4135,6 +4206,13 @@ namespace nana
ess.update();
return *this;
}
unsigned listbox::auto_width(size_type pos, unsigned max)
{
auto & ess = _m_ess();
unsigned max_w = ess.auto_width(pos, max);
ess.update();
return max_w;
}
unsigned listbox::header_width(size_type pos) const
{

View File

@ -114,7 +114,7 @@ namespace nana
{
if(at.item_state == state::active)
{
graph.rectangle(r, false, {0xa8, 0xd8, 0xeb});
graph.rectangle(r, false, static_cast<color_rgb>(0xa8d8eb));
nana::point points[4] = {
nana::point(r.x, r.y),
nana::point(r.x + r.width - 1, r.y),
@ -144,9 +144,9 @@ namespace nana
}
}
void item_image(graph_reference graph, const nana::point& pos, const paint::image& img)
void item_image(graph_reference graph, const nana::point& pos, unsigned image_px, const paint::image& img)
{
img.paste(graph, pos.x, pos.y);
img.stretch(rectangle{ img.size() }, graph, rectangle{ pos, ::nana::size(image_px, image_px) });
}
void item_text(graph_reference graph, const nana::point& pos, const nana::string& text, unsigned text_pixels, const attr& at)
@ -200,35 +200,35 @@ namespace nana
void checked(std::size_t index, bool check)
{
if(root_.items.size() > index)
if (root_.items.size() <= index)
return;
item_type & m = root_.items[index];
if(check && (checks::option == m.style))
{
item_type & m = root_.items[index];
if(check && (checks::option == m.style))
if(index)
{
if(index)
std::size_t i = index;
do
{
std::size_t i = index;
do
{
item_type& el = root_.items[--i];
if(el.flags.splitter) break;
if(checks::option == el.style)
el.flags.checked = false;
}while(i);
}
for(std::size_t i = index + 1; i < root_.items.size(); ++i)
{
item_type & el = root_.items[i];
item_type& el = root_.items[--i];
if(el.flags.splitter) break;
if(checks::option == el.style)
el.flags.checked = false;
}
}while(i);
}
for(std::size_t i = index + 1; i < root_.items.size(); ++i)
{
item_type & el = root_.items[i];
if(el.flags.splitter) break;
if(checks::option == el.style)
el.flags.checked = false;
}
m.flags.checked = check;
}
m.flags.checked = check;
}
menu_type& data()
@ -304,7 +304,7 @@ namespace nana
: public drawer_trigger
{
public:
typedef menu_item_type::item_proxy item_proxy;
using item_proxy = menu_item_type::item_proxy;
renderer_interface * renderer;
@ -330,12 +330,12 @@ namespace nana
detail_.monitor_pos = API::cursor_position();
}
void mouse_move(graph_reference, const arg_mouse& arg)
void mouse_move(graph_reference graph, const arg_mouse& arg)
{
state_.nullify_mouse = false;
if(track_mouse(arg.pos.x, arg.pos.y))
if(track_mouse(arg.pos))
{
draw();
refresh(graph);
API::lazy_refresh();
}
}
@ -350,9 +350,70 @@ namespace nana
state_.nullify_mouse = false;
}
void refresh(graph_reference)
void refresh(graph_reference graph)
{
draw();
if (nullptr == menu_) return;
_m_adjust_window_size();
renderer->background(graph, *widget_);
const unsigned item_h_px = _m_item_height();
const unsigned image_px = item_h_px - 2;
nana::rectangle item_r(2, 2, graph_->width() - 4, item_h_px);
unsigned strpixels = item_r.width - 60;
int text_top_off = (item_h_px - graph.text_extent_size(STR("jh({[")).height) / 2;
std::size_t pos = 0;
for (auto & m : menu_->items)
{
if (m.flags.splitter)
{
graph_->set_color(colors::gray_border);
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph.width()) - 1, item_r.y });
item_r.y += 2;
++pos;
continue;
}
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
//Draw item background
renderer->item(*graph_, item_r, attr);
//Draw text, the text is transformed from orignal for hotkey character
nana::char_t hotkey;
nana::string::size_type hotkey_pos;
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
if (m.image.empty() == false)
renderer->item_image(graph, nana::point(item_r.x + 5, item_r.y + static_cast<int>(item_h_px - image_px) / 2 - 1), image_px, m.image);
renderer->item_text(graph, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
if (hotkey)
{
m.hotkey = hotkey;
if (m.flags.enabled)
{
unsigned off_w = (hotkey_pos ? graph.text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
nana::size hotkey_size = graph.text_extent_size(text.c_str() + hotkey_pos, 1);
int x = item_r.x + 40 + off_w;
int y = item_r.y + text_top_off + hotkey_size.height;
graph_->set_color(colors::black);
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
}
}
if (m.sub_menu)
renderer->sub_arrow(graph, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
item_r.y += item_r.height + 1;
++pos;
}
}
std::size_t active() const
@ -411,21 +472,21 @@ namespace nana
state_.active = pos;
state_.sub_window = false;
draw();
refresh(*graph_);
return true;
}
return false;
}
bool track_mouse(int x, int y)
bool track_mouse(const ::nana::point& pos)
{
if(state_.nullify_mouse == false)
if (!state_.nullify_mouse)
{
std::size_t index = _m_get_index_by_pos(x, y);
if(index != state_.active)
std::size_t index = _m_get_index_by_pos(pos.x, pos.y);
if (index != state_.active)
{
if((index == npos) && menu_->items.at(state_.active).sub_menu && state_.sub_window)
if ((index == npos) && menu_->items.at(state_.active).sub_menu && state_.sub_window)
return false;
state_.active = (index != npos && menu_->items.at(index).flags.splitter) ? npos : index;
@ -433,6 +494,7 @@ namespace nana
return true;
}
}
return false;
}
@ -451,29 +513,35 @@ namespace nana
state_.sub_window = subw;
}
menu_type* retrive_sub_menu(nana::point& pos, std::size_t interval) const
menu_type* get_sub(nana::point& pos, unsigned long& tmstamp) const
{
if(state_.active != npos && (nana::system::timestamp() - state_.active_timestamp >= interval))
if (npos == state_.active)
return nullptr;
auto sub = menu_->items.at(state_.active).sub_menu;
if (sub)
{
pos.x = graph_->width() - 2;
pos.x = static_cast<int>(graph_->width()) - 2;
pos.y = 2;
std::size_t index = 0;
for(auto & m : menu_->items)
auto index = state_.active;
for (auto & m : menu_->items)
{
if(false == m.flags.splitter)
if (m.flags.splitter)
{
if(index == state_.active)
break;
pos.y += _m_item_height() + 1;
}
else
pos.y += 2;
continue;
}
++index;
if (0 == index)
break;
pos.y += _m_item_height() + 1;
--index;
}
return (menu_->items.at(state_.active).sub_menu);
tmstamp = state_.active_timestamp;
return sub;
}
return nullptr;
}
@ -498,8 +566,7 @@ namespace nana
state_.active = index;
state_.active_timestamp = nana::system::timestamp();
draw();
API::update_window(*widget_);
API::refresh_window(*widget_);
return 2;
}
else if(m.flags.enabled)
@ -514,71 +581,6 @@ namespace nana
}
return 0;
}
void draw() const
{
if(nullptr == menu_) return;
_m_adjust_window_size();
renderer->background(*graph_, *widget_);
const unsigned item_h_px = _m_item_height();
nana::rectangle item_r(2, 2, graph_->width() - 4, item_h_px);
unsigned strpixels = item_r.width - 60;
int text_top_off = (item_h_px - graph_->text_extent_size(STR("jh({[")).height) / 2;
std::size_t pos = 0;
for(auto & m : menu_->items)
{
if(m.flags.splitter)
{
graph_->set_color(colors::gray_border);
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph_->width()) - 1, item_r.y });
item_r.y += 2;
++pos;
continue;
}
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
//Draw item background
renderer->item(*graph_, item_r, attr);
//Draw text, the text is transformed from orignal for hotkey character
nana::char_t hotkey;
nana::string::size_type hotkey_pos;
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
if(m.image.empty() == false)
renderer->item_image(*graph_, nana::point(item_r.x + 5, item_r.y + (item_h_px - m.image.size().height) / 2), m.image);
renderer->item_text(*graph_, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
if(hotkey)
{
m.hotkey = hotkey;
if(m.flags.enabled)
{
unsigned off_w = (hotkey_pos ? graph_->text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
nana::size hotkey_size = graph_->text_extent_size(text.c_str() + hotkey_pos, 1);
int x = item_r.x + 40 + off_w;
int y = item_r.y + text_top_off + hotkey_size.height;
graph_->set_color(colors::black);
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
}
}
if(m.sub_menu)
renderer->sub_arrow(*graph_, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
item_r.y += item_r.height + 1;
++pos;
}
}
private:
static renderer_interface::attr _m_make_renderer_attr(bool active, const menu_item_type & m)
{
@ -683,10 +685,10 @@ namespace nana
struct state
{
std::size_t active;
unsigned long active_timestamp;
unsigned long sub_window: 1;
unsigned long nullify_mouse: 1;
std::size_t active;
unsigned active_timestamp;
bool sub_window: 1;
bool nullify_mouse: 1;
}state_;
struct widget_detail
@ -699,15 +701,18 @@ namespace nana
class menu_window
: public widget_object<category::root_tag, menu_drawer>
{
typedef menu_drawer drawer_type;
typedef widget_object<category::root_tag, menu_drawer> base_type;
using drawer_type = menu_drawer;
using base_type = widget_object<category::root_tag, menu_drawer>;
public:
typedef menu_builder::item_type item_type;
using item_type = menu_builder::item_type;
menu_window(window wd, const point& pos, renderer_interface * rdptr)
menu_window(window wd, bool is_wd_parent_menu, const point& pos, renderer_interface * rdptr)
//add a is_wd_parent_menu to determine whether the menu wants the focus.
//if a submenu gets the focus, the program may cause a crash error when the submenu is being destroyed
: base_type(wd, false, rectangle(pos, nana::size(2, 2)), appear::bald<appear::floating>()),
want_focus_(nullptr == wd || (API::focus_window() != wd)),
event_focus_(nullptr)
want_focus_{ (!wd) || ((!is_wd_parent_menu) && (API::focus_window() != wd)) },
event_focus_{ nullptr }
{
caption(STR("nana menu window"));
get_drawer_trigger().close_menu_tree([this]{ this->_m_close_all(); });
@ -718,7 +723,19 @@ namespace nana
submenu_.child = submenu_.parent = nullptr;
submenu_.object = nullptr;
_m_make_mouse_event();
state_.mouse_pos = API::cursor_position();
events().mouse_move.connect_unignorable([this]{
nana::point pos = API::cursor_position();
if (pos != state_.mouse_pos)
{
menu_window * root = this;
while (root->submenu_.parent)
root = root->submenu_.parent;
root->state_.auto_popup_submenu = true;
state_.mouse_pos = pos;
}
});
}
void popup(menu_type& menu, bool owner_menubar)
@ -745,13 +762,19 @@ namespace nana
_m_key_down(arg);
});
events().mouse_up.connect_unignorable([this]{
pick();
events().mouse_down.connect_unignorable([this](const arg_mouse& arg)
{
this->_m_open_sub(0); //Try to open submenu immediately
});
events().mouse_up.connect_unignorable([this](const arg_mouse& arg){
if (arg.left_button)
pick();
});
timer_.interval(100);
timer_.elapse([this]{
this->_m_check_repeatly();
this->_m_open_sub(500); //Try to open submenu
});
timer_.start();
@ -797,29 +820,27 @@ namespace nana
bool submenu(bool enter)
{
menu_window * object = this;
while (object->submenu_.child)
object = object->submenu_.child;
menu_window * menu_wd = this;
while (menu_wd->submenu_.child)
menu_wd = menu_wd->submenu_.child;
state_.auto_popup_submenu = false;
if (enter)
if (!enter)
{
if (object->submenu_.parent)
if (menu_wd->submenu_.parent)
{
auto & sub = object->submenu_.parent->submenu_;
auto & sub = menu_wd->submenu_.parent->submenu_;
sub.child = nullptr;
sub.object = nullptr;
object->close();
menu_wd->close();
return true;
}
return false;
}
nana::point pos;
menu_type * sbm = object->get_drawer_trigger().retrive_sub_menu(pos, 0);
return object->_m_show_submenu(sbm, pos, true);
return menu_wd->_m_manipulate_sub(0, true);
}
int send_shortkey(nana::char_t key)
@ -965,63 +986,51 @@ namespace nana
}
}
void _m_make_mouse_event()
bool _m_manipulate_sub(unsigned long delay_ms, bool forced)
{
state_.mouse_pos = API::cursor_position();
events().mouse_move.connect_unignorable([this]{
_m_mouse_event();
});
}
auto & drawer = get_drawer_trigger();
::nana::point pos;
unsigned long tmstamp;
void _m_mouse_event()
{
nana::point pos = API::cursor_position();
if(pos != state_.mouse_pos)
auto menu_ptr = drawer.get_sub(pos, tmstamp);
if (menu_ptr == submenu_.object)
return false;
if (menu_ptr && (::nana::system::timestamp() - tmstamp < delay_ms))
return false;
if (submenu_.object && (menu_ptr != submenu_.object))
{
menu_window * root = this;
while(root->submenu_.parent)
root = root->submenu_.parent;
root->state_.auto_popup_submenu = true;
state_.mouse_pos = pos;
}
}
bool _m_show_submenu(menu_type* sbm, nana::point pos, bool forced)
{
auto & mdtrigger = get_drawer_trigger();
if(submenu_.object && (sbm != submenu_.object))
{
mdtrigger.set_sub_window(false);
drawer.set_sub_window(false);
submenu_.child->close();
submenu_.child = nullptr;
submenu_.object = nullptr;
}
if(sbm)
if (menu_ptr)
{
menu_window * root = this;
while(root->submenu_.parent)
while (root->submenu_.parent)
root = root->submenu_.parent;
if((submenu_.object == nullptr) && sbm && (forced || root->state_.auto_popup_submenu))
if ((submenu_.object == nullptr) && menu_ptr && (forced || root->state_.auto_popup_submenu))
{
sbm->item_pixels = mdtrigger.data()->item_pixels;
sbm->gaps = mdtrigger.data()->gaps;
pos.x += sbm->gaps.x;
pos.y += sbm->gaps.y;
menu_ptr->item_pixels = drawer.data()->item_pixels;
menu_ptr->gaps = drawer.data()->gaps;
pos += menu_ptr->gaps;
menu_window & mwnd = form_loader<menu_window, false>()(handle(), pos, mdtrigger.renderer);
menu_window & mwnd = form_loader<menu_window, false>()(handle(), true, pos, drawer.renderer);
mwnd.state_.self_submenu = true;
submenu_.child = & mwnd;
submenu_.child = &mwnd;
submenu_.child->submenu_.parent = this;
submenu_.object = sbm;
submenu_.object = menu_ptr;
API::set_window_z_order(handle(), mwnd.handle(), z_order_action::none);
mwnd.popup(*sbm, state_.owner_menubar);
mdtrigger.set_sub_window(true);
if(forced)
mwnd.popup(*menu_ptr, state_.owner_menubar);
drawer.set_sub_window(true);
if (forced)
mwnd.goto_next(true);
return true;
@ -1030,17 +1039,16 @@ namespace nana
return false;
}
void _m_check_repeatly()
void _m_open_sub(unsigned delay_ms) //check_repeatly
{
if(state_.auto_popup_submenu)
{
nana::point pos = API::cursor_position();
auto pos = API::cursor_position();
drawer_type& drawer = get_drawer_trigger();
API::calc_window_point(handle(), pos);
drawer.track_mouse(pos.x, pos.y);
menu_type* sbm = drawer.retrive_sub_menu(pos, 500);
_m_show_submenu(sbm, pos, false);
get_drawer_trigger().track_mouse(pos);
_m_manipulate_sub(delay_ms, false);
}
}
private:
@ -1293,7 +1301,7 @@ namespace nana
{
close();
impl_->uiobj = &(form_loader<drawerbase::menu::menu_window, false>()(wd, point(x, y), &(*impl_->mbuilder.renderer())));
impl_->uiobj = &(form_loader<drawerbase::menu::menu_window, false>()(wd, false, point(x, y), &(*impl_->mbuilder.renderer())));
impl_->uiobj->events().destroy.connect_unignorable([this]{
impl_->uiobj = nullptr;
if (impl_->destroy_answer)

View File

@ -89,6 +89,15 @@ namespace nana
{
return unknown_;
}
bool trigger::stoped() const
{
return stop_;
}
bool trigger::stop(bool s)
{
std::swap(s,stop_);
return s;
}
void trigger::refresh(graph_reference)
{
@ -197,5 +206,13 @@ namespace nana
{
return get_drawer_trigger().unknown();
}
bool progress::stop(bool s)
{
return get_drawer_trigger().stop(s);
}
bool progress::stoped() const
{
return get_drawer_trigger().stoped();
}
//end class progress
}//end namespace nana

View File

@ -1482,6 +1482,8 @@ namespace nana{ namespace widgets
behavior_->pre_calc_lines(width_pixels());
_m_scrollbar();
move_caret(points_.caret);
return true;
}

View File

@ -11,10 +11,10 @@
*/
#include <nana/gui/widgets/toolbar.hpp>
#include <vector>
#include <stdexcept>
#include <nana/gui/tooltip.hpp>
#include <vector>
namespace nana
{
arg_toolbar::arg_toolbar(toolbar& tbar, std::size_t btn)
@ -25,13 +25,6 @@ namespace nana
{
namespace toolbar
{
struct listitem
{
nana::string text;
nana::paint::image image;
bool enable;
};
struct item_type
{
enum kind{ button, container};
@ -43,28 +36,23 @@ namespace nana
unsigned pixels{0};
nana::size textsize;
bool enable{true};
window other{nullptr};
kind type;
std::function<void(size_type, size_type)> answer;
std::vector<listitem> children;
item_type(const nana::string& text, const nana::paint::image& img, kind type)
:text(text), image(img), type(type)
{}
};
class container
{
container(const container&) = delete;
container& operator=(const container&) = delete;
public:
typedef std::vector<item_type*>::size_type size_type;
typedef std::vector<item_type*>::iterator iterator;
typedef std::vector<item_type*>::const_iterator const_iterator;
container() = default;
~container()
class item_container
{
public:
using container_type = std::vector<item_type*>;
using size_type = container_type::size_type;
~item_container()
{
for(auto ptr : cont_)
delete ptr;
@ -98,7 +86,7 @@ namespace nana
cont_.push_back(nullptr);
}
void push_back()
void separate()
{
cont_.push_back(nullptr);
}
@ -108,35 +96,17 @@ namespace nana
return cont_.size();
}
item_type* at(size_type n)
container_type& container()
{
if(n < cont_.size())
return cont_[n];
throw std::out_of_range("toolbar: bad index!");
return cont_;
}
iterator begin()
item_type * at(size_type pos)
{
return cont_.begin();
}
iterator end()
{
return cont_.end();
}
const_iterator begin() const
{
return cont_.cbegin();
}
const_iterator end() const
{
return cont_.cend();
return cont_.at(pos);
}
private:
std::vector<item_type*> cont_;
container_type cont_;
};
class item_renderer
@ -152,38 +122,36 @@ namespace nana
void operator()(int x, int y, unsigned width, unsigned height, item_type& item, state_t state)
{
//draw background
if(state != state_t::normal)
graph.rectangle({ x, y, width, height }, false, { 0x33, 0x99, 0xFF });
switch(state)
if (state != state_t::normal)
{
case state_t::highlighted:
graph.gradual_rectangle({ x + 1, y + 1, width - 2, height - 2 }, bgcolor, { 0xC0, 0xDD, 0xFC }, true);
break;
case state_t::selected:
graph.gradual_rectangle({ x + 1, y + 1, width - 2, height - 2 }, bgcolor, { 0x99, 0xCC, 0xFF }, true);
default: break;
nana::rectangle background_r(x, y, width, height);
graph.rectangle(background_r, false, static_cast<color_rgb>(0x3399FF));
if (state_t::highlighted == state || state_t::selected == state)
graph.gradual_rectangle(background_r.pare_off(1), bgcolor, static_cast<color_rgb>(state_t::selected == state ? 0x99CCFF : 0xC0DDFC), true);
}
if(item.image.empty() == false)
if(!item.image.empty())
{
nana::size size = item.image.size();
if(size.width > scale) size.width = scale;
if(size.height > scale) size.height = scale;
auto imgsize = item.image.size();
if (imgsize.width > scale) imgsize.width = scale;
if (imgsize.height > scale) imgsize.height = scale;
nana::point pos(x, y);
pos.x += static_cast<int>(scale + extra_size - size.width) / 2;
pos.y += static_cast<int>(height - size.height) / 2;
pos.x += static_cast<int>(scale + extra_size - imgsize.width) / 2;
pos.y += static_cast<int>(height - imgsize.height) / 2;
item.image.paste(::nana::rectangle{ size }, graph, pos);
item.image.paste(::nana::rectangle{ imgsize }, graph, pos);
if(item.enable == false)
{
nana::paint::graphics gh(size);
gh.bitblt(::nana::rectangle{ size }, graph, pos);
nana::paint::graphics gh(imgsize);
gh.bitblt(::nana::rectangle{ imgsize }, graph, pos);
gh.rgb_to_wb();
gh.paste(graph, pos.x, pos.y);
}
else if(state == state_t::normal)
graph.blend(nana::rectangle(pos, size), ::nana::color(0xc0, 0xdd, 0xfc).blend(bgcolor, 0.5), 0.25);
graph.blend(nana::rectangle(pos, imgsize), ::nana::color(0xc0, 0xdd, 0xfc).blend(bgcolor, 0.5), 0.25);
x += scale;
width -= scale;
@ -204,13 +172,15 @@ namespace nana
struct drawer::drawer_impl_type
{
event_handle event_size{nullptr};
event_handle event_size{ nullptr };
paint::graphics* graph_ptr{ nullptr };
unsigned scale{16};
bool textout{false};
size_type which{npos};
item_renderer::state_t state{item_renderer::state_t::normal};
container cont;
item_container items;
::nana::tooltip tooltip;
};
@ -225,116 +195,118 @@ namespace nana
delete impl_;
}
void drawer::append(const nana::string& text, const nana::paint::image& img)
item_container& drawer::items() const
{
impl_->cont.push_back(text, img);
}
void drawer::append()
{
impl_->cont.push_back();
}
bool drawer::enable(drawer::size_type n) const
{
if(impl_->cont.size() > n)
{
auto item = impl_->cont.at(n);
return (item && item->enable);
}
return false;
}
bool drawer::enable(size_type n, bool eb)
{
if(impl_->cont.size() > n)
{
item_type * item = impl_->cont.at(n);
if(item && (item->enable != eb))
{
item->enable = eb;
return true;
}
}
return false;
return impl_->items;
}
void drawer::scale(unsigned s)
{
impl_->scale = s;
for(auto m : impl_->cont)
_m_fill_pixels(m, true);
for(auto m : impl_->items.container())
_m_calc_pixels(m, true);
}
void drawer::refresh(graph_reference)
void drawer::refresh(graph_reference graph)
{
_m_draw();
int x = 2, y = 2;
auto bgcolor = API::bgcolor(widget_->handle());
graph.set_text_color(bgcolor);
graph.gradual_rectangle(rectangle{ graph.size() }, bgcolor.blend(colors::white, 0.9), bgcolor.blend(colors::black, 0.95), true);
item_renderer ir(graph, impl_->textout, impl_->scale, bgcolor);
size_type index = 0;
for (auto item : impl_->items.container())
{
if (item)
{
_m_calc_pixels(item, false);
ir(x, y, item->pixels, impl_->scale + ir.extra_size, *item, (index == impl_->which ? impl_->state : item_renderer::state_t::normal));
x += item->pixels;
}
else
{
x += 2;
graph.line({ x, y + 2 }, { x, y + static_cast<int>(impl_->scale + ir.extra_size) - 4 }, static_cast<color_rgb>(0x808080));
x += 4;
}
++index;
}
}
void drawer::attached(widget_reference widget, graph_reference graph)
{
graph_ = &graph;
impl_->graph_ptr = &graph;
widget_ = static_cast< ::nana::toolbar*>(&widget);
widget.caption(STR("Nana Toolbar"));
impl_->event_size = widget.events().resized.connect_unignorable(std::bind(&drawer::_m_owner_sized, this, std::placeholders::_1));
widget.caption(L"Nana Toolbar");
impl_->event_size = API::events(widget.parent()).resized.connect_unignorable([this](const arg_resized& arg)
{
auto wd = widget_->handle();
API::window_size(wd, nana::size(arg.width, widget_->size().height));
API::update_window(wd);
});
}
void drawer::detached()
{
API::umake_event(impl_->event_size);
impl_->event_size = nullptr;
impl_->graph_ptr = nullptr;
}
void drawer::mouse_move(graph_reference graph, const arg_mouse& arg)
{
if(arg.left_button == false)
if (arg.left_button)
return;
size_type which = _m_which(arg.pos, true);
if(impl_->which != which)
{
size_type which = _m_which(arg.pos.x, arg.pos.y, true);
if(impl_->which != which)
auto & container = impl_->items.container();
if (impl_->which != npos && container.at(impl_->which)->enable)
{
if (impl_->which != npos && impl_->cont.at(impl_->which)->enable)
{
::nana::arg_toolbar arg{ *widget_, impl_->which };
widget_->events().leave.emit(arg);
}
impl_->which = which;
if(which == npos || impl_->cont.at(which)->enable)
{
impl_->state = (arg.left_button ? item_renderer::state_t::selected : item_renderer::state_t::highlighted);
_m_draw();
API::lazy_refresh();
if (impl_->state == item_renderer::state_t::highlighted)
{
::nana::arg_toolbar arg{ *widget_, which };
widget_->events().enter.emit(arg);
}
}
if(which != npos)
impl_->tooltip.show(widget_->handle(), nana::point(arg.pos.x, arg.pos.y + 20), (*(impl_->cont.begin() + which))->text, 0);
else
impl_->tooltip.close();
::nana::arg_toolbar arg{ *widget_, impl_->which };
widget_->events().leave.emit(arg);
}
impl_->which = which;
if (which == npos || container.at(which)->enable)
{
impl_->state = (arg.left_button ? item_renderer::state_t::selected : item_renderer::state_t::highlighted);
refresh(graph);
API::lazy_refresh();
if (impl_->state == item_renderer::state_t::highlighted)
{
::nana::arg_toolbar arg{ *widget_, which };
widget_->events().enter.emit(arg);
}
}
if(which != npos)
impl_->tooltip.show(widget_->handle(), nana::point(arg.pos.x, arg.pos.y + 20), (*(container.begin() + which))->text, 0);
else
impl_->tooltip.close();
}
}
void drawer::mouse_leave(graph_reference, const arg_mouse&)
void drawer::mouse_leave(graph_reference graph, const arg_mouse&)
{
if(impl_->which != npos)
{
size_type which = impl_->which;
impl_->which = npos;
_m_draw();
refresh(graph);
API::lazy_refresh();
if (which != npos && impl_->cont.at(which)->enable)
if (which != npos && impl_->items.at(which)->enable)
{
::nana::arg_toolbar arg{ *widget_, which };
widget_->events().leave.emit(arg);
@ -343,22 +315,22 @@ namespace nana
impl_->tooltip.close();
}
void drawer::mouse_down(graph_reference, const arg_mouse&)
void drawer::mouse_down(graph_reference graph, const arg_mouse&)
{
impl_->tooltip.close();
if(impl_->which != npos && (impl_->cont.at(impl_->which)->enable))
if(impl_->which != npos && (impl_->items.at(impl_->which)->enable))
{
impl_->state = item_renderer::state_t::selected;
_m_draw();
refresh(graph);
API::lazy_refresh();
}
}
void drawer::mouse_up(graph_reference, const arg_mouse& arg)
void drawer::mouse_up(graph_reference graph, const arg_mouse& arg)
{
if(impl_->which != npos)
{
size_type which = _m_which(arg.pos.x, arg.pos.y, false);
size_type which = _m_which(arg.pos, false);
if(impl_->which == which)
{
::nana::arg_toolbar arg{ *widget_, which };
@ -372,89 +344,47 @@ namespace nana
impl_->state = (which == npos ? item_renderer::state_t::normal : item_renderer::state_t::highlighted);
}
_m_draw();
refresh(graph);
API::lazy_refresh();
}
}
drawer::size_type drawer::_m_which(int x, int y, bool want_if_disabled) const
drawer::size_type drawer::_m_which(point pos, bool want_if_disabled) const
{
if(x < 2 || y < 2 || y >= static_cast<int>(impl_->scale + item_renderer::extra_size + 2)) return npos;
if (pos.x < 2 || pos.y < 2 || pos.y >= static_cast<int>(impl_->scale + item_renderer::extra_size + 2)) return npos;
x -= 2;
pos.x -= 2;
size_type pos = 0;
for(auto m: impl_->cont)
std::size_t index = 0;
for(auto m: impl_->items.container())
{
bool compart = (nullptr == m);
auto px = static_cast<const int>(m ? m->pixels : 3);
if(x < static_cast<int>(compart ? 3 : m->pixels))
return ((compart || (m->enable == false && want_if_disabled == false)) ? npos : pos);
if(pos.x < px)
return (((!m) || (!m->enable && !want_if_disabled)) ? npos : index);
x -= (compart ? 3 : m->pixels);
pos.x -= px;
++pos;
++index;
}
return npos;
}
void drawer::_m_draw_background(const ::nana::color& clr)
void drawer::_m_calc_pixels(item_type* item, bool force)
{
graph_->gradual_rectangle(::nana::rectangle{ graph_->size() }, clr.blend(colors::white, 0.9), clr.blend(colors::black, 0.95), true);
}
void drawer::_m_draw()
{
int x = 2, y = 2;
auto bgcolor = API::bgcolor(widget_->handle());
graph_->set_text_color(bgcolor);
_m_draw_background(bgcolor);
item_renderer ir(*graph_, impl_->textout, impl_->scale, bgcolor);
size_type index = 0;
for(auto item : impl_->cont)
if (item && (force || (0 == item->pixels)))
{
if(item)
{
_m_fill_pixels(item, false);
ir(x, y, item->pixels, impl_->scale + ir.extra_size, *item, (index == impl_->which ? impl_->state : item_renderer::state_t::normal));
x += item->pixels;
}
else
{
graph_->line({ x + 2, y + 2 }, { x + 2, y + static_cast<int>(impl_->scale + ir.extra_size) - 4 }, { 0x80, 0x80, 0x80 });
x += 6;
}
++index;
}
}
if (item->text.size())
item->textsize = impl_->graph_ptr->text_extent_size(item->text);
void drawer::_m_owner_sized(const arg_resized& arg)
{
auto wd = widget_->handle();
API::window_size(wd, nana::size(arg.width, widget_->size().height));
_m_draw();
API::update_window(wd);
}
void drawer::_m_fill_pixels(item_type* item, bool force)
{
if(item && (force || (0 == item->pixels)))
{
if(item->text.size())
item->textsize = graph_->text_extent_size(item->text);
if(item->image.empty() == false)
if (item->image.empty() == false)
item->pixels = impl_->scale + item_renderer::extra_size;
if(item->textsize.width && impl_->textout)
if (item->textsize.width && impl_->textout)
item->pixels += item->textsize.width + 8;
}
}
//};//class drawer
//class drawer
}//end namespace toolbar
}//end namespace drawerbase
@ -469,33 +399,48 @@ namespace nana
create(wd, r, visible);
}
void toolbar::append()
void toolbar::separate()
{
get_drawer_trigger().append();
get_drawer_trigger().items().separate();
API::refresh_window(handle());
}
void toolbar::append(const nana::string& text, const nana::paint::image& img)
{
get_drawer_trigger().append(text, img);
get_drawer_trigger().items().push_back(text, img);
API::refresh_window(handle());
}
void toolbar::append(const nana::string& text)
{
get_drawer_trigger().append(text, nana::paint::image());
get_drawer_trigger().items().push_back(text, {});
API::refresh_window(this->handle());
}
bool toolbar::enable(size_type n) const
bool toolbar::enable(size_type pos) const
{
return get_drawer_trigger().enable(n);
auto & items = get_drawer_trigger().items();
if (items.size() <= pos)
return false;
auto m = items.at(pos);
return (m && m->enable);
}
void toolbar::enable(size_type n, bool eb)
void toolbar::enable(size_type pos, bool eb)
{
if(get_drawer_trigger().enable(n, eb))
API::refresh_window(this->handle());
auto & items = get_drawer_trigger().items();
if (items.size() > pos)
{
auto m = items.at(pos);
if (m && (m->enable != eb))
{
m->enable = eb;
API::refresh_window(this->handle());
}
}
}
void toolbar::scale(unsigned s)
@ -503,5 +448,5 @@ namespace nana
get_drawer_trigger().scale(s);
API::refresh_window(handle());
}
//}; class toolbar
//end class toolbar
}//end namespace nana

View File

@ -156,6 +156,9 @@ namespace detail
nana::size text_extent_size(drawable_type dw, const nana::char_t * text, std::size_t len)
{
if (nullptr == dw || nullptr == text || 0 == len)
return{};
nana::size extents = raw_text_extent_size(dw, text, len);
const nana::char_t* const end = text + len;