diff --git a/CMakeLists.txt b/CMakeLists.txt index 242a1ea2..3fbd6ed5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,13 @@ if(BIICODE) # we'll use the default config file so we can iliminate the following macro definitions if(MSVC) # More MSVC specific compilation flags - add_definitions(-D_SCL_SECURE_NO_WARNINGS) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_SCL_SECURE_NO_WARNINGS) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + if(MSVC14) + add_definitions(-DSTD_CODECVT_NOT_SUPPORTED) + else() + add_definitions(-DNOT_IMPLEMENTED_KEYWORD_noexcept) + endif() endif() add_biicode_targets() diff --git a/build/codeblocks/nana.cbp b/build/codeblocks/nana.cbp index fb1a1b55..9302ebd6 100644 --- a/build/codeblocks/nana.cbp +++ b/build/codeblocks/nana.cbp @@ -102,7 +102,6 @@ - diff --git a/build/codeblocks/nana.depend b/build/codeblocks/nana.depend index a2318fdf..f7f24eaa 100644 --- a/build/codeblocks/nana.depend +++ b/build/codeblocks/nana.depend @@ -537,3 +537,633 @@ 1399002439 source:d:\privates\nana\release\nana.cpp11\source\gui\detail\element_store.cpp +1363362719 source:d:\git.repo\nana\source\any.cpp + + +1362509572 source:d:\git.repo\nana\source\audio\detail\audio_device.cpp + + + + + + + +1439496157 source:d:\git.repo\nana\source\audio\detail\audio_stream.cpp + + + +1362509721 source:d:\git.repo\nana\source\audio\detail\buffer_preparation.cpp + + + +1353253406 source:d:\git.repo\nana\source\audio\player.cpp + + + + + + +1439496157 source:d:\git.repo\nana\source\basic_types.cpp + + + + + + +1439496157 source:d:\git.repo\nana\source\charset.cpp + + + + + + + + +1439496157 source:d:\git.repo\nana\source\datetime.cpp + + + + + +1439496157 source:d:\git.repo\nana\source\deploy.cpp + + + + + + + +1439496157 source:d:\git.repo\nana\source\detail\platform_spec_selector.cpp + + "win32/platform_spec.cpp" + "linux_X11/platform_spec.cpp" + +1439496157 d:\git.repo\nana\source\detail\win32\platform_spec.cpp + + + + + +1439496157 d:\git.repo\nana\source\detail\linux_x11\platform_spec.cpp + + + + + + + + + + + + + "msg_dispatcher.hpp" + +1439496157 d:\git.repo\nana\source\detail\linux_x11\msg_dispatcher.hpp + + + + + + + + + + +1365203880 source:d:\git.repo\nana\source\exceptions.cpp + + +1365203878 source:d:\git.repo\nana\source\filesystem\file_iterator.cpp + + +1365203878 source:d:\git.repo\nana\source\filesystem\fs_utility.cpp + + + + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\animation.cpp + + + + + + + + + + + + + + +1423350892 source:d:\git.repo\nana\source\gui\basis.cpp + + +1439496157 source:d:\git.repo\nana\source\gui\detail\basic_window.cpp + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\bedrock_pi.cpp + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\bedrock_selector.cpp + + "win32/bedrock.cpp" + "linux_X11/bedrock.cpp" + +1439496157 d:\git.repo\nana\source\gui\detail\win32\bedrock.cpp + + + + + + + + + + + + + + +1439496157 d:\git.repo\nana\source\gui\detail\linux_x11\bedrock.cpp + + + + + + + + + + +1423350892 source:d:\git.repo\nana\source\gui\detail\color_schemes.cpp + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\drawer.cpp + + + + + + + + +1408986718 source:d:\git.repo\nana\source\gui\detail\element_store.cpp + + +1439496157 source:d:\git.repo\nana\source\gui\detail\events_operation.cpp + + +1439828940 source:d:\git.repo\nana\source\gui\detail\native_window_interface.cpp + + + + + + + "../../paint/detail/image_ico.hpp" + + + +1439496158 d:\git.repo\nana\source\paint\detail\image_ico.hpp + + +1439496157 source:d:\git.repo\nana\source\gui\detail\window_layout.cpp + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\window_manager.cpp + + + + + + + + + + + +1439746409 source:d:\git.repo\nana\source\gui\dragger.cpp + + +1423350892 source:d:\git.repo\nana\source\gui\drawing.cpp + + + + +1439496157 source:d:\git.repo\nana\source\gui\effects.cpp + + + +1439829040 source:d:\git.repo\nana\source\gui\element.cpp + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\filebox.cpp + + + + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\layout_utility.cpp + + +1439496157 source:d:\git.repo\nana\source\gui\msgbox.cpp + + + + + + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\notifier.cpp + + + + + + + + + + + + +1439746410 source:d:\git.repo\nana\source\gui\programming_interface.cpp + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\screen.cpp + + + + + + + +1415011766 source:d:\git.repo\nana\source\gui\state_cursor.cpp + + + + +1439496158 source:d:\git.repo\nana\source\gui\timer.cpp + + + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\tooltip.cpp + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\button.cpp + + + +1439829040 source:d:\git.repo\nana\source\gui\widgets\categorize.cpp + + + + + + + +1439829040 source:d:\git.repo\nana\source\gui\widgets\checkbox.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\combox.cpp + + + + + + + + + +1439829040 source:d:\git.repo\nana\source\gui\widgets\date_chooser.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\float_listbox.cpp + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\form.cpp + + +1408985395 source:d:\git.repo\nana\source\gui\widgets\frame.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\group.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\label.cpp + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\listbox.cpp + + + + + + + + + + + + +1439828820 source:d:\git.repo\nana\source\gui\widgets\menu.cpp + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\menubar.cpp + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\panel.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\picture.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\progress.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\scroll.cpp + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\skeletons\text_editor.cpp + + + + + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\slider.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\spinbox.cpp + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\textbox.cpp + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\toolbar.cpp + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\treebox.cpp + + + + + + + +1439746410 source:d:\git.repo\nana\source\gui\widgets\widget.cpp + + + + +1408984042 source:d:\git.repo\nana\source\gui\wvl.cpp + + +1425221155 source:d:\git.repo\nana\source\internationalization.cpp + + + + + + + +1423350893 source:d:\git.repo\nana\source\paint\detail\image_process_provider.cpp + + + +1439496158 source:d:\git.repo\nana\source\paint\detail\native_paint_interface.cpp + + + + + + + +1439746289 source:d:\git.repo\nana\source\paint\graphics.cpp + + + + + + + + + + + +1439496158 source:d:\git.repo\nana\source\paint\image.cpp + + + + + + + + + "detail/image_png.hpp" + "detail/image_bmp.hpp" + "detail/image_ico.hpp" + +1439687843 d:\git.repo\nana\source\paint\detail\image_png.hpp + + + + + + +1439496158 d:\git.repo\nana\source\paint\detail\image_bmp.hpp + + + +1376313789 source:d:\git.repo\nana\source\paint\image_process_selector.cpp + + +1439496158 source:d:\git.repo\nana\source\paint\pixel_buffer.cpp + + + + + + + +1423350893 source:d:\git.repo\nana\source\paint\text_renderer.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\system\dataexch.cpp + + + + + + + + + +1387007333 source:d:\git.repo\nana\source\system\platform.cpp + + + + + + + + +1365203879 source:d:\git.repo\nana\source\system\shared_wrapper.cpp + + + + + + +1342280997 source:d:\git.repo\nana\source\system\timepiece.cpp + + + + + +1386165989 source:d:\git.repo\nana\source\threads\pool.cpp + + + + + + + + + + + + + +1365203748 source:d:\git.repo\nana\source\traits.cpp + + +1439496158 source:d:\git.repo\nana\source\unicode_bidi.cpp + + +1439830958 source:d:\git.repo\nana\source\gui\widgets\tabbar.cpp + + + + + + + + diff --git a/build/codeblocks/nana.layout b/build/codeblocks/nana.layout index 92b352dc..587b86f1 100644 --- a/build/codeblocks/nana.layout +++ b/build/codeblocks/nana.layout @@ -1,24 +1,9 @@ - + - - - - - - - - - - - - - - - - + @@ -26,9 +11,9 @@ - + - + @@ -36,66 +21,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - @@ -126,29 +71,89 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj index 610054bc..7ed1c2f9 100644 --- a/build/vc2013/nana.vcxproj +++ b/build/vc2013/nana.vcxproj @@ -243,7 +243,6 @@ - @@ -277,8 +276,8 @@ - - + + @@ -383,4 +382,4 @@ - + \ No newline at end of file diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters index 6ade66c7..e58eb56b 100644 --- a/build/vc2013/nana.vcxproj.filters +++ b/build/vc2013/nana.vcxproj.filters @@ -119,7 +119,7 @@ Source Files\nana\detail\win32 - + Source Files\nana\filesystem @@ -261,9 +261,6 @@ Source Files\nana\paint\detail - - Source Files\nana\paint - Source Files\nana\paint @@ -645,7 +642,7 @@ Header Files\extrlib - + Header Files\filesystem @@ -719,4 +716,4 @@ Header Files\gui\widgets - + \ No newline at end of file diff --git a/build/vc2015/nana.sln b/build/vc2015/nana.sln index eab31ab5..6de06997 100644 --- a/build/vc2015/nana.sln +++ b/build/vc2015/nana.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{25B21068-491B-4A9F-B99F-6C27BF31BAAD}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{98091380-2EC4-44B4-82A2-F0A6393BA908}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,14 +13,14 @@ Global 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 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x64.ActiveCfg = Debug|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x64.Build.0 = Debug|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x86.ActiveCfg = Debug|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x86.Build.0 = Debug|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x64.ActiveCfg = Release|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x64.Build.0 = Release|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x86.ActiveCfg = Release|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build/vc2015/nana.vcxproj b/build/vc2015/nana.vcxproj index d4f7f5d3..9b0433bd 100644 --- a/build/vc2015/nana.vcxproj +++ b/build/vc2015/nana.vcxproj @@ -5,24 +5,24 @@ Debug Win32 - - Debug - x64 - Release Win32 + + Debug + x64 + Release x64 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD} + {98091380-2EC4-44B4-82A2-F0A6393BA908} Win32Proj nana - 8.1 + 8.1 @@ -31,12 +31,6 @@ v140 Unicode - - StaticLibrary - true - v140 - Unicode - StaticLibrary false @@ -44,6 +38,12 @@ true Unicode + + StaticLibrary + true + v140 + Unicode + StaticLibrary false @@ -54,46 +54,30 @@ - - + - + - + + + + - - ../bin/ - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ + + ../../include;$(IncludePath) + ..\bin\vc2015\ + lib$(ProjectName) - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - ../bin/ - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ - - - ../bin/ - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ - - - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - ../bin/ - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ + ../../include;$(IncludePath) + ..\bin\vc2015\ + lib$(ProjectName)d @@ -102,17 +86,11 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDebug - true - false Windows true - - $(TargetPath) - @@ -120,15 +98,14 @@ Level3 Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDebug + _DEBUG;_LIB;%(PreprocessorDefinitions) Windows true - $(TargetPath) + $(OutDir)$(TargetName)$(TargetExt) @@ -140,8 +117,6 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - true Windows @@ -149,9 +124,6 @@ true true - - $(TargetPath) - @@ -161,8 +133,7 @@ MaxSpeed true true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded + NDEBUG;_LIB;%(PreprocessorDefinitions) Windows @@ -171,7 +142,7 @@ true - $(TargetPath) + $(OutDir)$(TargetName)$(TargetExt) @@ -244,7 +215,6 @@ - @@ -252,7 +222,6 @@ - diff --git a/build/vc2015/nana.vcxproj.filters b/build/vc2015/nana.vcxproj.filters index 81495341..42482ba2 100644 --- a/build/vc2015/nana.vcxproj.filters +++ b/build/vc2015/nana.vcxproj.filters @@ -13,298 +13,289 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - {b0bd11b1-bcbb-4e05-885e-44295bc1a7bb} + + {9630500a-5aca-4625-a11b-1ba83a93895c} - - {aab16aa3-c8d4-4495-8606-1b21ae739ee5} + + {d43db913-0472-45f6-889e-b147a7b3eb7e} - - {c395f107-7102-415b-a019-54e7cf3575af} + + {4e91af62-8e45-41d5-8bb9-1deb850de937} - - {e2569be2-9e68-477d-8b59-e248595de6c7} + + {c575e702-d7d3-48d2-a465-30e51ca72f8d} - - {52ed7f8e-fa48-495e-af1f-4df013205a35} + + {e1fbd69a-2a82-419e-854a-0b5dbd0e0237} - - {87d14798-9015-4162-b9ab-72c741cff063} + + {295ba47e-9dc7-4375-82bc-443b767eb87d} - - {4f8e7d23-9fe1-4409-bb03-2bd0809e606b} + + {b0854b25-60fc-47e2-a9df-5e4f2d28065c} - - {85c9c1bb-d87b-4481-bf3c-7425f680a12d} + + {b3023f5e-2759-409d-b6e8-5ef2fe6601ae} - - {8058b530-86ec-4d72-890d-345aa30db056} + + {2ce139f3-ef8e-48b7-a82a-68003eac75da} - - {87b124cb-408d-460b-a81b-8a788bbae0d9} + + {b9f9a5a8-fd1a-4b99-b530-d8a4c45e62ec} - - {b10db2f1-0542-421a-9e1d-4357e3be5f68} + + {4b04c197-4a1e-41f9-bfa3-d82c18bcad51} - - {59f186c8-f5f8-4499-8e19-f278d4754220} + + {cd6e7f3f-fe5b-44c6-ae8d-15554f926055} - - {5acf1733-47b2-4872-a105-66c7ad15cd39} + + {60f588f2-bdb9-4b1d-9e23-40a73f327283} - - {a81fa10e-1274-44e0-92a0-434fa28f89ae} - - - {e95b4a72-643f-4416-af95-b0bbaf7f0c57} + + {53feb93f-2b86-4bf5-b2f3-f60ef1bbbf76} - - Source Files\nana\audio\detail - - - Source Files\nana\audio\detail - - - Source Files\nana\audio\detail - - - Source Files\nana\audio - - - Source Files\nana\detail\win32 - - - Source Files\nana\filesystem - - - Source Files\nana\filesystem - - - Source Files\nana\gui\detail\win32 - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\widgets\skeletons - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\paint\detail - - - Source Files\nana\paint\detail - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\system - - - Source Files\nana\system - - - Source Files\nana\system - - - Source Files\nana\system - - - Source Files\nana\threads - - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana - - - Source Files\nana - - - Source Files\nana - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui - - - Source Files\nana\gui + Source Files - Source Files\nana + Source Files - - Source Files\nana\gui\detail + + Source Files - - Source Files\nana\gui + + Source Files - - Source Files\nana\gui\widgets + + Source Files\audio\detail + + + Source Files\audio\detail + + + Source Files\audio\detail + + + Source Files\audio + + + Source Files\detail\win32 + + + Source Files\filesystem - Source Files\nana\filesystem + Source Files\filesystem + + + Source Files\filesystem + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail\win32 + + + Source Files\gui\widgets\skeletons + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets - Source Files\nana\gui\widgets + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\threads + + + Source Files\system + + + Source Files\system + + + Source Files\system + + + Source Files\paint\detail + + + Source Files\paint\detail + + + Source Files\paint + + + Source Files\paint + + + Source Files\paint + + + Source Files\paint + + + Source Files\paint \ No newline at end of file diff --git a/extrlib/readme (2).txt b/extrlib/readme (2).txt deleted file mode 100644 index 84359ae5..00000000 --- a/extrlib/readme (2).txt +++ /dev/null @@ -1 +0,0 @@ -The libpng.a is for MinGW(Not linux), and other .lib files are for VS2013 \ No newline at end of file diff --git a/extrlib/readme.txt b/extrlib/readme.txt index e5edb297..c54ee0ad 100644 --- a/extrlib/readme.txt +++ b/extrlib/readme.txt @@ -1 +1,3 @@ +The libpng.a is for MinGW(Not linux), and other .lib files are for VS2013 + You can download the precompiled external libraries at http://sourceforge.net/projects/nanapro/files/extrlib/ \ No newline at end of file diff --git a/include/nana/detail/linux_X11/platform_spec.hpp b/include/nana/detail/linux_X11/platform_spec.hpp index ae4a1830..461517f9 100644 --- a/include/nana/detail/linux_X11/platform_spec.hpp +++ b/include/nana/detail/linux_X11/platform_spec.hpp @@ -106,6 +106,8 @@ namespace detail ~drawable_impl_type(); void fgcolor(const ::nana::color&); //deprecated + unsigned get_color() const; + unsigned get_text_color() const; void set_color(const ::nana::color&); void set_text_color(const ::nana::color&); diff --git a/include/nana/detail/win32/platform_spec.hpp b/include/nana/detail/win32/platform_spec.hpp index e8db5fff..3afea077 100644 --- a/include/nana/detail/win32/platform_spec.hpp +++ b/include/nana/detail/win32/platform_spec.hpp @@ -146,6 +146,7 @@ namespace detail void fgcolor(const ::nana::color&); //deprecated unsigned get_color() const; + unsigned get_text_color() const; void set_color(const ::nana::color&); void set_text_color(const ::nana::color&); diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index ec91fe1f..857d69e7 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -161,6 +161,9 @@ namespace detail std::vector> shortkeys(core_window_t*, bool with_children); core_window_t* find_shortkey(native_window_type, unsigned long key); + + void set_safe_place(core_window_t* wd, std::function&& fn); + void call_safe_place(unsigned thread_id); private: void _m_disengage(core_window_t*, core_window_t* for_new); void _m_destroy(core_window_t*); diff --git a/include/nana/gui/element.hpp b/include/nana/gui/element.hpp index ee63ecf0..599aa87a 100644 --- a/include/nana/gui/element.hpp +++ b/include/nana/gui/element.hpp @@ -27,19 +27,35 @@ namespace nana namespace element { + namespace detail + { + class element_abstract + { + public: + using graph_reference = ::nana::paint::graphics&; + virtual ~element_abstract() = default; + }; + + class factory_abstract + { + public: + virtual ~factory_abstract() = default; + + virtual void destroy(element_abstract *); + }; + } + class element_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; - - virtual ~element_interface() = default; virtual bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) = 0; }; class crook_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; using state = checkstate; struct data @@ -47,25 +63,21 @@ namespace nana state check_state; bool radio; }; - - virtual ~crook_interface() = default; + virtual bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state, const data&) = 0; }; class border_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; - - virtual ~border_interface() = default; virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, unsigned weight) = 0; }; class arrow_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; - virtual ~arrow_interface() = default; virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, direction) = 0; }; @@ -74,10 +86,10 @@ namespace nana public: template struct factory_interface + : public detail::factory_abstract { virtual ~factory_interface(){} virtual ElementInterface* create() const = 0; - virtual void destroy(ElementInterface*) const = 0; }; template @@ -85,38 +97,39 @@ namespace nana : public factory_interface { public: - typedef factory_interface interface_type; + using interface_type = factory_interface; ElementInterface * create() const override { return (new Element); } - - void destroy(ElementInterface * p) const override - { - delete p; - } }; - void add_crook(const std::string& name, const pat::cloneable>&); - crook_interface* const * keeper_crook(const std::string& name); + void add_arrow(const std::string&, const pat::cloneable>&); + arrow_interface* const * cite_arrow(const std::string&); void add_border(const std::string&, const pat::cloneable>&); - border_interface* const * keeper_border(const std::string&); - - void add_arrow(const std::string&, const pat::cloneable>&); - arrow_interface* const * keeper_arrow(const std::string&); + border_interface* const * cite_border(const std::string&); void add_button(const std::string&, const pat::cloneable>&); - element_interface* const* keeper_button(const std::string&); + element_interface* const* cite_button(const std::string&); + + void add_x_icon(const std::string& name, const pat::cloneable>&); + element_interface* const* cite_x_icon(const std::string&); + + void add_crook(const std::string& name, const pat::cloneable>&); + crook_interface* const * cite_crook(const std::string& name); + + void add_cross(const std::string& name, const pat::cloneable>&); + element_interface* const* cite_cross(const std::string&); }; - class crook; - template - void add_crook(const std::string& name) + class arrow; + template + void add_arrow(const std::string& name) { - using factory_t = provider::factory; - provider().add_crook(name, pat::cloneable(factory_t())); + using factory_t = provider::factory; + provider().add_arrow(name, pat::cloneable(factory_t())); } class border; @@ -127,14 +140,6 @@ namespace nana provider().add_border(name, pat::cloneable(factory_t())); } - class arrow; - template - void add_arrow(const std::string& name) - { - using factory_t = provider::factory; - provider().add_arrow(name, pat::cloneable(factory_t())); - } - class button; template void add_button(const std::string& name) @@ -142,6 +147,30 @@ namespace nana using factory_t = provider::factory; provider().add_button(name, pat::cloneable(factory_t())); } + + class x_icon; + template + void add_x_icon(const std::string& name) + { + using factory_t = provider::factory; + provider().add_x_icon(name, pat::cloneable(factory_t())); + } + + class crook; + template + void add_crook(const std::string& name) + { + using factory_t = provider::factory; + provider().add_crook(name, pat::cloneable(factory_t())); + } + + class cross; + template + void add_cross(const std::string& name) + { + using factory_t = provider::factory; + provider().add_cross(name, pat::cloneable(factory_t())); + } }//end namespace element template class facade; @@ -169,9 +198,27 @@ namespace nana bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state) override; private: element::crook_interface::data data_; - element::crook_interface* const * keeper_; + element::crook_interface* const * cite_; }; //end class facade + template<> class facade + : public element::element_interface + { + public: + facade(const char* name = nullptr); + void switch_to(const char*); + + void thickness(unsigned thk); + void size(unsigned size_pixels); + public: + //Implement element_interface + bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state) override; + private: + unsigned thickness_{6}; + unsigned size_{ 14 }; + element::element_interface* const * cite_; + }; + template<> class facade : public element::element_interface @@ -185,7 +232,7 @@ namespace nana //Implement element_interface bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) override; private: - element::border_interface* const * keeper_; + element::border_interface* const * cite_; };//end class facade template<> @@ -207,7 +254,7 @@ namespace nana //Implement element_interface bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) override; private: - element::arrow_interface* const * keeper_; + element::arrow_interface* const * cite_; ::nana::direction dir_{::nana::direction::north}; };//end class facade @@ -222,9 +269,22 @@ namespace nana //Implement element_interface bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state) override; private: - element::element_interface* const * keeper_; + element::element_interface* const * cite_; };//end class facade + template<> + class facade + : public element::element_interface + { + public: + facade(const char* name = nullptr); + void switch_to(const char*); + public: + //Implement element_interface + bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state) override; + private: + element::element_interface* const * cite_; + };//end class facade namespace element { diff --git a/include/nana/gui/place.hpp b/include/nana/gui/place.hpp index a7e7e0ea..2e3676de 100644 --- a/include/nana/gui/place.hpp +++ b/include/nana/gui/place.hpp @@ -109,9 +109,11 @@ namespace nana window window_handle() const; void div(const char* s); ///< Divides the attached widget into fields. + void modify(const char* field_name, const char* div_text); ///< Modifies a specified field. + field_reference field(const char* name);///< Returns a field with the specified name. - void field_visible(const char* filed_name, bool visible); ///< + place& dock(const std::string& dockname, const std::string& factory_name, Args&& ... args) + { + return dock(dockname, factory_name, std::bind([](window parent, Args & ... args) + { + return std::unique_ptr(new Panel(parent, std::forward(args)...)); + }, std::placeholders::_1, args...)); + } + + place& dock(const std::string& dockname, std::string factory_name, std::function(window)> factory); + place& dock_create(const std::string& factory); private: implement * impl_; }; diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 167fd8d8..6de9ba97 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -29,6 +29,13 @@ namespace nana /// Traits for widget classes template struct widget_traits + { + using event_type = typename Widget::event_type; + using scheme_type = typename Widget::scheme_type; + }; + + template<> + struct widget_traits { using event_type = ::nana::general_events; using scheme_type = ::nana::widget_colors; @@ -191,7 +198,7 @@ namespace API } point window_position(window); - void move_window(window, int x, int y); + void move_window(window, const point&); void move_window(window wd, const rectangle&); void bring_top(window, bool activated); @@ -298,6 +305,8 @@ namespace API bool ignore_mouse_focus(window, bool ignore); ///< Enables/disables the mouse focus, it returns the previous state bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled + + void at_safe_place(window, std::function); }//end namespace API }//end namespace nana diff --git a/include/nana/gui/widgets/combox.hpp b/include/nana/gui/widgets/combox.hpp index beb1cece..17bb7cfe 100644 --- a/include/nana/gui/widgets/combox.hpp +++ b/include/nana/gui/widgets/combox.hpp @@ -229,7 +229,8 @@ namespace nana nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override; }; - namespace dev + /* + namespace dev //deprecated { template<> struct widget_traits @@ -238,5 +239,6 @@ namespace nana using scheme_type = ::nana::widgets::skeletons::text_editor_scheme; }; } + */ } #endif diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 140d6dd2..652171a4 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -664,14 +664,16 @@ By \a clicking on one header the list get \a reordered, first up, and then down void _m_erase_key(nana::detail::key_interface*); }; + /* namespace dev { template<> - struct widget_traits + struct widget_traits //deprecated { using event_type = drawerbase::listbox::listbox_events; using scheme_type = drawerbase::listbox::scheme; }; } + */ }//end namespace nana #endif diff --git a/include/nana/gui/widgets/scroll.hpp b/include/nana/gui/widgets/scroll.hpp index 54a04de0..917a5da5 100644 --- a/include/nana/gui/widgets/scroll.hpp +++ b/include/nana/gui/widgets/scroll.hpp @@ -14,7 +14,6 @@ #define NANA_GUI_WIDGET_SCROLL_HPP #include "widget.hpp" -#include #include namespace nana @@ -444,7 +443,7 @@ namespace nana /// @return true if the vlaue is changed. bool make_page_scroll(bool forward) { - return this->make_step(forward, range() - 1); + return this->make_step(forward, static_cast(range() - 1)); } };//end class scroll }//end namespace nana diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp index 22b780e4..09e64faf 100644 --- a/include/nana/gui/widgets/spinbox.hpp +++ b/include/nana/gui/widgets/spinbox.hpp @@ -110,15 +110,17 @@ namespace nana void _m_caption(::nana::string&&); }; //end class spinbox + /* namespace dev { template<> - struct widget_traits + struct widget_traits //deprecated { using event_type = drawerbase::spinbox::spinbox_events; using scheme_type = ::nana::widgets::skeletons::text_editor_scheme; }; } + */ }//end namespace nana #endif //NANA_GUI_WIDGET_SPINBOX_HPP diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 1160c724..3f412f9b 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -14,7 +14,6 @@ #ifndef NANA_GUI_WIDGET_TABBAR_HPP #define NANA_GUI_WIDGET_TABBAR_HPP #include "widget.hpp" -#include "../../paint/gadget.hpp" #include #include @@ -30,7 +29,7 @@ namespace nana T & value; arg_tabbar(tabbar& wdg, T& v) - : widget{ wdg }, value{ v } + : widget(wdg), value{ v } {} }; @@ -337,15 +336,19 @@ namespace nana namespace nana -{ - namespace ng - { +{ namespace drawerbase { namespace tabbar_lite { class model; + struct events + : public general_events + { + basic_event selected; + }; + class driver : public drawer_trigger { @@ -353,7 +356,7 @@ namespace nana driver(); ~driver(); - model* get_model(); + model* get_model() const throw(); private: //Overrides drawer_trigger's method void attached(widget_reference, graph_reference) override; @@ -367,18 +370,39 @@ namespace nana } }//end namespace drawerbase - class tabbar_lite - : public widget_object + class tabbar_lite + : public widget_object + { + public: + tabbar_lite() = default; + tabbar_lite(window, bool visible = true, const::nana::rectangle& = {}); + + public: //capacity + std::size_t length() const; + + public: //modifiers + void attach(std::size_t pos, window); + window attach(std::size_t pos) const; + + void push_back(std::string text, ::nana::any par = {}); + void push_front(std::string text, ::nana::any par = {}); + + std::size_t selected() const; + void erase(std::size_t pos, bool close_attached = true); + }; + + /* + namespace dev + { + /// Traits for widget classes + template<> + struct widget_traits //deprecated { - public: - tabbar_lite() = default; - tabbar_lite(window, bool visible = true, const::nana::rectangle& = {}); - - - void push_back(std::string text, ::nana::any par = {}); - void push_front(std::string text, ::nana::any par = {}); + using event_type = drawerbase::tabbar_lite::events; + using scheme_type = ::nana::widget_colors; }; } + */ } #endif diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp index 85bac2a6..4360cd74 100644 --- a/include/nana/gui/widgets/textbox.hpp +++ b/include/nana/gui/widgets/textbox.hpp @@ -195,15 +195,17 @@ namespace nana void _m_typeface(const paint::font&) override; }; + /* namespace dev { /// Traits for widget classes template<> - struct widget_traits + struct widget_traits //deprecated { using event_type = drawerbase::textbox::textbox_events; using scheme_type = ::nana::widgets::skeletons::text_editor_scheme; }; } + */ }//end namespace nana #endif diff --git a/include/nana/gui/widgets/treebox.hpp b/include/nana/gui/widgets/treebox.hpp index db15a6cd..5e317781 100644 --- a/include/nana/gui/widgets/treebox.hpp +++ b/include/nana/gui/widgets/treebox.hpp @@ -19,7 +19,6 @@ #define NANA_GUI_WIDGETS_TREEBOX_HPP #include "widget.hpp" #include "detail/compset.hpp" -#include #include "detail/tree_cont.hpp" #include #include diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 0288388e..2da63cda 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -134,7 +134,8 @@ namespace nana protected: typedef DrawerTrigger drawer_trigger_t; public: - using scheme_type = Scheme; + using scheme_type = Scheme; + using event_type = Events; widget_object() : events_{ std::make_shared() }, @@ -147,7 +148,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } @@ -228,6 +229,7 @@ namespace nana typedef DrawerTrigger drawer_trigger_t; public: using scheme_type = Scheme; + using event_type = Events; widget_object() : events_{ std::make_shared() }, scheme_{ API::dev::make_scheme() } @@ -239,7 +241,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } @@ -297,6 +299,7 @@ namespace nana typedef DrawerTrigger drawer_trigger_t; public: using scheme_type = Scheme; + using event_type = Events; widget_object() { @@ -322,7 +325,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } @@ -451,6 +454,7 @@ namespace nana typedef int drawer_trigger_t; public: using scheme_type = Scheme; + using event_type = Events; widget_object() : events_{ std::make_shared() }, scheme_{ API::dev::make_scheme() } @@ -462,7 +466,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } diff --git a/include/nana/paint/gadget.hpp b/include/nana/paint/gadget.hpp deleted file mode 100644 index d64c9293..00000000 --- a/include/nana/paint/gadget.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Graphics Gadget Implementation - * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - * @file: nana/paint/gadget.hpp - */ - -#ifndef NANA_PAINT_GADGET_HPP -#define NANA_PAINT_GADGET_HPP -#include "graphics.hpp" -#include "image.hpp" -#include - -namespace nana -{ -namespace paint -{ -namespace gadget -{ - void close_16_pixels(::nana::paint::graphics&, int x, int y, unsigned style, const color&); - void cross(::nana::paint::graphics&, int x, int y, unsigned size, unsigned thickness, const nana::color&); - -}//end namespace gadget - -}//end namespace paint -}//end namespace nana - -#endif diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index ad2c8a6c..a194aa7e 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -136,8 +136,11 @@ namespace nana /// @param file_utf8 A UTF-8 string to a filename void save_as_file(const char* file_utf8) const throw(); - void set_color(const ::nana::color&); - void set_text_color(const ::nana::color&); + void set_color(const ::nana::color&); //deprecated, graphics::palette() instead + void set_text_color(const ::nana::color&); //deprecated, graphics::palette() instead + + ::nana::color palette(bool for_text) const; + graphics& palette(bool for_text, const ::nana::color&); unsigned bidi_string(const nana::point&, const char_t *, std::size_t len); unsigned bidi_string(const point& pos, const char*, std::size_t len); diff --git a/include/nana/pat/cloneable.hpp b/include/nana/pat/cloneable.hpp index 281c36f2..16a9dfcd 100644 --- a/include/nana/pat/cloneable.hpp +++ b/include/nana/pat/cloneable.hpp @@ -21,62 +21,50 @@ namespace nana{ namespace pat{ namespace detail { - template class cloneable_interface { public: - typedef T interface_t; - typedef cloneable_interface cloneable_t; virtual ~cloneable_interface() = default; - virtual interface_t& refer() = 0; - virtual const interface_t& refer() const = 0; - virtual cloneable_t* clone() const = 0; + virtual void * get() = 0; + virtual cloneable_interface* clone() const = 0; virtual void self_delete() const = 0; }; + struct cloneable_interface_deleter + { + void operator()(cloneable_interface * p) + { + if (p) + p->self_delete(); + } + }; - template + template class cloneable_wrapper - : public cloneable_interface + : public cloneable_interface { public: - typedef T value_t; - typedef typename cloneable_interface::interface_t interface_t; + using value_type = T; - cloneable_wrapper() + cloneable_wrapper() = default; + + cloneable_wrapper(const value_type& obj) + :value_obj_(obj) {} - cloneable_wrapper(const value_t& obj) - :object_(obj) + cloneable_wrapper(value_type&& rv) + :value_obj_(std::move(rv)) {} - - cloneable_wrapper(value_t&& rv) - :object_(std::move(rv)) - {} - - template - cloneable_wrapper(const U& u) - : object_(u) - {} - - template - cloneable_wrapper(U& u) - :object_(u) - {} - - virtual interface_t& refer() override + private: + //Implement cloneable_interface + virtual void* get() override { - return object_; + return &value_obj_; } - virtual const interface_t& refer() const override + virtual cloneable_interface* clone() const override { - return object_; - } - - virtual cloneable_interface* clone() const override - { - return (new cloneable_wrapper(object_)); + return (new cloneable_wrapper{ value_obj_ }); } virtual void self_delete() const override @@ -84,28 +72,20 @@ namespace nana{ namespace pat{ (delete this); } private: - value_t object_; + value_type value_obj_; }; - }//end namespace detail template class cloneable { using base_t = Base; - using interface_t = detail::cloneable_interface < base_t > ; + using cloneable_interface = detail::cloneable_interface; using const_base_ptr = typename std::conditional::type; using const_base_ref = typename std::conditional::type; - struct deleter - { - void operator()(interface_t * p) - { - if(p) - p->self_delete(); - } - }; + template friend class cloneable; struct inner_bool { @@ -125,16 +105,16 @@ namespace nana{ namespace pat{ template::type* = nullptr> cloneable(T&& t) - : cwrapper_(new detail::cloneable_wrapper::type>::type, base_t>(std::forward(t)), deleter()), - fast_ptr_(&(cwrapper_->refer())) + : cwrapper_(new detail::cloneable_wrapper::type>::type>(std::forward(t)), detail::cloneable_interface_deleter()), + fast_ptr_(reinterpret_cast::type>::type*>(cwrapper_->get())) {} cloneable(const cloneable& r) { if(r.cwrapper_) { - cwrapper_ = std::shared_ptr(r.cwrapper_->clone(), deleter()); - fast_ptr_ = &(cwrapper_->refer()); + cwrapper_ = std::move(std::shared_ptr(r.cwrapper_->clone(), detail::cloneable_interface_deleter{})); + fast_ptr_ = reinterpret_cast(cwrapper_->get()); } } @@ -145,12 +125,27 @@ namespace nana{ namespace pat{ r.fast_ptr_ = nullptr; } + template::value>::type* = nullptr> + cloneable(const cloneable& other) + { + if (other) + { + char* value_ptr = reinterpret_cast(other.cwrapper_->get()); + char* base_ptr = reinterpret_cast(other.fast_ptr_); + + auto ptr_diff = std::distance(base_ptr, value_ptr); + + cwrapper_.reset(other.cwrapper_->clone(), detail::cloneable_interface_deleter{}); + fast_ptr_ = reinterpret_cast(reinterpret_cast(cwrapper_->get()) - ptr_diff); + } + } + cloneable & operator=(const cloneable& r) { if((this != &r) && r.cwrapper_) { - cwrapper_ = std::shared_ptr(r.cwrapper_->clone(), deleter()); - fast_ptr_ = &(cwrapper_->refer()); + cwrapper_ = std::shared_ptr(r.cwrapper_->clone(), detail::cloneable_interface_deleter()); + fast_ptr_ = reinterpret_cast(cwrapper_->get()); } return *this; } @@ -159,10 +154,8 @@ namespace nana{ namespace pat{ { if(this != &r) { - cwrapper_ = r.cwrapper_; + cwrapper_ = std::move(r.cwrapper_); fast_ptr_ = r.fast_ptr_; - - r.cwrapper_.reset(); r.fast_ptr_ = nullptr; } return *this; @@ -204,12 +197,12 @@ namespace nana{ namespace pat{ return (fast_ptr_ ? &inner_bool::true_stand : nullptr); } private: - std::shared_ptr cwrapper_; + std::shared_ptr cwrapper_; base_t * fast_ptr_{nullptr}; }; template - using mutable_cloneable = cloneable < T, true > ; + using mutable_cloneable = cloneable; }//end namespace pat }//end namespace nana diff --git a/source/detail/linux_X11/platform_spec.cpp b/source/detail/linux_X11/platform_spec.cpp index 7501158d..8d4ff735 100644 --- a/source/detail/linux_X11/platform_spec.cpp +++ b/source/detail/linux_X11/platform_spec.cpp @@ -302,14 +302,24 @@ namespace detail #endif } + unsigned drawable_impl_type::get_color() const + { + return color_; + } + + unsigned drawable_impl_type::get_text_color() const + { + return text_color_; + } + void drawable_impl_type::set_color(const ::nana::color& clr) { - color_ = clr.px_color().value; + color_ = (clr.px_color().value & 0xFFFFFF); } void drawable_impl_type::set_text_color(const ::nana::color& clr) { - text_color_ = clr.px_color().value; + text_color_ = (clr.px_color().value & 0xFFFFFF); update_text_color(); } diff --git a/source/detail/win32/platform_spec.cpp b/source/detail/win32/platform_spec.cpp index cb064545..767b843f 100644 --- a/source/detail/win32/platform_spec.cpp +++ b/source/detail/win32/platform_spec.cpp @@ -63,14 +63,19 @@ namespace detail return color_; } + unsigned drawable_impl_type::get_text_color() const + { + return text_color_; + } + void drawable_impl_type::set_color(const ::nana::color& clr) { - color_ = clr.px_color().value; + color_ = (clr.px_color().value & 0xFFFFFF); } void drawable_impl_type::set_text_color(const ::nana::color& clr) { - auto rgb = clr.px_color().value; + auto rgb = (clr.px_color().value & 0xFFFFFF); if (text_color_ != rgb) { ::SetTextColor(context, NANA_RGB(rgb)); diff --git a/source/gui/detail/linux_X11/bedrock.cpp b/source/gui/detail/linux_X11/bedrock.cpp index 3cba6d2b..1260067b 100644 --- a/source/gui/detail/linux_X11/bedrock.cpp +++ b/source/gui/detail/linux_X11/bedrock.cpp @@ -1207,8 +1207,11 @@ namespace detail if(context) context->event_window = pre_event_window; } + auto thread_id = ::nana::system::this_thread_id() + brock.wd_manager.call_safe_place(thread_id); + if(msgwnd) - brock.wd_manager.remove_trash_handle(::nana::system::this_thread_id()); + brock.wd_manager.remove_trash_handle(thread_id); } } diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index d706b43d..6dd9a583 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -542,32 +542,6 @@ namespace nana{ return false; } - /* - bool native_interface::window_icon(native_window_type wd, const paint::image& big_icon, const paint::image& small_icon) //deprecated - { -#if defined(NANA_WINDOWS) - HICON h_big_icon = paint::image_accessor::icon(big_icon); - HICON h_small_icon = paint::image_accessor::icon(small_icon); - if (h_big_icon || h_small_icon) - { - nana::detail::platform_spec::instance().keep_window_icon(wd, (!big_icon.empty() ? big_icon : small_icon)); - if (h_big_icon) { - ::SendMessage(reinterpret_cast(wd), WM_SETICON, ICON_BIG, reinterpret_cast(h_big_icon)); - } - if (h_small_icon) { - ::SendMessage(reinterpret_cast(wd), WM_SETICON, ICON_SMALL, reinterpret_cast(h_small_icon)); - } - return true; - } -#elif defined(NANA_X11) - return window_icon(wd, big_icon); -#endif - return false; - } - */ - - - void native_interface::activate_owner(native_window_type wd) { #if defined(NANA_WINDOWS) diff --git a/source/gui/detail/win32/bedrock.cpp b/source/gui/detail/win32/bedrock.cpp index d8ac543c..e1095345 100644 --- a/source/gui/detail/win32/bedrock.cpp +++ b/source/gui/detail/win32/bedrock.cpp @@ -413,6 +413,7 @@ namespace detail ::DispatchMessage(&msg); } + wd_manager.call_safe_place(tid); wd_manager.remove_trash_handle(tid); if (msg.message == WM_DESTROY && msg.hwnd == native_handle) break; @@ -432,6 +433,7 @@ namespace detail ::DispatchMessage(&msg); } + wd_manager.call_safe_place(tid); wd_manager.remove_trash_handle(tid); }//end while diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index e9581fd1..e272801b 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -44,6 +44,8 @@ namespace detail handle_manager wd_register; paint::image default_icon_big; paint::image default_icon_small; + + std::map>> safe_place; }; //end struct wdm_private_impl @@ -1192,6 +1194,36 @@ namespace detail return nullptr; } + void window_manager::set_safe_place(core_window_t* wd, std::function&& fn) + { + if (fn) + { + std::lock_guard lock(mutex_); + if (!available(wd)) + return; + + impl_->safe_place[wd].emplace_back(std::move(fn)); + } + } + + void window_manager::call_safe_place(unsigned thread_id) + { + std::lock_guard lock(mutex_); + + for (auto i = impl_->safe_place.begin(); i != impl_->safe_place.end();) + { + if (i->first->thread_id == thread_id) + { + for (auto & fn : i->second) + fn(); + + i = impl_->safe_place.erase(i); + } + else + ++i; + } + } + bool check_tree(basic_window* wd, basic_window* const cond) { if (wd == cond) return true; diff --git a/source/gui/dragger.cpp b/source/gui/dragger.cpp index dac2c6c8..5bb82baf 100644 --- a/source/gui/dragger.cpp +++ b/source/gui/dragger.cpp @@ -164,7 +164,7 @@ namespace nana if (!t.restrict_area.empty()) _m_check_restrict_area(wdps, API::window_size(t.wd), t.restrict_area); - API::move_window(t.wd, wdps.x, wdps.y); + API::move_window(t.wd, wdps); } } } diff --git a/source/gui/element.cpp b/source/gui/element.cpp index 1852a554..4271a4d2 100644 --- a/source/gui/element.cpp +++ b/source/gui/element.cpp @@ -28,6 +28,14 @@ namespace nana //Element definitions namespace element { + namespace detail + { + void factory_abstract::destroy(element_abstract* ptr) + { + delete ptr; + } + } + class crook : public crook_interface { @@ -141,7 +149,7 @@ namespace nana } else { - ::nana::color highlighted(static_cast(0x5eb6f7)); + ::nana::color highlighted(0x5e, 0xb6, 0xf7); auto bld_bgcolor = bgcolor; auto bld_fgcolor = fgcolor; switch(es) @@ -156,7 +164,7 @@ namespace nana bld_fgcolor = fgcolor.blend(highlighted, 0.4); break; case element_state::disabled: - bld_bgcolor = bld_fgcolor.from_rgb(0xb2, 0xb7, 0xbc); + bld_bgcolor = bld_fgcolor = nana::color(0xb2, 0xb7, 0xbc); break; default: //Leave things as they are @@ -529,14 +537,71 @@ namespace nana return true; } };//end class annex_button + + class x_icon + : public element_interface + { + bool draw(graph_reference graph, const ::nana::color&, const ::nana::color& fgcolor, const rectangle& r, element_state estate) override + { + auto clr = fgcolor; + + switch (estate) + { + case element_state::hovered: + case element_state::pressed: + clr = clr.blend(colors::black, 0.8); + break; + case element_state::disabled: + clr = colors::dark_gray; + default: + break; + } + + graph.set_color(clr); + + const int x = r.x + 4; + const int y = r.y + 4; + + point p1{ x, y }, p2{ x + 7, y + 7 }; + + graph.line(p1, p2); + + ++p1.x; + --p2.y; + graph.line(p1, p2); + + p1.x = x; + ++p1.y; + p2.x = x + 6; + p2.y = y + 7; + graph.line(p1, p2); + + p1.x += 7; + p1.y = y; + p2.x = x; + graph.line(p1, p2); + + p1.x = x + 6; + p2.y = y + 6; + graph.line(p1, p2); + + ++p1.x; + ++p1.y; + ++p2.x; + ++p2.y; + graph.line(p1, p2); + + return true; + } + }; }//end namespace element template class element_object : nana::noncopyable, nana::nonmovable { - typedef ElementInterface element_t; - typedef pat::cloneable> factory_interface; + using element_type = ElementInterface; + using factory_interface = pat::cloneable; public: ~element_object() @@ -551,7 +616,7 @@ namespace nana auto keep_e = element_ptr_; factory_ = rhs; - element_ptr_ = factory_->create(); + element_ptr_ = static_cast(static_cast&>(*factory_).create()); if(nullptr == factory_ || nullptr == element_ptr_) { @@ -567,14 +632,14 @@ namespace nana spare_.emplace_back(keep_e, keep_f); } - element_t * const * keeper() const + element_type * const * cite() const { return &element_ptr_; } private: factory_interface factory_; //Keep the factory for destroying the element - element_t * element_ptr_{nullptr}; - std::vector> spare_; + element_type * element_ptr_{nullptr}; + std::vector> spare_; }; class element_manager @@ -613,6 +678,8 @@ namespace nana element::add_arrow("hollow_triangle"); element::add_button(""); //"annex" in default + + element::add_x_icon(""); } return obj; } @@ -624,7 +691,17 @@ namespace nana element::crook_interface * const * crook(const std::string& name) const { - return _m_get(name, crook_).keeper(); + return _m_get(name, crook_).cite(); + } + + void cross(const std::string& name, const pat::cloneable>& factory) + { + _m_add(name, cross_, factory); + } + + element::element_interface* const * cross(const std::string& name) const + { + return _m_get(name, cross_).cite(); } void border(const std::string& name, const pat::cloneable>& factory) @@ -634,7 +711,7 @@ namespace nana element::border_interface * const * border(const std::string& name) const { - return _m_get(name, border_).keeper(); + return _m_get(name, border_).cite(); } void arrow(const std::string& name, const pat::cloneable>& factory) @@ -644,7 +721,7 @@ namespace nana element::arrow_interface * const * arrow(const std::string& name) const { - return _m_get((name.empty() ? "arrowhead" : name), arrow_).keeper(); + return _m_get((name.empty() ? "arrowhead" : name), arrow_).cite(); } void button(const std::string& name, const pat::cloneable>& factory) @@ -654,7 +731,17 @@ namespace nana element::element_interface * const * button(const std::string& name) const { - return _m_get((name.empty() ? "annex" : name), button_).keeper(); + return _m_get((name.empty() ? "annex" : name), button_).cite(); + } + + void x_icon(const std::string& name, const pat::cloneable>& factory) + { + _m_add(name, x_icon_, factory); + } + + element::element_interface * const * x_icon(const std::string& name) const + { + return _m_get(name, x_icon_).cite(); } private: using lock_guard = std::lock_guard; @@ -689,9 +776,11 @@ namespace nana private: mutable std::recursive_mutex mutex_; item crook_; + item cross_; item border_; item arrow_; item button_; + item x_icon_; }; namespace element @@ -702,17 +791,27 @@ namespace nana element_manager::instance().crook(name, factory); } - crook_interface* const * provider::keeper_crook(const std::string& name) + crook_interface* const * provider::cite_crook(const std::string& name) { return element_manager::instance().crook(name); } + void provider::add_cross(const std::string& name, const pat::cloneable>& factory) + { + element_manager::instance().cross(name, factory); + } + + element_interface* const* provider::cite_cross(const std::string& name) + { + return element_manager::instance().cross(name); + } + void provider::add_border(const std::string& name, const pat::cloneable>& factory) { element_manager::instance().border(name, factory); } - border_interface* const * provider::keeper_border(const std::string& name) + border_interface* const * provider::cite_border(const std::string& name) { return element_manager::instance().border(name); } @@ -722,7 +821,7 @@ namespace nana element_manager::instance().arrow(name, factory); } - arrow_interface* const * provider::keeper_arrow(const std::string& name) + arrow_interface* const * provider::cite_arrow(const std::string& name) { return element_manager::instance().arrow(name); } @@ -732,16 +831,26 @@ namespace nana element_manager::instance().button(name, factory); } - element_interface* const* provider::keeper_button(const std::string& name) + element_interface* const* provider::cite_button(const std::string& name) { return element_manager::instance().button(name); } + + void provider::add_x_icon(const std::string& name, const pat::cloneable>& factory) + { + element_manager::instance().x_icon(name, factory); + } + + element_interface* const* provider::cite_x_icon(const std::string& name) + { + return element_manager::instance().x_icon(name); + } }//end namespace element //facades //template<> class facade facade::facade(const char* name) - : keeper_(element::provider().keeper_crook(name ? name : "")) + : cite_(element::provider().cite_crook(name ? name : "")) { data_.check_state = state::unchecked; data_.radio = false; @@ -777,40 +886,120 @@ namespace nana void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_crook(name ? name : ""); + cite_ = element::provider().cite_crook(name ? name : ""); } bool facade::draw(graph_reference graph, const ::nana::color& bgcol, const ::nana::color& fgcol, const nana::rectangle& r, element_state es) { - return (*keeper_)->draw(graph, bgcol, fgcol, r, es, data_); + return (*cite_)->draw(graph, bgcol, fgcol, r, es, data_); } //end class facade + //class facade + facade::facade(const char* name) + : cite_(element::provider().cite_cross(name ? name : "")) + { + + } + + void facade::switch_to(const char* name) + { + cite_ = element::provider().cite_cross(name ? name : ""); + } + + void facade::thickness(unsigned thk) + { + thickness_ = thk; + } + + void facade::size(unsigned size_px) + { + size_ = size_px; + } + + //Implement element_interface + bool facade::draw(graph_reference graph, const ::nana::color&, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state) + { + if (thickness_ + 2 <= size_) + { + int gap = (static_cast(size_) - static_cast(thickness_)) / 2; + + nana::point ps[12]; + ps[0].x = r.x + gap; + ps[1].x = ps[0].x + static_cast(thickness_) - 1; + ps[1].y = ps[0].y = r.y; + + ps[2].x = ps[1].x; + ps[2].y = r.y + gap; + + ps[3].x = ps[2].x + gap; + ps[3].y = ps[2].y; + + ps[4].x = ps[3].x; + ps[4].y = ps[3].y + static_cast(thickness_)-1; + + ps[5].x = ps[1].x; + ps[5].y = ps[4].y; + + ps[6].x = ps[5].x; + ps[6].y = ps[5].y + gap; + + ps[7].x = r.x + gap; + ps[7].y = ps[6].y; + + ps[8].x = ps[7].x; + ps[8].y = ps[4].y; + + ps[9].x = r.x; + ps[9].y = ps[4].y; + + ps[10].x = r.x; + ps[10].y = r.y + gap; + + ps[11].x = r.x + gap; + ps[11].y = r.y + gap; + + graph.set_color(fgcolor.blend(colors::black, true)); + + for (int i = 0; i < 11; ++i) + graph.line(ps[i], ps[i + 1]); + graph.line(ps[11], ps[0]); + + graph.set_color(fgcolor); + + unsigned thk_minus_2 = thickness_ - 2; + graph.rectangle(rectangle{ ps[10].x + 1, ps[10].y + 1, (gap << 1) + thk_minus_2, thk_minus_2 }, true); + graph.rectangle(rectangle{ ps[0].x + 1, ps[0].y + 1, thk_minus_2, (gap << 1) + thk_minus_2 }, true); + } + return true; + } + //end class facade + //class facade facade::facade(const char* name) - : keeper_(element::provider().keeper_border(name ? name : "")) + : cite_(element::provider().cite_border(name ? name : "")) {} void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_border(name ? name : ""); + cite_ = element::provider().cite_border(name ? name : ""); } bool facade::draw(graph_reference graph, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state es) { - return (*keeper_)->draw(graph, bgcolor, fgcolor, r, es, 2); + return (*cite_)->draw(graph, bgcolor, fgcolor, r, es, 2); } //end class facade //class facade facade::facade(const char* name) - : keeper_(element::provider().keeper_arrow(name ? name : "")) + : cite_(element::provider().cite_arrow(name ? name : "")) { } void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_arrow(name ? name : ""); + cite_ = element::provider().cite_arrow(name ? name : ""); } void facade::direction(::nana::direction dir) @@ -822,42 +1011,62 @@ namespace nana bool facade::draw(graph_reference graph, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state estate) { graph.set_color(fgcolor); - return (*keeper_)->draw(graph, bgcolor, fgcolor, r, estate, dir_); + return (*cite_)->draw(graph, bgcolor, fgcolor, r, estate, dir_); } //end class facade //class facade:: facade::facade(const char* name) - : keeper_(element::provider().keeper_button(name ? name : "")) + : cite_(element::provider().cite_button(name ? name : "")) {} void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_button(name ? name : ""); + cite_ = element::provider().cite_button(name ? name : ""); } //Implement element_interface bool facade::draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate) { - return (*keeper_)->draw(graph, bgcolor, fgcolor, r, estate); + return (*cite_)->draw(graph, bgcolor, fgcolor, r, estate); } //end class facade + + //class facade + facade::facade(const char* name) + : cite_(element::provider().cite_x_icon(name ? name : "")) + {} + + void facade::switch_to(const char* name) + { + cite_ = element::provider().cite_x_icon(name ? name : ""); + } + + //Implement element_interface + bool facade::draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate) + { + return (*cite_)->draw(graph, bgcolor, fgcolor, r, estate); + } + //end class facade + namespace element { + using brock = ::nana::detail::bedrock; + void set_bground(const char* name, const pat::cloneable& obj) { - detail::bedrock::instance().get_element_store().bground(name, obj); + brock::instance().get_element_store().bground(name, obj); } void set_bground(const char* name, pat::cloneable && obj) { - detail::bedrock::instance().get_element_store().bground(name, std::move(obj)); + brock::instance().get_element_store().bground(name, std::move(obj)); } //class cite cite_bground::cite_bground(const char* name) - : ref_ptr_(detail::bedrock::instance().get_element_store().bground(name)) + : ref_ptr_(brock::instance().get_element_store().bground(name)) { } @@ -871,7 +1080,7 @@ namespace nana void cite_bground::set(const char* name) { holder_.reset(); - ref_ptr_ = detail::bedrock::instance().get_element_store().bground(name); + ref_ptr_ = brock::instance().get_element_store().bground(name); } bool cite_bground::draw(graph_reference dst, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const nana::rectangle& r, element_state state) diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index c514f124..44addaa6 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -959,7 +959,7 @@ namespace nana int inputbox::date::month() const { if (!impl_->wdg_month.empty()) - return impl_->wdg_month.option() + 1; + return static_cast(impl_->wdg_month.option()) + 1; return impl_->month; } @@ -1028,7 +1028,7 @@ namespace nana impl->wdg_day.events().destroy.connect_unignorable([impl] { impl->day = impl->wdg_day.to_int(); - impl->month = impl->wdg_month.option() + 1; + impl->month = static_cast(impl->wdg_month.option()) + 1; }); impl->wdg_year.events().destroy.connect_unignorable([impl] @@ -1040,7 +1040,7 @@ namespace nana { auto month = impl->wdg_month.option() + 1; auto year = impl->wdg_year.to_int(); - int days = ::nana::date::month_days(year, month); + int days = ::nana::date::month_days(year, static_cast(month)); auto day = impl->wdg_day.to_int(); impl->wdg_day.range(1, days, 1); //It resets the current value of wdg_day diff --git a/source/gui/place.cpp b/source/gui/place.cpp index f57df5e5..8654f3aa 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1,4 +1,4 @@ -/** +/* * An Implementation of Place for Layout * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) @@ -8,333 +8,37 @@ * http://www.boost.org/LICENSE_1_0.txt) * * @file: nana/gui/place.cpp + * @contributors: qPCR4vir */ -#include + #include #include -#include -#include +#include +#include #include #include #include +#include #include +#include #include -#include -#include +#include //numeric_limits +#include //std::abs +#include //std::memset + +#include "place_parts.hpp" namespace nana { namespace place_parts { + //check the name void check_field_name(const char* name) { - //check the name if (*name && (*name != '_' && !(('a' <= *name && *name <= 'z') || ('A' <= *name && *name <= 'Z')))) - throw std::invalid_argument("place.field: bad field name"); + throw std::invalid_argument("nana.place: bad field name"); } - - class splitter_interface - { - public: - virtual ~splitter_interface(){} - }; - - class splitter_dtrigger - : public drawer_trigger - { - }; - - template - class splitter - : public widget_object ::type, splitter_dtrigger>, - public splitter_interface - { - }; - - //number_t is used for storing a number type variable - //such as integer, real and percent. Essentially, percent is a typo of real. - class number_t - { - public: - enum class kind{ none, integer, real, percent }; - - number_t() - : kind_(kind::none) - { - value_.integer = 0; - } - - void reset() - { - kind_ = kind::none; - value_.integer = 0; - } - - bool is_negative() const - { - switch (kind_) - { - case kind::integer: - return (value_.integer < 0); - case kind::real: - case kind::percent: - return (value_.real < 0); - default: - break; - } - return false; - } - - bool is_none() const - { - return (kind::none == kind_); - } - - bool is_not_none() const - { - return (kind::none != kind_); - } - - kind kind_of() const - { - return kind_; - } - - double get_value(int ref_percent) const - { - switch (kind_) - { - case kind::integer: - return value_.integer; - case kind::real: - return value_.real; - case kind::percent: - return value_.real * ref_percent; - default: - break; - } - return 0; - } - - int integer() const - { - if (kind::integer == kind_) - return value_.integer; - return static_cast(value_.real); - } - - double real() const - { - if (kind::integer == kind_) - return value_.integer; - return value_.real; - } - - void assign(int i) - { - kind_ = kind::integer; - value_.integer = i; - } - - void assign(double d) - { - kind_ = kind::real; - value_.real = d; - } - - void assign_percent(double d) - { - kind_ = kind::percent; - value_.real = d / 100; - } - private: - kind kind_; - union valueset - { - int integer; - double real; - }value_; - };//end class number_t - - class margin - { - public: - margin& operator=(margin&& rhs) - { - if (this != &rhs) - { - all_edges_ = rhs.all_edges_; - margins_ = std::move(rhs.margins_); - } - return *this; - } - - void clear() - { - all_edges_ = true; - margins_.clear(); - } - - void push(const number_t& v) - { - margins_.emplace_back(v); - } - - void set_value(const number_t& v) - { - clear(); - margins_.emplace_back(v); - } - - void set_array(const std::vector& v) - { - all_edges_ = false; - margins_ = v; - } - - nana::rectangle area(const ::nana::rectangle& field_area) const - { - if (margins_.empty()) - return field_area; - - auto r = field_area; - if (all_edges_) - { - auto px = static_cast(margins_.back().get_value(static_cast(r.width))); - const auto dbl_px = static_cast(px << 1); - r.x += px; - r.width = (r.width < dbl_px ? 0 : r.width - dbl_px); - - r.y += px; - r.height = (r.height < dbl_px ? 0 : r.height - dbl_px); - } - else - { - int il{ -1 }, ir{ -1 }, it{ -1 }, ib{ -1 }; //index of four corners in margin - switch (margins_.size()) - { - case 0: break; - case 1: //top - it = 0; - break; - case 2://top,bottom and left,right - it = ib = 0; - il = ir = 1; - break; - default: - il = 3; //left - case 3: //top, right, bottom - it = 0; - ir = 1; - ib = 2; - } - - typedef decltype(r.height) px_type; - auto calc = [](px_type a, px_type b) - { - return (a > b ? a - b : 0); - }; - - if (0 == it) //top - { - auto px = static_cast(margins_[it].get_value(static_cast(field_area.height))); - r.y += px; - r.height = calc(r.height, static_cast(px)); - } - - if (-1 != ib) //bottom - { - auto px = static_cast(margins_[ib].get_value(static_cast(field_area.height))); - r.height = calc(r.height, static_cast(px)); - } - - if (-1 != il) //left - { - auto px = static_cast(margins_[il].get_value(static_cast(field_area.width))); - r.x += px; - r.width = calc(r.width, static_cast(px)); - } - - if (-1 != ir) //right - { - auto px = static_cast(margins_[ir].get_value(static_cast(field_area.width))); - r.width = calc(r.width, static_cast(px)); - } - } - return r; - } - private: - bool all_edges_ = true; - std::vector margins_; - };//end class margin - - class repeated_array - { - public: - - //A workaround for VC2013, becuase it does not generated an implicit declared move-constructor as defaulted. - repeated_array() = default; - - repeated_array(repeated_array && other) - : repeated_{other.repeated_}, - values_(std::move(other.values_)) - { - } - - repeated_array& operator=(repeated_array&& other) - { - if(this != &other) - { - repeated_ = other.repeated_; - other.repeated_ = false; - values_ = std::move(other.values_); - } - return *this; - } - - void assign(std::vector&& c) - { - values_ = std::move(c); - } - - bool empty() const - { - return values_.empty(); - } - - void reset() - { - repeated_ = false; - values_.clear(); - } - - void repeated() - { - repeated_ = true; - } - - void push(const number_t& n) - { - values_.emplace_back(n); - } - - number_t at(std::size_t pos) const - { - if (values_.empty()) - return{}; - - if (repeated_) - pos %= values_.size(); - else if (pos >= values_.size()) - return{}; - - return values_[pos]; - } - private: - bool repeated_ = false; - std::vector values_; - }; }//end namespace place_parts typedef place_parts::number_t number_t; @@ -348,8 +52,8 @@ namespace nana enum class token { div_start, div_end, splitter, - identifier, vert, grid, number, array, reparray, - weight, gap, margin, arrange, variable, repeated, min_px, max_px, + identifier, dock, vert, grid, number, array, reparray, + weight, gap, margin, arrange, variable, repeated, min_px, max_px, left, right, top, bottom, collapse, parameters, equal, eof, error @@ -384,6 +88,22 @@ namespace nana return parameters_; } + std::size_t pos() const + { + return (sp_ - divstr_); + } + + std::string pos_str() const + { +#ifdef NANA_MINGW + std::stringstream ss; + ss< root_division; - std::map fields; + std::map fields; + std::map docks; + std::map dock_factoris; + + //A temporary pointer used to refer to a specified div object which + //will be deleted in modification process. + std::unique_ptr tmp_replaced; //The following functions are defined behind the definition of class division. //because the class division here is an incomplete type. ~implement(); + + void collocate(); + static division * search_div_name(division* start, const std::string&); std::unique_ptr scan_div(place_parts::tokenizer&); + void check_unique(const division*) const; + + //connect the field/dock with div object + void connect(division* start); + void disconnect(); }; //end struct implement - class place::implement::field_impl + class place::implement::field_gather : public place::field_interface { public: @@ -732,11 +485,11 @@ namespace nana {} }; - field_impl(place * p) + field_gather(place * p) : place_ptr_(p) {} - ~field_impl() + ~field_gather() { for (auto & e : elements) API::umake_event(e.evt_destroy); @@ -778,7 +531,7 @@ namespace nana { return API::events(wd).destroy.connect([this, wd](const arg_destroy& arg) { - if (erase_element(elements, arg.window_handle)) + for (auto i = elements.begin(), end = elements.end(); i != end; ++i) { if (!API::is_destroying(API::get_parent_window(wd))) place_ptr_->collocate(); @@ -840,12 +593,23 @@ namespace nana std::vector fastened; private: place * place_ptr_; - };//end class field_impl + };//end class field_gather + + class place::implement::field_dock + { + + public: + div_dockpane * attached{ nullptr }; //attached div object + std::unique_ptr dockarea; //the dockable widget + std::map(window)>> factories; //factories for dockpane + };//end class field_dock + + class place::implement::division { public: - enum class kind{ arrange, vertical_arrange, grid, splitter }; + enum class kind{ arrange, vertical_arrange, grid, splitter, dock, dockpane}; division(kind k, std::string&& n) : kind_of_division(k), @@ -879,6 +643,50 @@ namespace nana _m_visible_for_child(this, dsp); visible = dsp; display = dsp; + + if (kind::splitter != kind_of_division) + { + //Don't display the previous one, if it is a splitter + auto div = previous(); + if (div && (kind::splitter == div->kind_of_division)) + { + if (dsp) + { + auto leaf = div->previous(); + if (leaf && leaf->display) + div->set_display(true); + } + else + div->set_display(false); + } + + //Don't display the next one, if it is a splitter + if (div_next && (kind::splitter == div_next->kind_of_division)) + { + if (dsp) + { + auto leaf = div_next->div_next; + if (leaf && leaf->display) + div_next->set_display(true); + } + else + div_next->set_display(false); + } + } + else + { + //This is a splitter, it only checks when it is being displayed + if (dsp) + { + auto left = this->previous(); + if (left && !left->display) + left->set_display(true); + + auto right = div_next; + if (right && !right->display) + right->set_display(true); + } + } } bool is_back(const division* div) const @@ -924,6 +732,18 @@ namespace nana { return margin.area(field_area); } + + division * previous() const + { + if (div_owner) + { + for (auto & child : div_owner->children) + if (child->div_next == this) + return child.get(); + } + return nullptr; + + } public: void _m_visible_for_child(division * div, bool vsb) { @@ -943,21 +763,22 @@ namespace nana kind kind_of_division; bool display{ true }; bool visible{ true }; - const std::string name; + ::nana::direction dir{::nana::direction::west}; + std::string name; std::vector> children; - nana::rectangle field_area; + ::nana::rectangle field_area; number_t weight; number_t min_px, max_px; place_parts::margin margin; place_parts::repeated_array gap; - field_impl * field; + field_gather * field; division * div_next, *div_owner; };//end class division template - void place::implement::field_impl::_m_for_each(division * div, Function fn) + void place::implement::field_gather::_m_for_each(division * div, Function fn) { for (auto & up : div->children) //The element of children is unique_ptr fn(up.get()); @@ -1503,23 +1324,28 @@ namespace nana class place::implement::div_splitter : public division { + struct div_block + { + division * div; + int pixels; + double scale; + + div_block(division* d, int px) + : div(d), pixels(px) + {} + }; + enum{splitter_px = 4}; public: div_splitter(place_parts::number_t init_weight) : division(kind::splitter, std::string()), splitter_cursor_(cursor::arrow), - leaf_left_(nullptr), leaf_right_(nullptr), pause_move_collocate_(false), init_weight_(init_weight) { this->weight.assign(splitter_px); } - void set_leaf(bool is_left, division * d) - { - (is_left ? leaf_left_ : leaf_right_) = d; - } - void direction(bool horizontal) { splitter_cursor_ = (horizontal ? cursor::size_we : cursor::size_ns); @@ -1546,8 +1372,8 @@ namespace nana auto px_ptr = &nana::rectangle::width; //Use field_area of leaf, not margin_area. Otherwise splitter would be at wrong position - auto area_left = leaf_left_->field_area; - auto area_right = leaf_right_->field_area; + auto area_left = _m_leaf_left()->field_area; + auto area_right = _m_leaf_right()->field_area; if (nana::cursor::size_we != splitter_cursor_) { @@ -1583,8 +1409,8 @@ namespace nana left_px = 0; double imd_rate = 100.0 / area_px; - left_px = static_cast(limit_px(leaf_left_, left_px, area_px)); - leaf_left_->weight.assign_percent(imd_rate * left_px); + left_px = static_cast(limit_px(_m_leaf_left(), left_px, area_px)); + _m_leaf_left()->weight.assign_percent(imd_rate * left_px); auto right_px = static_cast(right_pixels_)-delta; if (right_px > total_pixels) @@ -1592,15 +1418,15 @@ namespace nana else if (right_px < 0) right_px = 0; - right_px = static_cast(limit_px(leaf_right_, right_px, area_px)); - leaf_right_->weight.assign_percent(imd_rate * right_px); + right_px = static_cast(limit_px(_m_leaf_right(), right_px, area_px)); + _m_leaf_right()->weight.assign_percent(imd_rate * right_px); pause_move_collocate_ = true; div_owner->collocate(splitter_.parent()); //After the collocating, the splitter keeps the calculated weight of left division, //and clear the weight of right division. - leaf_right_->weight.reset(); + _m_leaf_right()->weight.reset(); pause_move_collocate_ = false; }); @@ -1612,10 +1438,12 @@ namespace nana { const bool vert = (::nana::cursor::size_we != splitter_cursor_); - rectangle_rotator left(vert, leaf_left_->field_area); - rectangle_rotator right(vert, leaf_right_->field_area); + auto leaf_left = _m_leaf_left(); + auto leaf_right = _m_leaf_right(); + rectangle_rotator left(vert, leaf_left->field_area); + rectangle_rotator right(vert, leaf_right->field_area); auto area_px = right.right() - left.x(); - auto right_px = static_cast(limit_px(leaf_right_, init_weight_.get_value(area_px), static_cast(area_px))); + auto right_px = static_cast(limit_px(leaf_right, init_weight_.get_value(area_px), static_cast(area_px))); auto pos = area_px - right_px - splitter_px; //New position of splitter if (pos < limited_range.x()) @@ -1623,7 +1451,7 @@ namespace nana else if (pos > limited_range.right()) pos = limited_range.right(); - nana::rectangle_rotator sp_r(vert, field_area); + rectangle_rotator sp_r(vert, field_area); sp_r.x_ref() = pos; left.w_ref() = static_cast(pos - left.x()); @@ -1633,17 +1461,17 @@ namespace nana right.w_ref() = static_cast(right_pos - pos - splitter_px); field_area = sp_r.result(); - leaf_left_->field_area = left.result(); - leaf_right_->field_area = right.result(); - leaf_left_->collocate(wd); - leaf_right_->collocate(wd); + leaf_left->field_area = left.result(); + leaf_right->field_area = right.result(); + leaf_left->collocate(wd); + leaf_right->collocate(wd); //Set the leafs' weight rectangle_rotator area(vert, div_owner->field_area); double imd_rate = 100.0 / static_cast(area.w()); - leaf_left_->weight.assign_percent(imd_rate * static_cast(left.w())); - leaf_right_->weight.assign_percent(imd_rate * static_cast(right.w())); + leaf_left->weight.assign_percent(imd_rate * static_cast(left.w())); + leaf_right->weight.assign_percent(imd_rate * static_cast(right.w())); splitter_.move(this->field_area); @@ -1654,40 +1482,53 @@ namespace nana splitter_.move(this->field_area); } private: + division * _m_leaf_left() const + { + return previous(); + } + + division * _m_leaf_right() const + { + return div_next; + } + rectangle_rotator _m_update_splitter_range() { const bool vert = (cursor::size_ns == splitter_cursor_); rectangle_rotator area(vert, div_owner->margin_area()); - rectangle_rotator left(vert, leaf_left_->field_area); - rectangle_rotator right(vert, leaf_right_->field_area); + auto leaf_left = _m_leaf_left(); + auto leaf_right = _m_leaf_right(); + + rectangle_rotator left(vert, leaf_left->field_area); + rectangle_rotator right(vert, leaf_right->field_area); const int left_base = left.x(), right_base = right.right(); int pos = left_base; int endpos = right_base; - if (leaf_left_->min_px.is_not_none()) + if (leaf_left->min_px.is_not_none()) { - auto v = leaf_left_->min_px.get_value(area.w()); + auto v = leaf_left->min_px.get_value(area.w()); pos += static_cast(v); } - if (leaf_left_->max_px.is_not_none()) + if (leaf_left->max_px.is_not_none()) { - auto v = leaf_left_->max_px.get_value(area.w()); + auto v = leaf_left->max_px.get_value(area.w()); endpos = left_base + static_cast(v); } - if (leaf_right_->min_px.is_not_none()) + if (leaf_right->min_px.is_not_none()) { - auto v = leaf_right_->min_px.get_value(area.w()); + auto v = leaf_right->min_px.get_value(area.w()); auto x = right_base - static_cast(v); if (x < endpos) endpos = x; } - if (leaf_right_->max_px.is_not_none()) + if (leaf_right->max_px.is_not_none()) { - auto v = leaf_right_->max_px.get_value(area.w()); + auto v = leaf_right->max_px.get_value(area.w()); auto x = right_base - static_cast(v); if (x > pos) pos = x; @@ -1702,10 +1543,9 @@ namespace nana } private: nana::cursor splitter_cursor_; + bool created_{ false }; place_parts::splitter splitter_; nana::point begin_point_; - division * leaf_left_; - division * leaf_right_; int left_pos_, right_pos_; unsigned left_pixels_, right_pixels_; dragger dragger_; @@ -1713,12 +1553,588 @@ namespace nana place_parts::number_t init_weight_; }; + class place::implement::div_dockpane + : public division, public place_parts::dock_notifier_interface + { + public: + div_dockpane(std::string && name, implement* impl, direction pane_dir) + : division(kind::dockpane, std::move(name)), + impl_ptr_{impl} + { + dir = pane_dir; + this->display = false; + } + + ~div_dockpane() + { + if (dockable_field) + { + dockable_field->dockarea.reset(); + dockable_field->attached = nullptr; + } + } + + void collocate(window wd) override + { + if (!dockable_field) + { + if (name.empty()) + return; + + auto &dock_ptr = impl_ptr_->docks[name]; + if (!dock_ptr) + dock_ptr = new field_dock; + + dock_ptr->attached = this; + dockable_field = dock_ptr; + } + + auto & dockarea = dockable_field->dockarea; + + /* + if (!created_) + { + created_ = true; + dockarea.create(wd, this); + } + + if (!dockarea.empty() && !dockarea.floating()) + dockarea.move(this->field_area); + */ + + if (dockarea && !dockarea->floating()) + dockarea->move(this->field_area); + } + private: + //Implement dock_notifier_interface + void notify_float() override + { + set_display(false); + impl_ptr_->collocate(); + } + + void notify_dock() override + { + indicator_.docker.reset(); + + set_display(true); + impl_ptr_->collocate(); + } + + void notify_move() override + { + if (!_m_indicator()) + { + indicator_.docker.reset(); + return; + } + + if (!indicator_.docker) + { + auto host_size = API::window_size(impl_ptr_->window_handle); + indicator_.docker.reset(new form(impl_ptr_->window_handle, { static_cast(host_size.width) / 2 - 16, static_cast(host_size.height) / 2 - 16, 32, 32 }, form::appear::bald<>())); + drawing dw(indicator_.docker->handle()); + dw.draw([](paint::graphics& graph) + { + graph.rectangle(false, colors::midnight_blue); + graph.rectangle({ 1, 1, 30, 30 }, true, colors::light_sky_blue); + + facade arrow; + arrow.direction(::nana::direction::south); + arrow.draw(graph, colors::light_sky_blue, colors::midnight_blue, { 12, 0, 16, 16 }, element_state::normal); + + graph.rectangle({ 4, 16, 24, 11 }, true, colors::midnight_blue); + graph.rectangle({ 5, 19, 22, 7 }, true, colors::button_face); + }); + + indicator_.docker->z_order(nullptr, ::nana::z_order_action::topmost); + indicator_.docker->show(); + + indicator_.docker->events().destroy([this] + { + if (indicator_.dock_area) + { + indicator_.dock_area.reset(); + indicator_.graph.release(); + } + }); + } + + if (_m_dockable()) + { + if (!indicator_.dock_area) + { + set_display(true); + impl_ptr_->collocate(); + + indicator_.graph.make(API::window_size(impl_ptr_->window_handle)); + API::window_graphics(impl_ptr_->window_handle, indicator_.graph); + + indicator_.dock_area.reset(new panel(impl_ptr_->window_handle, false)); + indicator_.dock_area->move(this->field_area); + + ::nana::drawing dw(indicator_.dock_area->handle()); + dw.draw([this](paint::graphics& graph) + { + indicator_.graph.paste(this->field_area, graph, 0, 0); + + const int border_px = 4; + rectangle r{ graph.size() }; + int right = r.right(); + int bottom = r.bottom(); + + graph.blend(r.pare_off(border_px), colors::blue, 0.3); + + ::nana::color clr = colors::deep_sky_blue; + r.y = 0; + r.height = border_px; + graph.blend(r, clr, 0.5); + r.y = bottom - border_px; + graph.blend(r, clr, 0.5); + + r.x = r.y = 0; + r = graph.size(); + r.width = border_px; + graph.blend(r, clr, 0.5); + r.x = right - border_px; + graph.blend(r, clr, 0.5); + + }); + + API::bring_top(indicator_.dock_area->handle(), false); + indicator_.dock_area->show(); + } + } + else + { + set_display(false); + impl_ptr_->collocate(); + if (indicator_.dock_area) + { + indicator_.dock_area.reset(); + indicator_.graph.release(); + } + } + + } + + void notify_move_stopped() override + { + if (_m_dockable() && dockable_field && dockable_field->dockarea) + dockable_field->dockarea->dock(); + + indicator_.docker.reset(); + } + + void request_close() override + { + auto window_handle = dockable_field->dockarea->handle(); + + //a workaround for capture + auto ptr = dockable_field->dockarea.release(); + API::at_safe_place(window_handle, [this, ptr] + { + decltype(dockable_field->dockarea) del(ptr); + }); + + this->set_display(false); + impl_ptr_->collocate(); + + API::close_window(window_handle); + } + private: + bool _m_indicator() const + { + ::nana::point pos; + API::calc_screen_point(impl_ptr_->window_handle, pos); + + rectangle r{ pos, API::window_size(impl_ptr_->window_handle) }; + return r.is_hit(API::cursor_position()); + } + + bool _m_dockable() const + { + if (!indicator_.docker) + return false; + + ::nana::point pos; + API::calc_screen_point(indicator_.docker->handle(), pos); + + rectangle r{ pos, API::window_size(indicator_.docker->handle()) }; + return r.is_hit(API::cursor_position()); + } + public: + field_dock * dockable_field{ nullptr }; + private: + implement * impl_ptr_; + bool created_{ false }; + + // + struct indicator_rep + { + paint::graphics graph; + std::unique_ptr> dock_area; + std::unique_ptr
docker; + }indicator_; + }; + + class place::implement::div_dock + : public division + { + static const unsigned splitter_px = 5; + + class splitter : public panel + { + public: + splitter(window wd, ::nana::direction dir, division* dock_dv, division* pane_dv) + : panel(wd, true), dir_(dir), dock_dv_(dock_dv), pane_dv_(pane_dv) + { + this->bgcolor(colors::alice_blue); + this->cursor(_m_is_vert(dir_) ? ::nana::cursor::size_ns : ::nana::cursor::size_we); + + this->events().mouse_down([this](const arg_mouse& arg) + { + if (arg.button != ::nana::mouse::left_button) + return; + + API::capture_window(this->handle(), true); + auto basepos = API::cursor_position(); + base_pos_.x = (_m_is_vert(dir_) ? basepos.y : basepos.x); + + basepos = this->pos(); + base_pos_.y = (_m_is_vert(dir_) ? basepos.y : basepos.x); + + base_px_ = (_m_is_vert(dir_) ? pane_dv_->field_area.height : pane_dv_->field_area.width); + }); + + this->events().mouse_up([this] + { + API::capture_window(this->handle(), false); + }); + + this->events().mouse_move([this, wd](const arg_mouse& arg) + { + if (!arg.is_left_button()) + return; + + auto now_pos = API::cursor_position(); + int delta = (_m_is_vert(dir_) ? now_pos.y : now_pos.x) - base_pos_.x; + int new_pos = base_pos_.y + delta; + if (new_pos < range_.x) + { + new_pos = range_.x; + delta = new_pos - base_pos_.y; + } + else if (new_pos >= range_.y) + { + new_pos = range_.y - 1; + delta = new_pos - base_pos_.y; + } + + now_pos = this->pos(); + if (_m_is_vert(dir_)) + now_pos.y = new_pos; + else + now_pos.x = new_pos; + this->move(now_pos); + + auto px = base_px_; + switch (dir_) + { + case ::nana::direction::west: + case ::nana::direction::north: + if (delta < 0) + px -= static_cast(-delta); + else + px += static_cast(delta); + break; + case ::nana::direction::east: + case ::nana::direction::south: + if (delta < 0) + px += static_cast(-delta); + else + px -= static_cast(delta); + break; + } + + auto dock_px = (_m_is_vert(dir_) ? dock_dv_->field_area.height : dock_dv_->field_area.width); + + pane_dv_->weight.assign_percent(double(px) / double(dock_px) * 100); + + dock_dv_->collocate(wd); + }); + } + + void range(int begin, int end) + { + range_.x = begin; + range_.y = end; + } + private: + const ::nana::direction dir_; + division* const dock_dv_; + division* const pane_dv_; + ::nana::point range_; + ::nana::point base_pos_; //x = mouse pos, y = splitter pos + unsigned base_px_; //weight of div_dockpane when mouse button is been pressing; + + }; + public: + + div_dock(std::string && name, implement* impl) + : division(kind::dock, std::move(name)), impl_(impl) + {} + + division* front() const + { + auto i = children.cbegin(); + + for (auto i = children.cbegin(); i != children.cend(); ++i) + { + if (i->get()->display) + return i->get(); + } + + return nullptr; + } + + void collocate(window wd) override + { + auto area = this->margin_area(); + + unsigned vert_count = 0, horz_count = 0; + + bool is_first = true; + bool prev_attr; + + for (auto & child : children) + { + if (!child->display) + continue; + + auto child_dv = dynamic_cast(child.get()); + + const auto is_vert = _m_is_vert(child->dir); + if (is_first) + { + is_first = false; + (is_vert ? horz_count : vert_count) = 1; + prev_attr = is_vert; + } + + if ((is_vert == prev_attr) == is_vert) + ++vert_count; + else + ++horz_count; + + prev_attr = is_vert; + } + if (0 == vert_count) + ++vert_count; + if (0 == horz_count) + ++horz_count; + + //room indicates the size without splitters + ::nana::size room(area.width - splitter_px * (horz_count - 1), area.height - splitter_px * (vert_count - 1)); + + //double auto_horz_w = double(area.width - splitter_px * (horz_count - 1))/ horz_count; + //double auto_vert_w = double(area.height - splitter_px * (vert_count - 1)) / vert_count; + + double left = area.x; + double right = area.right(); + double top = area.y; + double bottom = area.bottom(); + + std::map> swp_splitters; + + for (auto & child : children) + { + if (!child->display) + continue; + + auto child_dv = dynamic_cast(child.get()); + const bool is_vert = _m_is_vert(child->dir); + + auto room_px = (is_vert ? room.height : room.width); + + double weight; + if (child->weight.is_not_none()) + { + weight = child->weight.get_value(is_vert ? area.height : area.width); + if (weight > room_px) + weight = room_px; + } + else + weight = room_px / double(is_vert ? vert_count : horz_count); + + splitter* split = nullptr; + if (_m_right(child_dv)) + { + //Creates a splitbar if the 'right' leaf is not empty + + auto & splitter_ptr = swp_splitters[child_dv]; + + auto si = splitters_.find(child_dv); + if (si == splitters_.end()) + splitter_ptr.reset(new splitter(impl_->window_handle, child->dir, this, child_dv)); + else + splitter_ptr.swap(si->second); + + split = splitter_ptr.get(); + } + + ::nana::rectangle child_r; + double split_range_begin = -1, split_range_end; + switch (child->dir) + { + default: + case ::nana::direction::west: + child_r.x = static_cast(left); + child_r.y = static_cast(top); + child_r.width = static_cast(weight); + child_r.height = static_cast(bottom - top); + left += weight; + if (split) + { + split->move(rectangle{ child_r.right(), child_r.y, splitter_px, child_r.height }); + split_range_begin = left - weight; + split_range_end = right - static_cast(splitter_px); + left += splitter_px; + } + break; + case ::nana::direction::east: + right -= weight; + child_r.x = static_cast(right); + child_r.y = static_cast(top); + child_r.width = static_cast(weight); + child_r.height = static_cast(bottom - top); + if (split) + { + split->move(rectangle{ child_r.x - static_cast(splitter_px), child_r.y, splitter_px, child_r.height }); + split_range_begin = left; + split_range_end = right - static_cast(splitter_px)+weight; + right -= splitter_px; + } + break; + case ::nana::direction::north: + child_r.x = static_cast(left); + child_r.y = static_cast(top); + child_r.width = static_cast(right - left); + child_r.height = static_cast(weight); + top += weight; + if (split) + { + split->move(rectangle{ child_r.x, child_r.bottom(), child_r.width, splitter_px }); + split_range_begin = top - weight; + split_range_end = bottom - static_cast(splitter_px); + top += splitter_px; + } + break; + case ::nana::direction::south: + child_r.x = static_cast(left); + bottom -= weight; + child_r.y = static_cast(bottom); + child_r.width = static_cast(right - left); + child_r.height = static_cast(weight); + if (split) + { + bottom -= splitter_px; + split->move(rectangle{ child_r.x, child_r.y - static_cast(splitter_px), child_r.width, splitter_px }); + split_range_begin = top; + split_range_end = bottom + weight; + } + break; + } + + if (split_range_begin > -0.5) + split->range(static_cast(split_range_begin), static_cast(split_range_end)); + + + if (is_vert) + { + room.height -= child_r.height; + --vert_count; + } + else + { + room.width -= child_r.width; + --horz_count; + } + + child->field_area = child_r; + child->collocate(wd); + } + + splitters_.swap(swp_splitters); + } + private: + static bool _m_is_vert(::nana::direction dir) + { + return (dir == ::nana::direction::north || dir == ::nana::direction::south); + } + + static div_dockpane* _m_right(division* dv) + { + dv = dv->div_next; + while (dv) + { + if (dv->display) + return dynamic_cast(dv); + + dv = dv->div_next; + } + return nullptr; + } + private: + implement * const impl_; + std::map> splitters_; + }; + place::implement::~implement() { API::umake_event(event_size_handle); root_division.reset(); + for (auto & pair : fields) delete pair.second; + + for (auto & dock : docks) + delete dock.second; + } + + void place::implement::collocate() + { + if (root_division && window_handle) + { + root_division->field_area = API::window_size(window_handle); + + if (root_division->field_area.empty()) + return; + + root_division->collocate(window_handle); + + for (auto & field : fields) + { + bool is_show = false; + if (field.second->attached && field.second->attached->visible && field.second->attached->display) + { + is_show = true; + auto div = field.second->attached->div_owner; + while (div) + { + if (!div->visible || !div->display) + { + is_show = false; + break; + } + div = div->div_owner; + } + } + + for (auto & el : field.second->elements) + API::show_window(el.handle, is_show); + } + } } //search_div_name @@ -1755,18 +2171,24 @@ namespace nana std::vector array; std::vector collapses; std::vector> children; + ::nana::direction div_dir = ::nana::direction::west; for (token tk = tknizer.read(); tk != token::eof; tk = tknizer.read()) { bool exit_for = false; switch (tk) { + case token::dock: + if (token::eof != div_type && token::dock != div_type) + throw std::invalid_argument("nana.place: conflict of div type at " + tknizer.pos_str()); + + div_type = token::dock; + break; case token::splitter: //Ignore the splitter when there is not a division. if (!children.empty() && (division::kind::splitter != children.back()->kind_of_division)) { auto splitter = new div_splitter(tknizer.number()); - splitter->set_leaf(true, children.back().get()); children.back()->div_next = splitter; children.emplace_back(splitter); } @@ -1774,12 +2196,9 @@ namespace nana case token::div_start: { auto div = scan_div(tknizer); - if (children.size()) - { + if (!children.empty()) children.back()->div_next = div.get(); - if (division::kind::splitter == children.back()->kind_of_division) - dynamic_cast(*children.back()).set_leaf(false, div.get()); - } + children.emplace_back(div.release()); } break; @@ -1815,7 +2234,7 @@ namespace nana else if (arg.kind_of() == number_t::kind::real) return static_cast(arg.real()); - throw std::runtime_error("place: the type of the "+ nth +" parameter for collapse should be integer."); + throw std::invalid_argument("nana.place: the type of the "+ nth +" parameter for collapse should be integer."); }; ::nana::rectangle col; @@ -1851,7 +2270,7 @@ namespace nana } } else - throw std::runtime_error("place: collapse requires 4 parameters."); + throw std::invalid_argument("nana.place: collapse requires 4 parameters."); break; case token::weight: case token::min_px: case token::max_px: { @@ -1904,13 +2323,21 @@ namespace nana case token::identifier: name = tknizer.idstr(); break; + case token::left: + div_dir = ::nana::direction::west; break; + case token::right: + div_dir = ::nana::direction::east; break; + case token::top: + div_dir = ::nana::direction::north; break; + case token::bottom: + div_dir = ::nana::direction::south; break; default: break; } if (exit_for) break; } - field_impl * attached_field = nullptr; + field_gather * attached_field = nullptr; if (name.size()) { //find the field with specified name. @@ -1951,8 +2378,11 @@ namespace nana div = std::move(p); } break; + case token::dock: + div.reset(new div_dock(std::move(name), this)); + break; default: - throw std::runtime_error("nana.place: invalid division type."); + throw std::invalid_argument("nana.place: invalid division type."); } //Requirements for min/max @@ -1999,13 +2429,148 @@ namespace nana if (division::kind::splitter == child->kind_of_division) dynamic_cast(*child).direction(div_type != token::vert); } + + if (token::dock == div_type) + { + //adjust these children for dock division + std::vector> adjusted_children; + for (auto & child : children) + { + //ignores weight if it is a dockpane + auto dockpn = new div_dockpane(std::move(child->name), this, child->dir); + dockpn->div_owner = child->div_owner; + adjusted_children.emplace_back(dockpn); + } + + division * next = nullptr; + for (auto i = adjusted_children.rbegin(); i != adjusted_children.rend(); ++i) + { + i->get()->div_next = next; + next = i->get(); + } + + children.swap(adjusted_children); + } } div->children.swap(children); div->margin = std::move(margin); + div->dir = div_dir; return div; } + void place::implement::check_unique(const division* div) const + { + //The second field_impl is useless. Reuse the map type in order to + //reduce the size of the generated code, becuase std::set + //will create a new template class. + std::map unique; + field_gather tmp(nullptr); + + std::function check_fn; + check_fn = [&check_fn, &unique, &tmp](const implement::division* div) + { + if (!div->name.empty()) + { + auto & ptr = unique[div->name]; + if (ptr) + throw std::invalid_argument("place, the name '" + div->name + "' is redefined."); + ptr = &tmp; + } + + for (auto & child : div->children) + { + check_fn(child.get()); + } + }; + + if (div) + check_fn(div); + } + + //connect the field/dock with div object, + void place::implement::connect(division* start) + { + if (!start) + return; + + this->disconnect(); + + std::map docks_to_be_closed; + //disconnect + for (auto & dk : docks) + { + if (dk.second->attached) + docks_to_be_closed[dk.first] = dk.second; + } + + std::function connect_fn; + connect_fn = [&connect_fn, this, &docks_to_be_closed](division* div) + { + if (div->name.size()) + { + if (division::kind::dock == div->kind_of_division || division::kind::dockpane == div->kind_of_division) + { + auto i = docks.find(div->name); + if (i != docks.end()) + { + docks_to_be_closed.erase(div->name); + auto pane = dynamic_cast(div); + pane->dockable_field = i->second; + + auto old_pane = pane->dockable_field->attached; + if (old_pane) + { + //old div_dockpane will be deleted + old_pane->dockable_field = nullptr; + div->display = old_pane->display; + } + pane->dockable_field->attached = pane; + + if (pane->dockable_field->dockarea) + pane->dockable_field->dockarea->set_notifier(pane); + } + } + else + { + auto i = fields.find(div->name); + if (i != fields.end()) + { + div->field = i->second; + div->field->attached = div; + } + } + + } + + for (auto & child : div->children) + { + connect_fn(child.get()); + } + }; + + connect_fn(start); + + for (auto& e : docks_to_be_closed) + { + e.second->dockarea.reset(); + e.second->attached->dockable_field = nullptr; + e.second->attached = nullptr; + } + } + + void place::implement::disconnect() + { + for (auto & fd : fields) + { + if (fd.second->attached) + { + fd.second->attached->field = nullptr; + fd.second->attached = nullptr; + } + } + } + //class place place::place() : impl_(new implement) @@ -2046,8 +2611,85 @@ namespace nana void place::div(const char* s) { place_parts::tokenizer tknizer(s); - impl_->root_division.reset(); //clear atachments div-fields - impl_->scan_div(tknizer).swap(impl_->root_division); + impl_->disconnect(); + auto div = impl_->scan_div(tknizer); + try + { + impl_->check_unique(div.get()); //may throw if there is a redefined name of field. + impl_->connect(div.get()); + impl_->root_division.reset(); //clear atachments div-fields + impl_->root_division.swap(div); + } + catch (...) + { + //redefined a name of field + throw; + } + } + + void place::modify(const char* name, const char* div_text) + { + if (nullptr == div_text) + throw std::invalid_argument("nana.place: invalid div-text"); + + if (nullptr == name) name = ""; + + //check the name, it throws std::invalid_argument + //if name violate the naming convention. + place_parts::check_field_name(name); + + auto div_ptr = impl_->search_div_name(impl_->root_division.get(), name); + if (!div_ptr) + { + std::string what = "nana::place: field '"; + what += name; + what += "' is not found."; + + throw std::invalid_argument(what); + } + + + std::unique_ptr* replaced = nullptr; + + implement::division * div_owner = div_ptr->div_owner; + implement::division * div_next = div_ptr->div_next; + if (div_owner) + { + for (auto i = div_owner->children.begin(); i != div_owner->children.end(); ++i) + { + if (i->get() == div_ptr) + { + replaced = &(*i); + break; + } + } + } + else + replaced = &(impl_->root_division); + + replaced->swap(impl_->tmp_replaced); + + try + { + place_parts::tokenizer tknizer(div_text); + auto modified = impl_->scan_div(tknizer); + auto modified_ptr = modified.get(); + modified_ptr->name = name; + + replaced->swap(modified); + + impl_->check_unique(impl_->root_division.get()); + impl_->connect(impl_->root_division.get()); + impl_->tmp_replaced.reset(); + + modified_ptr->div_owner = div_owner; + modified_ptr->div_next = div_next; + } + catch (...) + { + replaced->swap(impl_->tmp_replaced); + throw; + } } place::field_reference place::field(const char* name) @@ -2055,14 +2697,15 @@ namespace nana if (nullptr == name) name = ""; - //May throw std::invalid_argument + //check the name, it throws std::invalid_argument + //if name violate the naming convention. place_parts::check_field_name(name); //get the field with specified name, if no such field with specified name //then create one. auto & p = impl_->fields[name]; if (nullptr == p) - p = new implement::field_impl(this); + p = new implement::field_gather(this); if ((!p->attached) && impl_->root_division) { @@ -2084,7 +2727,7 @@ namespace nana void place::field_visible(const char* name, bool vsb) { if (!name) name = ""; - + //May throw std::invalid_argument place_parts::check_field_name(name); @@ -2129,33 +2772,7 @@ namespace nana void place::collocate() { - if (impl_->root_division && impl_->window_handle) - { - impl_->root_division->field_area = API::window_size(impl_->window_handle); - impl_->root_division->collocate(impl_->window_handle); - - for (auto & field : impl_->fields) - { - bool is_show = false; - if (field.second->attached && field.second->attached->visible && field.second->attached->display) - { - is_show = true; - auto div = field.second->attached->div_owner; - while (div) - { - if (!div->visible || !div->display) - { - is_show = false; - break; - } - div = div->div_owner; - } - } - - for (auto & el : field.second->elements) - API::show_window(el.handle, is_show); - } - } + impl_->collocate(); } void place::erase(window handle) @@ -2170,7 +2787,7 @@ namespace nana recollocate |= (nullptr != fld.second->attached); } - API::umake_event( fld.second->erase_element(fld.second->fastened, handle)); + API::umake_event(fld.second->erase_element(fld.second->fastened, handle)); } if (recollocate) @@ -2181,5 +2798,75 @@ namespace nana { return field(name); } + + place& place::dock(const std::string& name, std::string factory_name, std::function(window)> factory) + { + //check the name, it throws std::invalid_argument + //if name violate the naming convention. + place_parts::check_field_name(name.data()); + + auto & dock_ptr = impl_->docks[name]; + if (!dock_ptr) + dock_ptr = new implement::field_dock; + + //Register the factory if it has a name + if (!factory_name.empty()) + { + auto i = impl_->dock_factoris.find(factory_name); + if (i != impl_->dock_factoris.end()) + throw std::invalid_argument("nana::place - the specified factory name(" + factory_name + ") already exists"); + + impl_->dock_factoris[factory_name] = dock_ptr; + dock_ptr->factories[factory_name].swap(factory); + } + + auto div = dynamic_cast(impl_->search_div_name(impl_->root_division.get(), name)); + if (div) + { + dock_ptr->attached = div; + div->dockable_field = dock_ptr; + } + + //Create the pane if it has not a name + if (factory_name.empty()) + { + dock_ptr->attached->set_display(true); + impl_->collocate(); + + if (!dock_ptr->dockarea) + { + dock_ptr->dockarea.reset(new ::nana::place_parts::dockarea); + dock_ptr->dockarea->create(impl_->window_handle); + dock_ptr->dockarea->set_notifier(dock_ptr->attached); + dock_ptr->dockarea->move(dock_ptr->attached->field_area); + } + dock_ptr->dockarea->add_pane(factory); + } + + return *this; + } + + place& place::dock_create(const std::string& factory) + { + auto i = impl_->dock_factoris.find(factory); + if (i == impl_->dock_factoris.end()) + throw std::invalid_argument("invalid factory name(" + factory + ") of dockpane"); + + auto dock_ptr = i->second; + dock_ptr->attached->set_display(true); + impl_->collocate(); + + if (!dock_ptr->dockarea) + { + dock_ptr->dockarea.reset(new ::nana::place_parts::dockarea); + dock_ptr->dockarea->create(impl_->window_handle); + dock_ptr->dockarea->set_notifier(dock_ptr->attached); + dock_ptr->dockarea->move(dock_ptr->attached->field_area); + } + + dock_ptr->dockarea->add_pane(i->second->factories[factory]); + + return *this; + } //end class place }//end namespace nana diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp new file mode 100644 index 00000000..946d03ac --- /dev/null +++ b/source/gui/place_parts.hpp @@ -0,0 +1,697 @@ +/* + * Parts of Class Place + * Nana C++ Library(http://www.nanapro.org) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * @file: nana/gui/place_parts.hpp + */ +#ifndef NANA_GUI_PLACE_PARTS_HPP +#define NANA_GUI_PLACE_PARTS_HPP + +#include +#include +#include +#include +#include +#include + +namespace nana +{ + namespace place_parts + { + class splitter_interface + { + public: + virtual ~splitter_interface(){} + }; + + class splitter_dtrigger + : public drawer_trigger + { + }; + + template + class splitter + : public widget_object ::type, splitter_dtrigger>, + public splitter_interface + { + private: + void _m_complete_creation() override + { + this->caption("place-splitter"); + widget_object ::type, splitter_dtrigger>::_m_complete_creation(); + } + }; + + + class dock_notifier_interface + { + public: + virtual ~dock_notifier_interface() = default; + + virtual void notify_float() = 0; + virtual void notify_dock() = 0; + virtual void notify_move() = 0; + virtual void notify_move_stopped() = 0; + + //a dockarea requests to close the dockpane + virtual void request_close() = 0; + }; + + class dockcaption_dtrigger + : public drawer_trigger + { + public: + void on_close(std::function&& fn) + { + close_fn_ = std::move(fn); + } + private: + virtual void attached(widget_reference wdg, graph_reference graph) override + { + window_handle_ = wdg; + text_rd_.reset(new paint::text_renderer(graph)); + } + + void refresh(graph_reference& graph) override + { + graph.set_color(static_cast(0x83EB)); + graph.set_text_color(colors::white); + graph.rectangle(true); + + //draw caption + auto text = API::window_caption(window_handle_); + text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, true); + + //draw x button + auto r = _m_button_area(); + if (x_pointed_) + { + color xclr = colors::red; + + if(x_state_ == ::nana::mouse_action::pressed) + xclr = xclr.blend(colors::white, 0.8); + + graph.rectangle(r, true, xclr); + } + + r.x += (r.width - 16) / 2; + r.y = (r.height - 16) / 2; + + x_icon_.draw(graph, colors::red, colors::white, r, element_state::normal); + } + + void mouse_move(graph_reference graph, const arg_mouse& arg) override + { + x_pointed_ = _m_button_area().is_hit(arg.pos); + + refresh(graph); + API::lazy_refresh(); + } + + void mouse_leave(graph_reference graph, const arg_mouse&) override + { + x_pointed_ = false; + refresh(graph); + API::lazy_refresh(); + } + + void mouse_down(graph_reference graph, const arg_mouse&) override + { + if (!x_pointed_) + return; + + x_state_ = ::nana::mouse_action::pressed; + + refresh(graph); + API::lazy_refresh(); + } + + void mouse_up(graph_reference graph, const arg_mouse&) override + { + if (!x_pointed_) + return; + + x_state_ = ::nana::mouse_action::over; + refresh(graph); + API::lazy_refresh(); + + close_fn_(); + } + private: + ::nana::rectangle _m_button_area() const + { + ::nana::rectangle r{API::window_size(window_handle_)}; + + r.x = r.right() - 20; + r.width = 20; + return r; + } + public: + window window_handle_; + std::unique_ptr text_rd_; + bool x_pointed_{ false }; + ::nana::mouse_action x_state_{ ::nana::mouse_action::normal }; + facade x_icon_; + + std::function close_fn_; + }; + + class dockarea_caption + : public widget_object < category::widget_tag, dockcaption_dtrigger > + { + public: + void on_close(std::function fn) + { + get_drawer_trigger().on_close(std::move(fn)); + } + }; + + class dock_page + : public form + { + public: + dock_page(window host, const rectangle& r, const rectangle & tab_r) + : form(host, r, form::appear::bald<>()) + { + tab_form_.reset(new form(handle(), tab_r, form::appear::bald<>())); + + } + private: + std::unique_ptr tab_form_; + }; + + class dockarea + : public widget_object + { + using base_type = widget_object; + + using factory = std::function(window)>; + + struct panel + { + std::unique_ptr widget_ptr; + }; + public: + void set_notifier(place_parts::dock_notifier_interface* notifier) + { + notifier_ = notifier; + } + void create(window parent) + { + host_window_ = parent; + base_type::create(parent, true); + this->caption("dockarea"); + caption_.create(*this, true); + caption_.on_close([this] + { + bool destroy_dockarea = true; + + if (tabbar_) + { + tabbar_->erase(tabbar_->selected()); + + destroy_dockarea = (0 == tabbar_->length()); + } + + + if (destroy_dockarea) + notifier_->request_close(); + }); + + this->events().resized([this](const arg_resized& arg) + { + rectangle r{ 0, 0, arg.width, 20 }; + caption_.move(r); + + if (arg.height > 20) + { + r.y = 20; + if (tabbar_) + { + tabbar_->move({ 0, int(arg.height) - 20, arg.width, 20 }); + r.height = arg.height - 40; + } + else + r.height = arg.height - 20; + } + + + for (auto & pn : panels_) + { + if (pn.widget_ptr) + pn.widget_ptr->move(r); + } + }); + + caption_.events().mouse_down([this](const arg_mouse& arg) + { + if (::nana::mouse::left_button == arg.button) + { + moves_.started = true; + moves_.start_pos = API::cursor_position(); + moves_.start_container_pos = (floating() ? container_->pos() : this->pos()); + API::capture_window(caption_, true); + } + }); + + caption_.events().mouse_move([this](const arg_mouse& arg) + { + if (arg.left_button && moves_.started) + { + auto move_pos = API::cursor_position() - moves_.start_pos; + if (!floating()) + { + if (std::abs(move_pos.x) > 4 || std::abs(move_pos.y) > 4) + float_away(move_pos); + } + else + { + move_pos += moves_.start_container_pos; + API::move_window(container_->handle(), move_pos); + notifier_->notify_move(); + } + } + }); + + caption_.events().mouse_up([this](const arg_mouse& arg) + { + if ((::nana::mouse::left_button == arg.button) && moves_.started) + { + moves_.started = false; + API::capture_window(caption_, false); + notifier_->notify_move_stopped(); + } + }); + + } + + void add_pane(factory & fn) + { + rectangle r{ point(), this->size()}; + + //get a rectangle excluding caption + r.y = 20; + if (r.height > 20) + r.height -= 20; + else + r.height = 0; + + if (!tabbar_) + { + if (panels_.size() > 0) + { + tabbar_.reset(new tabbar_lite(*this)); + + tabbar_->events().selected.clear(); + tabbar_->events().selected([this] + { + auto handle = tabbar_->attach(tabbar_->selected()); + if (handle) + caption_.caption(API::window_caption(handle)); + else + caption_.caption(::nana::string()); + }); + + tabbar_->move({ 0, r.bottom() - 20, r.width, 20 }); + r.height -= 20; + + std::size_t pos = 0; + for (auto & pn : panels_) + { + tabbar_->push_back(::nana::charset(pn.widget_ptr->caption())); + tabbar_->attach(pos++, *pn.widget_ptr); + } + } + } + else + r.height -= 20; + + auto wdg = fn(*this); + + if (tabbar_) + { + tabbar_->push_back(::nana::charset(wdg->caption())); + tabbar_->attach(panels_.size(), wdg->handle()); + } + + if (panels_.empty()) + { + caption_.caption(wdg->caption()); + } + + panels_.emplace_back(); + panels_.back().widget_ptr.swap(wdg); + + for (auto & pn : panels_) + { + if (pn.widget_ptr) + pn.widget_ptr->move(r); + } + } + + void float_away(const ::nana::point& move_pos) + { + if (container_) + return; + + API::capture_window(caption_, false); + + rectangle r{ pos() + move_pos, size() }; + container_.reset(new form(host_window_, r.pare_off(-1), form::appear::bald<>())); + drawing dw(container_->handle()); + dw.draw([](paint::graphics& graph) + { + graph.rectangle(false, colors::coral); + }); + + API::set_parent_window(handle(), container_->handle()); + this->move({ 1, 1 }); + + container_->show(); + API::capture_window(caption_, true); + + notifier_->notify_float(); + } + + void dock() + { + API::capture_window(caption_, false); + API::set_parent_window(handle(), host_window_); + container_.reset(); + notifier_->notify_dock(); + } + + bool floating() const + { + return (nullptr != container_); + } + private: + window host_window_{nullptr}; + place_parts::dock_notifier_interface* notifier_{ nullptr }; + std::unique_ptr container_; + dockarea_caption caption_; + std::deque panels_; + std::unique_ptr tabbar_; + + struct moves + { + bool started{ false }; + ::nana::point start_pos; + ::nana::point start_container_pos; + }moves_; + };//class dockarea + + + //number_t is used for storing a number type variable + //such as integer, real and percent. Essentially, percent is a typo of real. + class number_t + { + public: + enum class kind{ none, integer, real, percent }; + + number_t() + : kind_(kind::none) + { + value_.integer = 0; + } + + void reset() + { + kind_ = kind::none; + value_.integer = 0; + } + + bool is_negative() const + { + switch (kind_) + { + case kind::integer: + return (value_.integer < 0); + case kind::real: + case kind::percent: + return (value_.real < 0); + default: + break; + } + return false; + } + + bool is_none() const + { + return (kind::none == kind_); + } + + bool is_not_none() const + { + return (kind::none != kind_); + } + + kind kind_of() const + { + return kind_; + } + + double get_value(int ref_percent) const + { + switch (kind_) + { + case kind::integer: + return value_.integer; + case kind::real: + return value_.real; + case kind::percent: + return value_.real * ref_percent; + default: + break; + } + return 0; + } + + int integer() const + { + if (kind::integer == kind_) + return value_.integer; + return static_cast(value_.real); + } + + double real() const + { + if (kind::integer == kind_) + return value_.integer; + return value_.real; + } + + void assign(int i) + { + kind_ = kind::integer; + value_.integer = i; + } + + void assign(double d) + { + kind_ = kind::real; + value_.real = d; + } + + void assign_percent(double d) + { + kind_ = kind::percent; + value_.real = d / 100; + } + private: + kind kind_; + union valueset + { + int integer; + double real; + }value_; + };//end class number_t + + + class margin + { + public: + margin& operator=(margin&& rhs) + { + if (this != &rhs) + { + all_edges_ = rhs.all_edges_; + margins_ = std::move(rhs.margins_); + } + return *this; + } + + void clear() + { + all_edges_ = true; + margins_.clear(); + } + + void push(const number_t& v) + { + margins_.emplace_back(v); + } + + void set_value(const number_t& v) + { + clear(); + margins_.emplace_back(v); + } + + void set_array(const std::vector& v) + { + all_edges_ = false; + margins_ = v; + } + + nana::rectangle area(const ::nana::rectangle& field_area) const + { + if (margins_.empty()) + return field_area; + + auto r = field_area; + if (all_edges_) + { + auto px = static_cast(margins_.back().get_value(static_cast(r.width))); + const auto dbl_px = static_cast(px << 1); + r.x += px; + r.width = (r.width < dbl_px ? 0 : r.width - dbl_px); + + r.y += px; + r.height = (r.height < dbl_px ? 0 : r.height - dbl_px); + } + else + { + int il{ -1 }, ir{ -1 }, it{ -1 }, ib{ -1 }; //index of four corners in margin + switch (margins_.size()) + { + case 0: break; + case 1: //top + it = 0; + break; + case 2://top,bottom and left,right + it = ib = 0; + il = ir = 1; + break; + default: + il = 3; //left + case 3: //top, right, bottom + it = 0; + ir = 1; + ib = 2; + } + + typedef decltype(r.height) px_type; + auto calc = [](px_type a, px_type b) + { + return (a > b ? a - b : 0); + }; + + if (0 == it) //top + { + auto px = static_cast(margins_[it].get_value(static_cast(field_area.height))); + r.y += px; + r.height = calc(r.height, static_cast(px)); + } + + if (-1 != ib) //bottom + { + auto px = static_cast(margins_[ib].get_value(static_cast(field_area.height))); + r.height = calc(r.height, static_cast(px)); + } + + if (-1 != il) //left + { + auto px = static_cast(margins_[il].get_value(static_cast(field_area.width))); + r.x += px; + r.width = calc(r.width, static_cast(px)); + } + + if (-1 != ir) //right + { + auto px = static_cast(margins_[ir].get_value(static_cast(field_area.width))); + r.width = calc(r.width, static_cast(px)); + } + } + return r; + } + private: + bool all_edges_ = true; + std::vector margins_; + };//end class margin + + class repeated_array + { + public: + + //A workaround for VC2013, becuase it does not generated an implicit declared move-constructor as defaulted. + repeated_array() = default; + + repeated_array(repeated_array && other) + : repeated_{ other.repeated_ }, + values_(std::move(other.values_)) + { + } + + repeated_array& operator=(repeated_array&& other) + { + if (this != &other) + { + repeated_ = other.repeated_; + other.repeated_ = false; + values_ = std::move(other.values_); + } + return *this; + } + + void assign(std::vector&& c) + { + values_ = std::move(c); + } + + bool empty() const + { + return values_.empty(); + } + + void reset() + { + repeated_ = false; + values_.clear(); + } + + void repeated() + { + repeated_ = true; + } + + void push(const number_t& n) + { + values_.emplace_back(n); + } + + number_t at(std::size_t pos) const + { + if (values_.empty()) + return{}; + + if (repeated_) + pos %= values_.size(); + else if (pos >= values_.size()) + return{}; + + return values_[pos]; + } + private: + bool repeated_ = false; + std::vector values_; + }; + }//end namespace place_parts +}//end namespace nana + +#endif //NANA_GUI_PLACE_PARTS_HPP \ No newline at end of file diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 6a64dc2d..5d4901b7 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -538,11 +538,11 @@ namespace API return nana::point{}; } - void move_window(window wd, int x, int y) + void move_window(window wd, const point& pos) { auto iwd = reinterpret_cast(wd); internal_scope_guard lock; - if(restrict::window_manager.move(iwd, x, y, false)) + if(restrict::window_manager.move(iwd, pos.x, pos.y, false)) { restrict::core_window_t* update_wd = nullptr; if (iwd->displayed() && iwd->effect.bground) @@ -1314,5 +1314,10 @@ namespace API internal_scope_guard lock; return (restrict::window_manager.available(iwd) ? iwd->flags.ignore_mouse_focus : false); } + + void at_safe_place(window wd, std::function fn) + { + restrict::window_manager.set_safe_place(reinterpret_cast(wd), std::move(fn)); + } }//end namespace API }//end namespace nana diff --git a/source/gui/widgets/categorize.cpp b/source/gui/widgets/categorize.cpp index 4351a719..92fb9743 100644 --- a/source/gui/widgets/categorize.cpp +++ b/source/gui/widgets/categorize.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 49626834..582803cc 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/source/gui/widgets/date_chooser.cpp b/source/gui/widgets/date_chooser.cpp index 7da5474c..b46b29a5 100644 --- a/source/gui/widgets/date_chooser.cpp +++ b/source/gui/widgets/date_chooser.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/source/gui/widgets/menu.cpp b/source/gui/widgets/menu.cpp index d42f2b79..fd206764 100644 --- a/source/gui/widgets/menu.cpp +++ b/source/gui/widgets/menu.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index e568fbee..29e5a181 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -2250,7 +2250,7 @@ namespace nana{ namespace widgets break; case keyboard::os_end: if (caret.y != nlines - 1) { - caret.y = nlines - 1; + caret.y = static_cast(nlines - 1); changed = true; } break; @@ -2265,7 +2265,7 @@ namespace nana{ namespace widgets }else { if (caret.y != 0) { --caret.y; - caret.x = textbase_.getline(caret.y).size(); + caret.x = static_cast(textbase_.getline(caret.y).size()); changed = true; } } @@ -2309,7 +2309,7 @@ namespace nana{ namespace widgets break; case keyboard::os_end: if (caret.x < lnsz) { - caret.x = lnsz; + caret.x = static_cast(lnsz); changed = true; } break; diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 8b82c6d0..bbaabeeb 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -97,7 +97,7 @@ namespace nana { int x = r.x + (static_cast(r.width) - 14) / 2; int y = r.y + (static_cast(r.height) - 14) / 2; - + ::nana::color clr; switch(sta) @@ -112,12 +112,14 @@ namespace nana clr = { 0xF0, 0xF0, 0xF0 }; } graph.rectangle(r, true, bgcolor_); - nana::paint::gadget::cross(graph, x, y, 14, 6, clr); + facade cross; + cross.draw(graph, {}, clr, { x, y, 14, 6 }, element_state::normal); } virtual void close(graph_reference graph, const nana::rectangle& r, state_t sta) { - nana::paint::gadget::close_16_pixels(graph, r.x + (r.width - 16) / 2, r.y + (r.height - 16) / 2, 1, colors::black); + facade x_icon; + x_icon.draw(graph, {}, colors::black, { r.x + static_cast(r.width - 16) / 2, r.y + static_cast(r.height - 16) / 2, 16, 16 }, element_state::normal); if(item_renderer::highlight == sta) graph.rectangle(r, false, {0xa0, 0xa0, 0xa0}); } @@ -140,24 +142,23 @@ namespace nana else if (!active) clr = ::nana::color{ 0x92, 0x99, 0xA4 }; - gadget::close_16_pixels(graph, r.x - (16 - r.width) / 2, r.y - (16 - r.height) / 2, 1, clr); + facade x_icon; + x_icon.draw(graph, {}, colors::black, { r.x + static_cast(r.width - 16) / 2, r.y + static_cast(r.height - 16) / 2, 16, 16 }, element_state::normal); + } virtual void back(graph_reference graph, const nana::rectangle& r, state_t sta) { - using namespace nana::paint::gadget; _m_draw_arrow(graph, r, sta, direction::west); } virtual void next(graph_reference graph, const nana::rectangle& r, state_t sta) { - using namespace nana::paint::gadget; _m_draw_arrow(graph, r, sta, direction::east); } virtual void list(graph_reference graph, const nana::rectangle& r, state_t sta) { - using namespace nana::paint::gadget; _m_draw_arrow(graph, r, sta, direction::south); } private: @@ -343,7 +344,7 @@ namespace nana { if(i < list_.size()) return at_no_bound_check(i); - throw std::out_of_range("Nana.GUI.tabbar::at() is out of range"); + throw std::out_of_range("invalid position of tabbar"); } iterator iterator_at(std::size_t pos) @@ -369,7 +370,7 @@ namespace nana { if(pos < list_.size()) return at_no_bound_check(pos); - throw std::out_of_range("Nana.GUI.tabbar::at() const is out of range"); + throw std::out_of_range("invalid position of tabbar"); } const nana::any& at_no_bound_check(std::size_t pos) const @@ -1274,8 +1275,6 @@ namespace nana #include namespace nana { - namespace ng - { namespace drawerbase { namespace tabbar_lite @@ -1285,6 +1284,7 @@ namespace nana ::std::string text; ::nana::any value; ::std::pair pos_ends; + ::nana::window attached_window{ nullptr }; item(std::string t, ::nana::any v) : text(std::move(t)), value(std::move(v)) @@ -1345,21 +1345,44 @@ namespace nana using graph_reference = ::nana::paint::graphics&; static const std::size_t npos = static_cast(-1); - void set_widget(widget& wdg) + void set_widget(::nana::tabbar_lite& wdg) { widget_ = &wdg; } - ::nana::dev::widget_traits::scheme_type & scheme() + ::nana::tabbar_lite* widget_ptr() const + { + return widget_; + } + /* + ::nana::dev::widget_traits::scheme_type & scheme() //deprecated { return API::scheme(*widget_); } + */ std::forward_list& items() { return items_; } + void show_attached_window() + { + if (indexes_.active_pos != npos) + { + auto i = items_.cbegin(); + std::advance(i, indexes_.active_pos); + API::show_window(i->attached_window, true); + + std::size_t pos = 0; + for (auto & m : items_) + { + if (pos++ != indexes_.active_pos) + API::show_window(m.attached_window, false); + } + } + } + bool track_pointer(const point& pos) { std::size_t item_pos = 0; @@ -1390,7 +1413,7 @@ namespace nana return indexes_; } private: - widget * widget_{ nullptr }; + ::nana::tabbar_lite * widget_{ nullptr }; std::forward_list items_; indexes indexes_; }; @@ -1404,7 +1427,7 @@ namespace nana { _m_calc_metrics(graph, model.items()); - auto & scheme = model.scheme(); + auto & scheme = model.widget_ptr()->scheme(); //draw background graph.rectangle(true, scheme.background); @@ -1475,14 +1498,14 @@ namespace nana delete model_; } - model* driver::get_model() + model* driver::get_model() const throw() { return model_; } void driver::attached(widget_reference wdg, graph_reference) { - model_->set_widget(wdg); + model_->set_widget(dynamic_cast(wdg)); } //Overrides drawer_trigger's method @@ -1513,12 +1536,20 @@ namespace nana void driver::mouse_down(graph_reference graph, const arg_mouse&) { auto & indexes = model_->get_indexes(); - if (indexes.hovered_pos == model_->npos) + if ((indexes.hovered_pos == model_->npos) || (indexes.active_pos == indexes.hovered_pos)) return; - indexes.active_pos = indexes.hovered_pos; - refresh(graph); - API::lazy_refresh(); + if (indexes.active_pos != indexes.hovered_pos) + { + indexes.active_pos = indexes.hovered_pos; + model_->show_attached_window(); + + refresh(graph); + API::lazy_refresh(); + + event_arg arg; + model_->widget_ptr()->events().selected.emit(arg); + } } //end class driver } @@ -1531,6 +1562,47 @@ namespace nana this->create(parent_wd, r, visible); } + //capacity + std::size_t tabbar_lite::length() const + { + auto& items = get_drawer_trigger().get_model()->items(); + internal_scope_guard lock; + return static_cast(std::distance(items.cbegin(), items.cend())); + } + + //modifiers + void tabbar_lite::attach(std::size_t pos_set, window wd) + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + for (auto & m : model->items()) + { + if (0 == pos_set--) + { + m.attached_window = wd; + model->show_attached_window(); + return; + } + } + + throw std::out_of_range("invalid position of tabbar_lite"); + } + + window tabbar_lite::attach(std::size_t pos_set) const + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + for (auto & m : model->items()) + { + if (0 == pos_set--) + return m.attached_window; + } + + throw std::out_of_range("invalid position of tabbar_lite"); + } + void tabbar_lite::push_back(std::string text, ::nana::any any) { auto & items = get_drawer_trigger().get_model()->items(); @@ -1559,6 +1631,64 @@ namespace nana items.emplace_front(std::move(text), std::move(any)); API::refresh_window(handle()); } + + std::size_t tabbar_lite::selected() const + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + return model->get_indexes().active_pos; + } + + void tabbar_lite::erase(std::size_t pos, bool close_attached) + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + const auto len = length(); + + if (len <= pos) + throw std::out_of_range("invalid position of tabbar_lite"); + + auto active_pos = model->get_indexes().active_pos; + + //selection_changed is used to determine whether the title will be updated + bool selection_changed = true; + if (pos == active_pos) + { + if (active_pos + 1 == len) + { + if (active_pos) + --active_pos; + else + active_pos = npos; + } + } + else if (pos < active_pos) + --active_pos; + else + selection_changed = false; + + model->get_indexes().active_pos = active_pos; + + auto i = model->items().cbefore_begin(); + std::advance(i, pos); + + auto attached_wd = std::next(i)->attached_window; + + model->items().erase_after(i); + + model->show_attached_window(); + API::refresh_window(handle()); + + if (close_attached && attached_wd) + API::close_window(attached_wd); + + if (selection_changed && (active_pos != npos)) + { + event_arg arg; + events().selected.emit(arg); + } + } //end class tabbar - } }//end namespace nana diff --git a/source/gui/widgets/widget.cpp b/source/gui/widgets/widget.cpp index 39a2ac57..dc1e0d58 100644 --- a/source/gui/widgets/widget.cpp +++ b/source/gui/widgets/widget.cpp @@ -305,7 +305,7 @@ namespace nana void widget::_m_move(int x, int y) { - API::move_window(handle(), x, y); + API::move_window(handle(), { x, y }); } void widget::_m_move(const rectangle& r) diff --git a/source/paint/gadget.cpp b/source/paint/gadget.cpp deleted file mode 100644 index c6da79e6..00000000 --- a/source/paint/gadget.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Graphics Gadget Implementation - * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - * @file: nana/paint/gadget.cpp - */ - -#include -#include - -namespace nana -{ -namespace paint -{ -namespace gadget -{ - void close_16_pixels(::nana::paint::graphics& graph, int x, int y, unsigned style, const ::nana::color& clr) - { - graph.set_color(clr); - if(0 == style) - { - x += 3; - y += 3; - - graph.line({ x, y }, { x + 9, y + 9 }); - graph.line({ x + 1, y }, { x + 9, y + 8 }); - graph.line({ x, y + 1 }, { x + 8, y + 9 }); - - graph.line({ x + 9, y }, { x, y + 9 }); - graph.line({ x + 8, y }, { x, y + 8 }); - graph.line({ x + 9, y + 1 }, { x + 1, y + 9 }); - } - else - { - x += 4; - y += 4; - - graph.line({ x, y }, { x + 7, y + 7 }); - graph.line({ x + 1, y }, { x + 7, y + 6 }); - graph.line({ x, y + 1 }, { x + 6, y + 7 }); - - graph.line({ x + 7, y }, { x, y + 7 }); - graph.line({ x + 6, y }, { x, y + 6 }); - graph.line({ x + 7, y + 1 }, { x + 1, y + 7 }); - } - } - - void cross(graphics& graph, int x, int y, unsigned size, unsigned thickness, const ::nana::color& clr) - { - if (thickness + 2 <= size) - { - int gap = (size - thickness) / 2; - - nana::point ps[12]; - ps[0].x = x + gap; - ps[1].x = ps[0].x + thickness - 1; - ps[1].y = ps[0].y = y; - - ps[2].x = ps[1].x; - ps[2].y = y + gap; - - ps[3].x = ps[2].x + gap; - ps[3].y = ps[2].y; - - ps[4].x = ps[3].x; - ps[4].y = ps[3].y + thickness - 1; - - ps[5].x = ps[1].x; - ps[5].y = ps[4].y; - - ps[6].x = ps[5].x; - ps[6].y = ps[5].y + gap; - - ps[7].x = x + gap; - ps[7].y = ps[6].y; - - ps[8].x = ps[7].x; - ps[8].y = ps[4].y; - - ps[9].x = x; - ps[9].y = ps[4].y; - - ps[10].x = x; - ps[10].y = y + gap; - - ps[11].x = x + gap; - ps[11].y = y + gap; - - graph.set_color(clr.blend(colors::black, true)); - - for (int i = 0; i < 11; ++i) - graph.line(ps[i], ps[i + 1]); - graph.line(ps[11], ps[0]); - - graph.set_color(clr); - graph.rectangle(rectangle{ ps[10].x + 1, ps[10].y + 1, (gap << 1) + thickness - 2, thickness - 2 }, true); - graph.rectangle(rectangle{ ps[0].x + 1, ps[0].y + 1, thickness - 2, (gap << 1) + thickness - 2 }, true); - } - } -}//end namespace gadget - -}//end namespace paint -}//end namespace nana diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index cba4b272..c6b71f21 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -845,13 +845,13 @@ namespace paint BITMAPFILEHEADER bmFileHeader = { 0 }; bmFileHeader.bfType = 0x4d42; //bmp bmFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - bmFileHeader.bfSize = bmFileHeader.bfOffBits + imageBytes; + bmFileHeader.bfSize = bmFileHeader.bfOffBits + static_cast(imageBytes); HANDLE hFile = ::CreateFileW(static_cast(::nana::charset(file_utf8, ::nana::unicode::utf8)).data(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwWrite = 0; ::WriteFile(hFile, &bmFileHeader, sizeof(BITMAPFILEHEADER), &dwWrite, nullptr); ::WriteFile(hFile, &bmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER), &dwWrite, nullptr); - ::WriteFile(hFile, pData, imageBytes, &dwWrite, nullptr); + ::WriteFile(hFile, pData, static_cast(imageBytes), &dwWrite, nullptr); ::CloseHandle(hFile); ::DeleteObject(hBmp); @@ -874,6 +874,27 @@ namespace paint handle_->set_text_color(col); } + ::nana::color graphics::palette(bool for_text) const + { + if (handle_) + return static_cast(for_text ? handle_->get_text_color() : handle_->get_color()); + + return{}; + } + + graphics& graphics::palette(bool for_text, const ::nana::color& clr) + { + if (handle_) + { + if (for_text) + handle_->set_text_color(clr); + else + handle_->set_color(clr); + } + + return *this; + } + unsigned graphics::bidi_string(const nana::point& pos, const char_t * str, std::size_t len) { auto moved_pos = pos; diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 9fbcf8f6..eaa87349 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -118,11 +118,12 @@ namespace nana { graphics & graph; int x, endpos; - ::nana::color fgcolor; + //::nana::color fgcolor; //deprecated unsigned omitted_pixels; nana::unicode_bidi bidi; std::vector reordered; + /* //deprecated draw_string_omitted(graphics& graph, int x, int endpos, const ::nana::color& fgcolor, bool omitted) : graph(graph), x(x), endpos(endpos), fgcolor(fgcolor) { @@ -132,6 +133,7 @@ namespace nana else this->endpos = x; } + */ draw_string_omitted(graphics& graph, int x, int endpos, bool omitted) : graph(graph), x(x), endpos(endpos) @@ -169,7 +171,8 @@ namespace nana nana::paint::graphics dum_graph({ r.width, r.height }); dum_graph.bitblt(r, graph, pos); - dum_graph.set_text_color(fgcolor); + //dum_graph.set_text_color(fgcolor); //deprecated + dum_graph.set_text_color(graph.palette(true)); dum_graph.string({}, i.begin, len); r.x = pos.x;