From 74bb9cd27242b9320f99ff4d2b50c3051576cc14 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 8 Feb 2022 16:53:51 +0800 Subject: ... --- include/cru/common/Base.h | 98 +++++ include/cru/common/Base.hpp | 98 ----- include/cru/common/Bitmask.h | 42 ++ include/cru/common/Bitmask.hpp | 42 -- include/cru/common/ClonablePtr.h | 216 ++++++++++ include/cru/common/ClonablePtr.hpp | 216 ---------- include/cru/common/Event.h | 281 +++++++++++++ include/cru/common/Event.hpp | 281 ------------- include/cru/common/Exception.h | 32 ++ include/cru/common/Exception.hpp | 32 -- include/cru/common/Format.h | 143 +++++++ include/cru/common/Format.hpp | 143 ------- include/cru/common/HandlerRegistry.h | 87 ++++ include/cru/common/HandlerRegistry.hpp | 87 ---- include/cru/common/Logger.h | 114 ++++++ include/cru/common/Logger.hpp | 114 ------ include/cru/common/PreConfig.h | 16 + include/cru/common/PreConfig.hpp | 16 - include/cru/common/PropertyTree.h | 63 +++ include/cru/common/PropertyTree.hpp | 63 --- include/cru/common/Range.h | 43 ++ include/cru/common/Range.hpp | 43 -- include/cru/common/SelfResolvable.h | 69 ++++ include/cru/common/SelfResolvable.hpp | 69 ---- include/cru/common/String.h | 436 +++++++++++++++++++++ include/cru/common/String.hpp | 436 --------------------- include/cru/common/StringUtil.h | 223 +++++++++++ include/cru/common/StringUtil.hpp | 223 ----------- include/cru/common/io/FileStream.h | 13 + include/cru/common/io/FileStream.hpp | 13 - include/cru/common/io/MemoryStream.h | 44 +++ include/cru/common/io/MemoryStream.hpp | 44 --- include/cru/common/io/OpenFileFlag.h | 18 + include/cru/common/io/OpenFileFlag.hpp | 18 - include/cru/common/io/Resource.h | 8 + include/cru/common/io/Resource.hpp | 8 - include/cru/common/io/Stream.h | 48 +++ include/cru/common/io/Stream.hpp | 48 --- include/cru/common/platform/Exception.h | 15 + include/cru/common/platform/Exception.hpp | 15 - include/cru/common/platform/osx/Convert.h | 17 + include/cru/common/platform/osx/Convert.hpp | 17 - include/cru/common/platform/osx/Exception.h | 14 + include/cru/common/platform/osx/Exception.hpp | 14 - include/cru/common/platform/unix/ErrnoException.h | 28 ++ .../cru/common/platform/unix/ErrnoException.hpp | 28 -- include/cru/common/platform/unix/UnixFileStream.h | 46 +++ .../cru/common/platform/unix/UnixFileStream.hpp | 46 --- include/cru/common/platform/win/ComAutoInit.h | 21 + include/cru/common/platform/win/ComAutoInit.hpp | 21 - include/cru/common/platform/win/Exception.h | 56 +++ include/cru/common/platform/win/Exception.hpp | 56 --- include/cru/common/platform/win/StreamConvert.h | 14 + include/cru/common/platform/win/StreamConvert.hpp | 14 - include/cru/common/platform/win/Win32FileStream.h | 54 +++ .../cru/common/platform/win/Win32FileStream.hpp | 54 --- include/cru/common/platform/win/WinPreConfig.h | 13 + include/cru/common/platform/win/WinPreConfig.hpp | 13 - include/cru/osx/Convert.h | 2 + include/cru/osx/Convert.hpp | 2 - include/cru/osx/Exception.h | 3 + include/cru/osx/Exception.hpp | 3 - include/cru/osx/Resource.h | 13 + include/cru/osx/Resource.hpp | 13 - include/cru/osx/graphics/quartz/Brush.h | 47 +++ include/cru/osx/graphics/quartz/Brush.hpp | 47 --- include/cru/osx/graphics/quartz/Convert.h | 23 ++ include/cru/osx/graphics/quartz/Convert.hpp | 23 -- include/cru/osx/graphics/quartz/Factory.h | 35 ++ include/cru/osx/graphics/quartz/Factory.hpp | 35 -- include/cru/osx/graphics/quartz/Font.h | 25 ++ include/cru/osx/graphics/quartz/Font.hpp | 25 -- include/cru/osx/graphics/quartz/Geometry.h | 48 +++ include/cru/osx/graphics/quartz/Geometry.hpp | 48 --- include/cru/osx/graphics/quartz/Image.h | 32 ++ include/cru/osx/graphics/quartz/Image.hpp | 32 -- include/cru/osx/graphics/quartz/ImageFactory.h | 19 + include/cru/osx/graphics/quartz/ImageFactory.hpp | 19 - include/cru/osx/graphics/quartz/Painter.h | 83 ++++ include/cru/osx/graphics/quartz/Painter.hpp | 83 ---- include/cru/osx/graphics/quartz/Resource.h | 25 ++ include/cru/osx/graphics/quartz/Resource.hpp | 25 -- include/cru/osx/graphics/quartz/TextLayout.h | 95 +++++ include/cru/osx/graphics/quartz/TextLayout.hpp | 95 ----- include/cru/osx/gui/Clipboard.h | 31 ++ include/cru/osx/gui/Clipboard.hpp | 31 -- include/cru/osx/gui/Cursor.h | 43 ++ include/cru/osx/gui/Cursor.hpp | 43 -- include/cru/osx/gui/InputMethod.h | 56 +++ include/cru/osx/gui/InputMethod.hpp | 56 --- include/cru/osx/gui/Keyboard.h | 7 + include/cru/osx/gui/Keyboard.hpp | 7 - include/cru/osx/gui/Menu.h | 67 ++++ include/cru/osx/gui/Menu.hpp | 67 ---- include/cru/osx/gui/Resource.h | 24 ++ include/cru/osx/gui/Resource.hpp | 24 -- include/cru/osx/gui/UiApplication.h | 64 +++ include/cru/osx/gui/UiApplication.hpp | 64 --- include/cru/osx/gui/Window.h | 90 +++++ include/cru/osx/gui/Window.hpp | 90 ----- include/cru/parse/Base.h | 11 + include/cru/parse/Base.hpp | 11 - include/cru/parse/Grammar.h | 62 +++ include/cru/parse/Grammar.hpp | 62 --- include/cru/parse/Nonterminal.h | 14 + include/cru/parse/Nonterminal.hpp | 14 - include/cru/parse/ParsingAlgorithm.h | 22 ++ include/cru/parse/ParsingAlgorithm.hpp | 22 -- include/cru/parse/ParsingAlgorithmContext.h | 28 ++ include/cru/parse/ParsingAlgorithmContext.hpp | 28 -- include/cru/parse/ParsingContext.h | 22 ++ include/cru/parse/ParsingContext.hpp | 22 -- include/cru/parse/ParsingTreeNode.h | 33 ++ include/cru/parse/ParsingTreeNode.hpp | 33 -- include/cru/parse/Production.h | 43 ++ include/cru/parse/Production.hpp | 43 -- include/cru/parse/RecursiveDescentAlgorithm.h | 19 + include/cru/parse/RecursiveDescentAlgorithm.hpp | 19 - .../cru/parse/RecursiveDescentAlgorithmContext.h | 22 ++ .../cru/parse/RecursiveDescentAlgorithmContext.hpp | 22 -- include/cru/parse/Symbol.h | 30 ++ include/cru/parse/Symbol.hpp | 30 -- include/cru/parse/Terminal.h | 14 + include/cru/parse/Terminal.hpp | 14 - include/cru/parse/Token.h | 0 include/cru/parse/Token.hpp | 0 include/cru/parse/TokenType.h | 24 ++ include/cru/parse/TokenType.hpp | 24 -- include/cru/platform/Base.h | 11 + include/cru/platform/Base.hpp | 11 - include/cru/platform/Check.h | 41 ++ include/cru/platform/Check.hpp | 41 -- include/cru/platform/Color.h | 265 +++++++++++++ include/cru/platform/Color.hpp | 265 ------------- include/cru/platform/Exception.h | 34 ++ include/cru/platform/Exception.hpp | 34 -- include/cru/platform/GraphicsBase.h | 287 ++++++++++++++ include/cru/platform/GraphicsBase.hpp | 287 -------------- include/cru/platform/Matrix.h | 110 ++++++ include/cru/platform/Matrix.hpp | 110 ------ include/cru/platform/Resource.h | 17 + include/cru/platform/Resource.hpp | 17 - include/cru/platform/bootstrap/Bootstrap.h | 17 + include/cru/platform/bootstrap/Bootstrap.hpp | 17 - include/cru/platform/graphics/Base.h | 37 ++ include/cru/platform/graphics/Base.hpp | 37 -- include/cru/platform/graphics/Brush.h | 11 + include/cru/platform/graphics/Brush.hpp | 11 - include/cru/platform/graphics/Factory.h | 32 ++ include/cru/platform/graphics/Factory.hpp | 32 -- include/cru/platform/graphics/Font.h | 8 + include/cru/platform/graphics/Font.hpp | 8 - include/cru/platform/graphics/Geometry.h | 20 + include/cru/platform/graphics/Geometry.hpp | 20 - include/cru/platform/graphics/Image.h | 10 + include/cru/platform/graphics/Image.hpp | 10 - include/cru/platform/graphics/ImageFactory.h | 11 + include/cru/platform/graphics/ImageFactory.hpp | 11 - include/cru/platform/graphics/NullPainter.h | 84 ++++ include/cru/platform/graphics/NullPainter.hpp | 84 ---- include/cru/platform/graphics/Painter.h | 42 ++ include/cru/platform/graphics/Painter.hpp | 42 -- include/cru/platform/graphics/Resource.h | 10 + include/cru/platform/graphics/Resource.hpp | 10 - include/cru/platform/graphics/TextLayout.h | 33 ++ include/cru/platform/graphics/TextLayout.hpp | 33 -- include/cru/platform/graphics/util/Painter.h | 18 + include/cru/platform/graphics/util/Painter.hpp | 18 - include/cru/platform/gui/Base.h | 37 ++ include/cru/platform/gui/Base.hpp | 37 -- include/cru/platform/gui/Clipboard.h | 9 + include/cru/platform/gui/Clipboard.hpp | 9 - include/cru/platform/gui/Cursor.h | 16 + include/cru/platform/gui/Cursor.hpp | 16 - include/cru/platform/gui/DebugFlags.h | 8 + include/cru/platform/gui/DebugFlags.hpp | 8 - include/cru/platform/gui/InputMethod.h | 55 +++ include/cru/platform/gui/InputMethod.hpp | 55 --- include/cru/platform/gui/Keyboard.h | 140 +++++++ include/cru/platform/gui/Keyboard.hpp | 140 ------- include/cru/platform/gui/Menu.h | 32 ++ include/cru/platform/gui/Menu.hpp | 32 -- include/cru/platform/gui/SaveOpenDialogOptions.h | 81 ++++ include/cru/platform/gui/SaveOpenDialogOptions.hpp | 81 ---- include/cru/platform/gui/TimerHelper.h | 69 ++++ include/cru/platform/gui/TimerHelper.hpp | 69 ---- include/cru/platform/gui/UiApplication.h | 70 ++++ include/cru/platform/gui/UiApplication.hpp | 70 ---- include/cru/platform/gui/Window.h | 112 ++++++ include/cru/platform/gui/Window.hpp | 112 ------ include/cru/toml/Base.h | 11 + include/cru/toml/Base.hpp | 11 - include/cru/toml/TomlDocument.h | 57 +++ include/cru/toml/TomlDocument.hpp | 57 --- include/cru/toml/TomlParser.h | 36 ++ include/cru/toml/TomlParser.hpp | 36 -- include/cru/ui/Base.h | 152 +++++++ include/cru/ui/Base.hpp | 152 ------- include/cru/ui/DebugFlags.h | 10 + include/cru/ui/DebugFlags.hpp | 10 - include/cru/ui/ThemeManager.h | 92 +++++ include/cru/ui/ThemeManager.hpp | 92 ----- include/cru/ui/components/Component.h | 19 + include/cru/ui/components/Component.hpp | 19 - include/cru/ui/components/Menu.h | 107 +++++ include/cru/ui/components/Menu.hpp | 107 ----- include/cru/ui/controls/Base.h | 4 + include/cru/ui/controls/Base.hpp | 4 - include/cru/ui/controls/Button.h | 53 +++ include/cru/ui/controls/Button.hpp | 53 --- include/cru/ui/controls/Container.h | 25 ++ include/cru/ui/controls/Container.hpp | 25 -- include/cru/ui/controls/ContentControl.h | 38 ++ include/cru/ui/controls/ContentControl.hpp | 38 -- include/cru/ui/controls/Control.h | 157 ++++++++ include/cru/ui/controls/Control.hpp | 157 -------- include/cru/ui/controls/FlexLayout.h | 40 ++ include/cru/ui/controls/FlexLayout.hpp | 40 -- include/cru/ui/controls/IBorderControl.h | 10 + include/cru/ui/controls/IBorderControl.hpp | 10 - include/cru/ui/controls/IClickableControl.h | 12 + include/cru/ui/controls/IClickableControl.hpp | 12 - include/cru/ui/controls/LayoutControl.h | 37 ++ include/cru/ui/controls/LayoutControl.hpp | 37 -- include/cru/ui/controls/NoChildControl.h | 20 + include/cru/ui/controls/NoChildControl.hpp | 20 - include/cru/ui/controls/Popup.h | 26 ++ include/cru/ui/controls/Popup.hpp | 26 -- include/cru/ui/controls/RootControl.h | 39 ++ include/cru/ui/controls/RootControl.hpp | 39 -- include/cru/ui/controls/ScrollView.h | 32 ++ include/cru/ui/controls/ScrollView.hpp | 32 -- include/cru/ui/controls/StackLayout.h | 31 ++ include/cru/ui/controls/StackLayout.hpp | 31 -- include/cru/ui/controls/TextBlock.h | 44 +++ include/cru/ui/controls/TextBlock.hpp | 44 --- include/cru/ui/controls/TextBox.h | 46 +++ include/cru/ui/controls/TextBox.hpp | 46 --- include/cru/ui/controls/TextHostControlService.h | 219 +++++++++++ include/cru/ui/controls/TextHostControlService.hpp | 219 ----------- include/cru/ui/controls/Window.h | 27 ++ include/cru/ui/controls/Window.hpp | 27 -- include/cru/ui/events/FocusChangeEventArgs.h | 23 ++ include/cru/ui/events/FocusChangeEventArgs.hpp | 23 -- include/cru/ui/events/KeyEventArgs.h | 29 ++ include/cru/ui/events/KeyEventArgs.hpp | 29 -- include/cru/ui/events/MouseButtonEventArgs.h | 35 ++ include/cru/ui/events/MouseButtonEventArgs.hpp | 35 -- include/cru/ui/events/MouseEventArgs.h | 27 ++ include/cru/ui/events/MouseEventArgs.hpp | 27 -- include/cru/ui/events/MouseWheelEventArgs.h | 29 ++ include/cru/ui/events/MouseWheelEventArgs.hpp | 29 -- include/cru/ui/events/PaintEventArgs.h | 25 ++ include/cru/ui/events/PaintEventArgs.hpp | 25 -- include/cru/ui/events/RoutedEvent.h | 39 ++ include/cru/ui/events/RoutedEvent.hpp | 39 -- include/cru/ui/events/UiEventArgs.h | 28 ++ include/cru/ui/events/UiEventArgs.hpp | 28 -- include/cru/ui/events/UiEvents.h | 10 + include/cru/ui/events/UiEvents.hpp | 10 - include/cru/ui/helper/ClickDetector.h | 87 ++++ include/cru/ui/helper/ClickDetector.hpp | 87 ---- include/cru/ui/helper/ShortcutHub.h | 142 +++++++ include/cru/ui/helper/ShortcutHub.hpp | 142 ------- include/cru/ui/host/LayoutPaintCycler.h | 40 ++ include/cru/ui/host/LayoutPaintCycler.hpp | 40 -- include/cru/ui/host/WindowHost.h | 164 ++++++++ include/cru/ui/host/WindowHost.hpp | 164 -------- include/cru/ui/mapper/BorderStyleMapper.h | 20 + include/cru/ui/mapper/BorderStyleMapper.hpp | 20 - include/cru/ui/mapper/BrushMapper.h | 20 + include/cru/ui/mapper/BrushMapper.hpp | 20 - include/cru/ui/mapper/ColorMapper.h | 19 + include/cru/ui/mapper/ColorMapper.hpp | 19 - include/cru/ui/mapper/CornerRadiusMapper.h | 17 + include/cru/ui/mapper/CornerRadiusMapper.hpp | 17 - include/cru/ui/mapper/CursorMapper.h | 21 + include/cru/ui/mapper/CursorMapper.hpp | 21 - include/cru/ui/mapper/FontMapper.h | 19 + include/cru/ui/mapper/FontMapper.hpp | 19 - include/cru/ui/mapper/Mapper.h | 92 +++++ include/cru/ui/mapper/Mapper.hpp | 92 ----- include/cru/ui/mapper/MapperRegistry.h | 58 +++ include/cru/ui/mapper/MapperRegistry.hpp | 58 --- include/cru/ui/mapper/PointMapper.h | 18 + include/cru/ui/mapper/PointMapper.hpp | 18 - include/cru/ui/mapper/SizeMapper.h | 18 + include/cru/ui/mapper/SizeMapper.hpp | 18 - include/cru/ui/mapper/ThicknessMapper.h | 22 ++ include/cru/ui/mapper/ThicknessMapper.hpp | 22 -- include/cru/ui/mapper/style/AndConditionMapper.h | 25 ++ include/cru/ui/mapper/style/AndConditionMapper.hpp | 25 -- include/cru/ui/mapper/style/BorderStylerMapper.h | 28 ++ include/cru/ui/mapper/style/BorderStylerMapper.hpp | 28 -- .../ui/mapper/style/ClickStateConditionMapper.h | 26 ++ .../ui/mapper/style/ClickStateConditionMapper.hpp | 26 -- include/cru/ui/mapper/style/CursorStylerMapper.h | 26 ++ include/cru/ui/mapper/style/CursorStylerMapper.hpp | 26 -- include/cru/ui/mapper/style/FocusConditionMapper.h | 26 ++ .../cru/ui/mapper/style/FocusConditionMapper.hpp | 26 -- include/cru/ui/mapper/style/HoverConditionMapper.h | 26 ++ .../cru/ui/mapper/style/HoverConditionMapper.hpp | 26 -- include/cru/ui/mapper/style/IConditionMapper.h | 17 + include/cru/ui/mapper/style/IConditionMapper.hpp | 17 - include/cru/ui/mapper/style/IStylerMapper.h | 17 + include/cru/ui/mapper/style/IStylerMapper.hpp | 17 - include/cru/ui/mapper/style/NoConditionMapper.h | 29 ++ include/cru/ui/mapper/style/NoConditionMapper.hpp | 29 -- include/cru/ui/mapper/style/OrConditionMapper.h | 25 ++ include/cru/ui/mapper/style/OrConditionMapper.hpp | 25 -- include/cru/ui/mapper/style/StyleRuleMapper.h | 20 + include/cru/ui/mapper/style/StyleRuleMapper.hpp | 20 - include/cru/ui/mapper/style/StyleRuleSetMapper.h | 21 + include/cru/ui/mapper/style/StyleRuleSetMapper.hpp | 21 - include/cru/ui/render/Base.h | 12 + include/cru/ui/render/Base.hpp | 12 - include/cru/ui/render/BorderRenderObject.h | 109 ++++++ include/cru/ui/render/BorderRenderObject.hpp | 109 ------ include/cru/ui/render/CanvasRenderObject.h | 36 ++ include/cru/ui/render/CanvasRenderObject.hpp | 36 -- include/cru/ui/render/FlexLayoutRenderObject.h | 120 ++++++ include/cru/ui/render/FlexLayoutRenderObject.hpp | 120 ------ include/cru/ui/render/LayoutHelper.h | 14 + include/cru/ui/render/LayoutHelper.hpp | 14 - include/cru/ui/render/LayoutRenderObject.h | 86 ++++ include/cru/ui/render/LayoutRenderObject.hpp | 86 ---- include/cru/ui/render/MeasureRequirement.h | 251 ++++++++++++ include/cru/ui/render/MeasureRequirement.hpp | 251 ------------ include/cru/ui/render/RenderObject.h | 240 ++++++++++++ include/cru/ui/render/RenderObject.hpp | 240 ------------ include/cru/ui/render/ScrollBar.h | 255 ++++++++++++ include/cru/ui/render/ScrollBar.hpp | 255 ------------ include/cru/ui/render/ScrollRenderObject.h | 98 +++++ include/cru/ui/render/ScrollRenderObject.hpp | 98 ----- include/cru/ui/render/StackLayoutRenderObject.h | 57 +++ include/cru/ui/render/StackLayoutRenderObject.hpp | 57 --- include/cru/ui/render/TextRenderObject.h | 121 ++++++ include/cru/ui/render/TextRenderObject.hpp | 121 ------ include/cru/ui/style/ApplyBorderStyleInfo.h | 30 ++ include/cru/ui/style/ApplyBorderStyleInfo.hpp | 30 -- include/cru/ui/style/Condition.h | 133 +++++++ include/cru/ui/style/Condition.hpp | 133 ------- include/cru/ui/style/StyleRule.h | 49 +++ include/cru/ui/style/StyleRule.hpp | 49 --- include/cru/ui/style/StyleRuleSet.h | 80 ++++ include/cru/ui/style/StyleRuleSet.hpp | 80 ---- include/cru/ui/style/Styler.h | 90 +++++ include/cru/ui/style/Styler.hpp | 90 ----- include/cru/win/Base.h | 13 + include/cru/win/Base.hpp | 13 - include/cru/win/DebugLogger.h | 24 ++ include/cru/win/DebugLogger.hpp | 24 -- include/cru/win/Exception.h | 3 + include/cru/win/Exception.hpp | 3 - include/cru/win/StdOutLogger.h | 23 ++ include/cru/win/StdOutLogger.hpp | 23 -- include/cru/win/WinPreConfig.h | 2 + include/cru/win/WinPreConfig.hpp | 2 - include/cru/win/graphics/direct/Base.h | 18 + include/cru/win/graphics/direct/Base.hpp | 18 - include/cru/win/graphics/direct/Brush.h | 40 ++ include/cru/win/graphics/direct/Brush.hpp | 40 -- include/cru/win/graphics/direct/ComResource.h | 11 + include/cru/win/graphics/direct/ComResource.hpp | 11 - include/cru/win/graphics/direct/ConvertUtil.h | 107 +++++ include/cru/win/graphics/direct/ConvertUtil.hpp | 107 ----- include/cru/win/graphics/direct/Exception.h | 7 + include/cru/win/graphics/direct/Exception.hpp | 7 - include/cru/win/graphics/direct/Factory.h | 68 ++++ include/cru/win/graphics/direct/Factory.hpp | 68 ---- include/cru/win/graphics/direct/Font.h | 34 ++ include/cru/win/graphics/direct/Font.hpp | 34 -- include/cru/win/graphics/direct/Geometry.h | 59 +++ include/cru/win/graphics/direct/Geometry.hpp | 59 --- include/cru/win/graphics/direct/Image.h | 31 ++ include/cru/win/graphics/direct/Image.hpp | 31 -- include/cru/win/graphics/direct/ImageFactory.h | 27 ++ include/cru/win/graphics/direct/ImageFactory.hpp | 27 -- include/cru/win/graphics/direct/Painter.h | 75 ++++ include/cru/win/graphics/direct/Painter.hpp | 75 ---- include/cru/win/graphics/direct/Resource.h | 52 +++ include/cru/win/graphics/direct/Resource.hpp | 52 --- include/cru/win/graphics/direct/TextLayout.h | 63 +++ include/cru/win/graphics/direct/TextLayout.hpp | 63 --- include/cru/win/graphics/direct/WindowPainter.h | 22 ++ include/cru/win/graphics/direct/WindowPainter.hpp | 22 -- .../cru/win/graphics/direct/WindowRenderTarget.h | 43 ++ .../cru/win/graphics/direct/WindowRenderTarget.hpp | 43 -- include/cru/win/gui/Base.h | 27 ++ include/cru/win/gui/Base.hpp | 27 -- include/cru/win/gui/Clipboard.h | 24 ++ include/cru/win/gui/Clipboard.hpp | 24 -- include/cru/win/gui/Cursor.h | 51 +++ include/cru/win/gui/Cursor.hpp | 51 --- include/cru/win/gui/Exception.h | 7 + include/cru/win/gui/Exception.hpp | 7 - include/cru/win/gui/GodWindow.h | 39 ++ include/cru/win/gui/GodWindow.hpp | 39 -- include/cru/win/gui/InputMethod.h | 88 +++++ include/cru/win/gui/InputMethod.hpp | 88 ----- include/cru/win/gui/Keyboard.h | 9 + include/cru/win/gui/Keyboard.hpp | 9 - include/cru/win/gui/Resource.h | 24 ++ include/cru/win/gui/Resource.hpp | 24 -- include/cru/win/gui/UiApplication.h | 87 ++++ include/cru/win/gui/UiApplication.hpp | 87 ---- include/cru/win/gui/Window.h | 217 ++++++++++ include/cru/win/gui/Window.hpp | 217 ---------- include/cru/win/gui/WindowClass.h | 24 ++ include/cru/win/gui/WindowClass.hpp | 24 -- include/cru/win/gui/WindowNativeMessageEventArgs.h | 40 ++ .../cru/win/gui/WindowNativeMessageEventArgs.hpp | 40 -- include/cru/xml/Base.h | 11 + include/cru/xml/Base.hpp | 11 - include/cru/xml/XmlNode.h | 135 +++++++ include/cru/xml/XmlNode.hpp | 135 ------- include/cru/xml/XmlParser.h | 47 +++ include/cru/xml/XmlParser.hpp | 47 --- 418 files changed, 11140 insertions(+), 11140 deletions(-) create mode 100644 include/cru/common/Base.h delete mode 100644 include/cru/common/Base.hpp create mode 100644 include/cru/common/Bitmask.h delete mode 100644 include/cru/common/Bitmask.hpp create mode 100644 include/cru/common/ClonablePtr.h delete mode 100644 include/cru/common/ClonablePtr.hpp create mode 100644 include/cru/common/Event.h delete mode 100644 include/cru/common/Event.hpp create mode 100644 include/cru/common/Exception.h delete mode 100644 include/cru/common/Exception.hpp create mode 100644 include/cru/common/Format.h delete mode 100644 include/cru/common/Format.hpp create mode 100644 include/cru/common/HandlerRegistry.h delete mode 100644 include/cru/common/HandlerRegistry.hpp create mode 100644 include/cru/common/Logger.h delete mode 100644 include/cru/common/Logger.hpp create mode 100644 include/cru/common/PreConfig.h delete mode 100644 include/cru/common/PreConfig.hpp create mode 100644 include/cru/common/PropertyTree.h delete mode 100644 include/cru/common/PropertyTree.hpp create mode 100644 include/cru/common/Range.h delete mode 100644 include/cru/common/Range.hpp create mode 100644 include/cru/common/SelfResolvable.h delete mode 100644 include/cru/common/SelfResolvable.hpp create mode 100644 include/cru/common/String.h delete mode 100644 include/cru/common/String.hpp create mode 100644 include/cru/common/StringUtil.h delete mode 100644 include/cru/common/StringUtil.hpp create mode 100644 include/cru/common/io/FileStream.h delete mode 100644 include/cru/common/io/FileStream.hpp create mode 100644 include/cru/common/io/MemoryStream.h delete mode 100644 include/cru/common/io/MemoryStream.hpp create mode 100644 include/cru/common/io/OpenFileFlag.h delete mode 100644 include/cru/common/io/OpenFileFlag.hpp create mode 100644 include/cru/common/io/Resource.h delete mode 100644 include/cru/common/io/Resource.hpp create mode 100644 include/cru/common/io/Stream.h delete mode 100644 include/cru/common/io/Stream.hpp create mode 100644 include/cru/common/platform/Exception.h delete mode 100644 include/cru/common/platform/Exception.hpp create mode 100644 include/cru/common/platform/osx/Convert.h delete mode 100644 include/cru/common/platform/osx/Convert.hpp create mode 100644 include/cru/common/platform/osx/Exception.h delete mode 100644 include/cru/common/platform/osx/Exception.hpp create mode 100644 include/cru/common/platform/unix/ErrnoException.h delete mode 100644 include/cru/common/platform/unix/ErrnoException.hpp create mode 100644 include/cru/common/platform/unix/UnixFileStream.h delete mode 100644 include/cru/common/platform/unix/UnixFileStream.hpp create mode 100644 include/cru/common/platform/win/ComAutoInit.h delete mode 100644 include/cru/common/platform/win/ComAutoInit.hpp create mode 100644 include/cru/common/platform/win/Exception.h delete mode 100644 include/cru/common/platform/win/Exception.hpp create mode 100644 include/cru/common/platform/win/StreamConvert.h delete mode 100644 include/cru/common/platform/win/StreamConvert.hpp create mode 100644 include/cru/common/platform/win/Win32FileStream.h delete mode 100644 include/cru/common/platform/win/Win32FileStream.hpp create mode 100644 include/cru/common/platform/win/WinPreConfig.h delete mode 100644 include/cru/common/platform/win/WinPreConfig.hpp create mode 100644 include/cru/osx/Convert.h delete mode 100644 include/cru/osx/Convert.hpp create mode 100644 include/cru/osx/Exception.h delete mode 100644 include/cru/osx/Exception.hpp create mode 100644 include/cru/osx/Resource.h delete mode 100644 include/cru/osx/Resource.hpp create mode 100644 include/cru/osx/graphics/quartz/Brush.h delete mode 100644 include/cru/osx/graphics/quartz/Brush.hpp create mode 100644 include/cru/osx/graphics/quartz/Convert.h delete mode 100644 include/cru/osx/graphics/quartz/Convert.hpp create mode 100644 include/cru/osx/graphics/quartz/Factory.h delete mode 100644 include/cru/osx/graphics/quartz/Factory.hpp create mode 100644 include/cru/osx/graphics/quartz/Font.h delete mode 100644 include/cru/osx/graphics/quartz/Font.hpp create mode 100644 include/cru/osx/graphics/quartz/Geometry.h delete mode 100644 include/cru/osx/graphics/quartz/Geometry.hpp create mode 100644 include/cru/osx/graphics/quartz/Image.h delete mode 100644 include/cru/osx/graphics/quartz/Image.hpp create mode 100644 include/cru/osx/graphics/quartz/ImageFactory.h delete mode 100644 include/cru/osx/graphics/quartz/ImageFactory.hpp create mode 100644 include/cru/osx/graphics/quartz/Painter.h delete mode 100644 include/cru/osx/graphics/quartz/Painter.hpp create mode 100644 include/cru/osx/graphics/quartz/Resource.h delete mode 100644 include/cru/osx/graphics/quartz/Resource.hpp create mode 100644 include/cru/osx/graphics/quartz/TextLayout.h delete mode 100644 include/cru/osx/graphics/quartz/TextLayout.hpp create mode 100644 include/cru/osx/gui/Clipboard.h delete mode 100644 include/cru/osx/gui/Clipboard.hpp create mode 100644 include/cru/osx/gui/Cursor.h delete mode 100644 include/cru/osx/gui/Cursor.hpp create mode 100644 include/cru/osx/gui/InputMethod.h delete mode 100644 include/cru/osx/gui/InputMethod.hpp create mode 100644 include/cru/osx/gui/Keyboard.h delete mode 100644 include/cru/osx/gui/Keyboard.hpp create mode 100644 include/cru/osx/gui/Menu.h delete mode 100644 include/cru/osx/gui/Menu.hpp create mode 100644 include/cru/osx/gui/Resource.h delete mode 100644 include/cru/osx/gui/Resource.hpp create mode 100644 include/cru/osx/gui/UiApplication.h delete mode 100644 include/cru/osx/gui/UiApplication.hpp create mode 100644 include/cru/osx/gui/Window.h delete mode 100644 include/cru/osx/gui/Window.hpp create mode 100644 include/cru/parse/Base.h delete mode 100644 include/cru/parse/Base.hpp create mode 100644 include/cru/parse/Grammar.h delete mode 100644 include/cru/parse/Grammar.hpp create mode 100644 include/cru/parse/Nonterminal.h delete mode 100644 include/cru/parse/Nonterminal.hpp create mode 100644 include/cru/parse/ParsingAlgorithm.h delete mode 100644 include/cru/parse/ParsingAlgorithm.hpp create mode 100644 include/cru/parse/ParsingAlgorithmContext.h delete mode 100644 include/cru/parse/ParsingAlgorithmContext.hpp create mode 100644 include/cru/parse/ParsingContext.h delete mode 100644 include/cru/parse/ParsingContext.hpp create mode 100644 include/cru/parse/ParsingTreeNode.h delete mode 100644 include/cru/parse/ParsingTreeNode.hpp create mode 100644 include/cru/parse/Production.h delete mode 100644 include/cru/parse/Production.hpp create mode 100644 include/cru/parse/RecursiveDescentAlgorithm.h delete mode 100644 include/cru/parse/RecursiveDescentAlgorithm.hpp create mode 100644 include/cru/parse/RecursiveDescentAlgorithmContext.h delete mode 100644 include/cru/parse/RecursiveDescentAlgorithmContext.hpp create mode 100644 include/cru/parse/Symbol.h delete mode 100644 include/cru/parse/Symbol.hpp create mode 100644 include/cru/parse/Terminal.h delete mode 100644 include/cru/parse/Terminal.hpp create mode 100644 include/cru/parse/Token.h delete mode 100644 include/cru/parse/Token.hpp create mode 100644 include/cru/parse/TokenType.h delete mode 100644 include/cru/parse/TokenType.hpp create mode 100644 include/cru/platform/Base.h delete mode 100644 include/cru/platform/Base.hpp create mode 100644 include/cru/platform/Check.h delete mode 100644 include/cru/platform/Check.hpp create mode 100644 include/cru/platform/Color.h delete mode 100644 include/cru/platform/Color.hpp create mode 100644 include/cru/platform/Exception.h delete mode 100644 include/cru/platform/Exception.hpp create mode 100644 include/cru/platform/GraphicsBase.h delete mode 100644 include/cru/platform/GraphicsBase.hpp create mode 100644 include/cru/platform/Matrix.h delete mode 100644 include/cru/platform/Matrix.hpp create mode 100644 include/cru/platform/Resource.h delete mode 100644 include/cru/platform/Resource.hpp create mode 100644 include/cru/platform/bootstrap/Bootstrap.h delete mode 100644 include/cru/platform/bootstrap/Bootstrap.hpp create mode 100644 include/cru/platform/graphics/Base.h delete mode 100644 include/cru/platform/graphics/Base.hpp create mode 100644 include/cru/platform/graphics/Brush.h delete mode 100644 include/cru/platform/graphics/Brush.hpp create mode 100644 include/cru/platform/graphics/Factory.h delete mode 100644 include/cru/platform/graphics/Factory.hpp create mode 100644 include/cru/platform/graphics/Font.h delete mode 100644 include/cru/platform/graphics/Font.hpp create mode 100644 include/cru/platform/graphics/Geometry.h delete mode 100644 include/cru/platform/graphics/Geometry.hpp create mode 100644 include/cru/platform/graphics/Image.h delete mode 100644 include/cru/platform/graphics/Image.hpp create mode 100644 include/cru/platform/graphics/ImageFactory.h delete mode 100644 include/cru/platform/graphics/ImageFactory.hpp create mode 100644 include/cru/platform/graphics/NullPainter.h delete mode 100644 include/cru/platform/graphics/NullPainter.hpp create mode 100644 include/cru/platform/graphics/Painter.h delete mode 100644 include/cru/platform/graphics/Painter.hpp create mode 100644 include/cru/platform/graphics/Resource.h delete mode 100644 include/cru/platform/graphics/Resource.hpp create mode 100644 include/cru/platform/graphics/TextLayout.h delete mode 100644 include/cru/platform/graphics/TextLayout.hpp create mode 100644 include/cru/platform/graphics/util/Painter.h delete mode 100644 include/cru/platform/graphics/util/Painter.hpp create mode 100644 include/cru/platform/gui/Base.h delete mode 100644 include/cru/platform/gui/Base.hpp create mode 100644 include/cru/platform/gui/Clipboard.h delete mode 100644 include/cru/platform/gui/Clipboard.hpp create mode 100644 include/cru/platform/gui/Cursor.h delete mode 100644 include/cru/platform/gui/Cursor.hpp create mode 100644 include/cru/platform/gui/DebugFlags.h delete mode 100644 include/cru/platform/gui/DebugFlags.hpp create mode 100644 include/cru/platform/gui/InputMethod.h delete mode 100644 include/cru/platform/gui/InputMethod.hpp create mode 100644 include/cru/platform/gui/Keyboard.h delete mode 100644 include/cru/platform/gui/Keyboard.hpp create mode 100644 include/cru/platform/gui/Menu.h delete mode 100644 include/cru/platform/gui/Menu.hpp create mode 100644 include/cru/platform/gui/SaveOpenDialogOptions.h delete mode 100644 include/cru/platform/gui/SaveOpenDialogOptions.hpp create mode 100644 include/cru/platform/gui/TimerHelper.h delete mode 100644 include/cru/platform/gui/TimerHelper.hpp create mode 100644 include/cru/platform/gui/UiApplication.h delete mode 100644 include/cru/platform/gui/UiApplication.hpp create mode 100644 include/cru/platform/gui/Window.h delete mode 100644 include/cru/platform/gui/Window.hpp create mode 100644 include/cru/toml/Base.h delete mode 100644 include/cru/toml/Base.hpp create mode 100644 include/cru/toml/TomlDocument.h delete mode 100644 include/cru/toml/TomlDocument.hpp create mode 100644 include/cru/toml/TomlParser.h delete mode 100644 include/cru/toml/TomlParser.hpp create mode 100644 include/cru/ui/Base.h delete mode 100644 include/cru/ui/Base.hpp create mode 100644 include/cru/ui/DebugFlags.h delete mode 100644 include/cru/ui/DebugFlags.hpp create mode 100644 include/cru/ui/ThemeManager.h delete mode 100644 include/cru/ui/ThemeManager.hpp create mode 100644 include/cru/ui/components/Component.h delete mode 100644 include/cru/ui/components/Component.hpp create mode 100644 include/cru/ui/components/Menu.h delete mode 100644 include/cru/ui/components/Menu.hpp create mode 100644 include/cru/ui/controls/Base.h delete mode 100644 include/cru/ui/controls/Base.hpp create mode 100644 include/cru/ui/controls/Button.h delete mode 100644 include/cru/ui/controls/Button.hpp create mode 100644 include/cru/ui/controls/Container.h delete mode 100644 include/cru/ui/controls/Container.hpp create mode 100644 include/cru/ui/controls/ContentControl.h delete mode 100644 include/cru/ui/controls/ContentControl.hpp create mode 100644 include/cru/ui/controls/Control.h delete mode 100644 include/cru/ui/controls/Control.hpp create mode 100644 include/cru/ui/controls/FlexLayout.h delete mode 100644 include/cru/ui/controls/FlexLayout.hpp create mode 100644 include/cru/ui/controls/IBorderControl.h delete mode 100644 include/cru/ui/controls/IBorderControl.hpp create mode 100644 include/cru/ui/controls/IClickableControl.h delete mode 100644 include/cru/ui/controls/IClickableControl.hpp create mode 100644 include/cru/ui/controls/LayoutControl.h delete mode 100644 include/cru/ui/controls/LayoutControl.hpp create mode 100644 include/cru/ui/controls/NoChildControl.h delete mode 100644 include/cru/ui/controls/NoChildControl.hpp create mode 100644 include/cru/ui/controls/Popup.h delete mode 100644 include/cru/ui/controls/Popup.hpp create mode 100644 include/cru/ui/controls/RootControl.h delete mode 100644 include/cru/ui/controls/RootControl.hpp create mode 100644 include/cru/ui/controls/ScrollView.h delete mode 100644 include/cru/ui/controls/ScrollView.hpp create mode 100644 include/cru/ui/controls/StackLayout.h delete mode 100644 include/cru/ui/controls/StackLayout.hpp create mode 100644 include/cru/ui/controls/TextBlock.h delete mode 100644 include/cru/ui/controls/TextBlock.hpp create mode 100644 include/cru/ui/controls/TextBox.h delete mode 100644 include/cru/ui/controls/TextBox.hpp create mode 100644 include/cru/ui/controls/TextHostControlService.h delete mode 100644 include/cru/ui/controls/TextHostControlService.hpp create mode 100644 include/cru/ui/controls/Window.h delete mode 100644 include/cru/ui/controls/Window.hpp create mode 100644 include/cru/ui/events/FocusChangeEventArgs.h delete mode 100644 include/cru/ui/events/FocusChangeEventArgs.hpp create mode 100644 include/cru/ui/events/KeyEventArgs.h delete mode 100644 include/cru/ui/events/KeyEventArgs.hpp create mode 100644 include/cru/ui/events/MouseButtonEventArgs.h delete mode 100644 include/cru/ui/events/MouseButtonEventArgs.hpp create mode 100644 include/cru/ui/events/MouseEventArgs.h delete mode 100644 include/cru/ui/events/MouseEventArgs.hpp create mode 100644 include/cru/ui/events/MouseWheelEventArgs.h delete mode 100644 include/cru/ui/events/MouseWheelEventArgs.hpp create mode 100644 include/cru/ui/events/PaintEventArgs.h delete mode 100644 include/cru/ui/events/PaintEventArgs.hpp create mode 100644 include/cru/ui/events/RoutedEvent.h delete mode 100644 include/cru/ui/events/RoutedEvent.hpp create mode 100644 include/cru/ui/events/UiEventArgs.h delete mode 100644 include/cru/ui/events/UiEventArgs.hpp create mode 100644 include/cru/ui/events/UiEvents.h delete mode 100644 include/cru/ui/events/UiEvents.hpp create mode 100644 include/cru/ui/helper/ClickDetector.h delete mode 100644 include/cru/ui/helper/ClickDetector.hpp create mode 100644 include/cru/ui/helper/ShortcutHub.h delete mode 100644 include/cru/ui/helper/ShortcutHub.hpp create mode 100644 include/cru/ui/host/LayoutPaintCycler.h delete mode 100644 include/cru/ui/host/LayoutPaintCycler.hpp create mode 100644 include/cru/ui/host/WindowHost.h delete mode 100644 include/cru/ui/host/WindowHost.hpp create mode 100644 include/cru/ui/mapper/BorderStyleMapper.h delete mode 100644 include/cru/ui/mapper/BorderStyleMapper.hpp create mode 100644 include/cru/ui/mapper/BrushMapper.h delete mode 100644 include/cru/ui/mapper/BrushMapper.hpp create mode 100644 include/cru/ui/mapper/ColorMapper.h delete mode 100644 include/cru/ui/mapper/ColorMapper.hpp create mode 100644 include/cru/ui/mapper/CornerRadiusMapper.h delete mode 100644 include/cru/ui/mapper/CornerRadiusMapper.hpp create mode 100644 include/cru/ui/mapper/CursorMapper.h delete mode 100644 include/cru/ui/mapper/CursorMapper.hpp create mode 100644 include/cru/ui/mapper/FontMapper.h delete mode 100644 include/cru/ui/mapper/FontMapper.hpp create mode 100644 include/cru/ui/mapper/Mapper.h delete mode 100644 include/cru/ui/mapper/Mapper.hpp create mode 100644 include/cru/ui/mapper/MapperRegistry.h delete mode 100644 include/cru/ui/mapper/MapperRegistry.hpp create mode 100644 include/cru/ui/mapper/PointMapper.h delete mode 100644 include/cru/ui/mapper/PointMapper.hpp create mode 100644 include/cru/ui/mapper/SizeMapper.h delete mode 100644 include/cru/ui/mapper/SizeMapper.hpp create mode 100644 include/cru/ui/mapper/ThicknessMapper.h delete mode 100644 include/cru/ui/mapper/ThicknessMapper.hpp create mode 100644 include/cru/ui/mapper/style/AndConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/AndConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/BorderStylerMapper.h delete mode 100644 include/cru/ui/mapper/style/BorderStylerMapper.hpp create mode 100644 include/cru/ui/mapper/style/ClickStateConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/ClickStateConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/CursorStylerMapper.h delete mode 100644 include/cru/ui/mapper/style/CursorStylerMapper.hpp create mode 100644 include/cru/ui/mapper/style/FocusConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/FocusConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/HoverConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/HoverConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/IConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/IConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/IStylerMapper.h delete mode 100644 include/cru/ui/mapper/style/IStylerMapper.hpp create mode 100644 include/cru/ui/mapper/style/NoConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/NoConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/OrConditionMapper.h delete mode 100644 include/cru/ui/mapper/style/OrConditionMapper.hpp create mode 100644 include/cru/ui/mapper/style/StyleRuleMapper.h delete mode 100644 include/cru/ui/mapper/style/StyleRuleMapper.hpp create mode 100644 include/cru/ui/mapper/style/StyleRuleSetMapper.h delete mode 100644 include/cru/ui/mapper/style/StyleRuleSetMapper.hpp create mode 100644 include/cru/ui/render/Base.h delete mode 100644 include/cru/ui/render/Base.hpp create mode 100644 include/cru/ui/render/BorderRenderObject.h delete mode 100644 include/cru/ui/render/BorderRenderObject.hpp create mode 100644 include/cru/ui/render/CanvasRenderObject.h delete mode 100644 include/cru/ui/render/CanvasRenderObject.hpp create mode 100644 include/cru/ui/render/FlexLayoutRenderObject.h delete mode 100644 include/cru/ui/render/FlexLayoutRenderObject.hpp create mode 100644 include/cru/ui/render/LayoutHelper.h delete mode 100644 include/cru/ui/render/LayoutHelper.hpp create mode 100644 include/cru/ui/render/LayoutRenderObject.h delete mode 100644 include/cru/ui/render/LayoutRenderObject.hpp create mode 100644 include/cru/ui/render/MeasureRequirement.h delete mode 100644 include/cru/ui/render/MeasureRequirement.hpp create mode 100644 include/cru/ui/render/RenderObject.h delete mode 100644 include/cru/ui/render/RenderObject.hpp create mode 100644 include/cru/ui/render/ScrollBar.h delete mode 100644 include/cru/ui/render/ScrollBar.hpp create mode 100644 include/cru/ui/render/ScrollRenderObject.h delete mode 100644 include/cru/ui/render/ScrollRenderObject.hpp create mode 100644 include/cru/ui/render/StackLayoutRenderObject.h delete mode 100644 include/cru/ui/render/StackLayoutRenderObject.hpp create mode 100644 include/cru/ui/render/TextRenderObject.h delete mode 100644 include/cru/ui/render/TextRenderObject.hpp create mode 100644 include/cru/ui/style/ApplyBorderStyleInfo.h delete mode 100644 include/cru/ui/style/ApplyBorderStyleInfo.hpp create mode 100644 include/cru/ui/style/Condition.h delete mode 100644 include/cru/ui/style/Condition.hpp create mode 100644 include/cru/ui/style/StyleRule.h delete mode 100644 include/cru/ui/style/StyleRule.hpp create mode 100644 include/cru/ui/style/StyleRuleSet.h delete mode 100644 include/cru/ui/style/StyleRuleSet.hpp create mode 100644 include/cru/ui/style/Styler.h delete mode 100644 include/cru/ui/style/Styler.hpp create mode 100644 include/cru/win/Base.h delete mode 100644 include/cru/win/Base.hpp create mode 100644 include/cru/win/DebugLogger.h delete mode 100644 include/cru/win/DebugLogger.hpp create mode 100644 include/cru/win/Exception.h delete mode 100644 include/cru/win/Exception.hpp create mode 100644 include/cru/win/StdOutLogger.h delete mode 100644 include/cru/win/StdOutLogger.hpp create mode 100644 include/cru/win/WinPreConfig.h delete mode 100644 include/cru/win/WinPreConfig.hpp create mode 100644 include/cru/win/graphics/direct/Base.h delete mode 100644 include/cru/win/graphics/direct/Base.hpp create mode 100644 include/cru/win/graphics/direct/Brush.h delete mode 100644 include/cru/win/graphics/direct/Brush.hpp create mode 100644 include/cru/win/graphics/direct/ComResource.h delete mode 100644 include/cru/win/graphics/direct/ComResource.hpp create mode 100644 include/cru/win/graphics/direct/ConvertUtil.h delete mode 100644 include/cru/win/graphics/direct/ConvertUtil.hpp create mode 100644 include/cru/win/graphics/direct/Exception.h delete mode 100644 include/cru/win/graphics/direct/Exception.hpp create mode 100644 include/cru/win/graphics/direct/Factory.h delete mode 100644 include/cru/win/graphics/direct/Factory.hpp create mode 100644 include/cru/win/graphics/direct/Font.h delete mode 100644 include/cru/win/graphics/direct/Font.hpp create mode 100644 include/cru/win/graphics/direct/Geometry.h delete mode 100644 include/cru/win/graphics/direct/Geometry.hpp create mode 100644 include/cru/win/graphics/direct/Image.h delete mode 100644 include/cru/win/graphics/direct/Image.hpp create mode 100644 include/cru/win/graphics/direct/ImageFactory.h delete mode 100644 include/cru/win/graphics/direct/ImageFactory.hpp create mode 100644 include/cru/win/graphics/direct/Painter.h delete mode 100644 include/cru/win/graphics/direct/Painter.hpp create mode 100644 include/cru/win/graphics/direct/Resource.h delete mode 100644 include/cru/win/graphics/direct/Resource.hpp create mode 100644 include/cru/win/graphics/direct/TextLayout.h delete mode 100644 include/cru/win/graphics/direct/TextLayout.hpp create mode 100644 include/cru/win/graphics/direct/WindowPainter.h delete mode 100644 include/cru/win/graphics/direct/WindowPainter.hpp create mode 100644 include/cru/win/graphics/direct/WindowRenderTarget.h delete mode 100644 include/cru/win/graphics/direct/WindowRenderTarget.hpp create mode 100644 include/cru/win/gui/Base.h delete mode 100644 include/cru/win/gui/Base.hpp create mode 100644 include/cru/win/gui/Clipboard.h delete mode 100644 include/cru/win/gui/Clipboard.hpp create mode 100644 include/cru/win/gui/Cursor.h delete mode 100644 include/cru/win/gui/Cursor.hpp create mode 100644 include/cru/win/gui/Exception.h delete mode 100644 include/cru/win/gui/Exception.hpp create mode 100644 include/cru/win/gui/GodWindow.h delete mode 100644 include/cru/win/gui/GodWindow.hpp create mode 100644 include/cru/win/gui/InputMethod.h delete mode 100644 include/cru/win/gui/InputMethod.hpp create mode 100644 include/cru/win/gui/Keyboard.h delete mode 100644 include/cru/win/gui/Keyboard.hpp create mode 100644 include/cru/win/gui/Resource.h delete mode 100644 include/cru/win/gui/Resource.hpp create mode 100644 include/cru/win/gui/UiApplication.h delete mode 100644 include/cru/win/gui/UiApplication.hpp create mode 100644 include/cru/win/gui/Window.h delete mode 100644 include/cru/win/gui/Window.hpp create mode 100644 include/cru/win/gui/WindowClass.h delete mode 100644 include/cru/win/gui/WindowClass.hpp create mode 100644 include/cru/win/gui/WindowNativeMessageEventArgs.h delete mode 100644 include/cru/win/gui/WindowNativeMessageEventArgs.hpp create mode 100644 include/cru/xml/Base.h delete mode 100644 include/cru/xml/Base.hpp create mode 100644 include/cru/xml/XmlNode.h delete mode 100644 include/cru/xml/XmlNode.hpp create mode 100644 include/cru/xml/XmlParser.h delete mode 100644 include/cru/xml/XmlParser.hpp (limited to 'include') diff --git a/include/cru/common/Base.h b/include/cru/common/Base.h new file mode 100644 index 00000000..4d4d1f5f --- /dev/null +++ b/include/cru/common/Base.h @@ -0,0 +1,98 @@ +#pragma once +#include "PreConfig.h" + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_BASE_EXPORT_API +#define CRU_BASE_API __declspec(dllexport) +#else +#define CRU_BASE_API __declspec(dllimport) +#endif +#else +#define CRU_BASE_API +#endif + +#include + +#define CRU_UNUSED(entity) static_cast(entity); + +#define CRU__CONCAT(a, b) a##b +#define CRU_MAKE_UNICODE_LITERAL(str) CRU__CONCAT(u, #str) + +#define CRU_DEFAULT_COPY(classname) \ + classname(const classname&) = default; \ + classname& operator=(const classname&) = default; + +#define CRU_DEFAULT_MOVE(classname) \ + classname(classname&&) = default; \ + classname& operator=(classname&&) = default; + +#define CRU_DELETE_COPY(classname) \ + classname(const classname&) = delete; \ + classname& operator=(const classname&) = delete; + +#define CRU_DELETE_MOVE(classname) \ + classname(classname&&) = delete; \ + classname& operator=(classname&&) = delete; + +#define CRU_DEFAULT_DESTRUCTOR(classname) ~classname() = default; + +#define CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(classname) \ + classname() = default; \ + ~classname() = default; + +#define CRU_DEFINE_COMPARE_OPERATORS(classname) \ + inline bool operator==(const classname& left, const classname& right) { \ + return left.Compare(right) == 0; \ + } \ + \ + inline bool operator!=(const classname& left, const classname& right) { \ + return left.Compare(right) != 0; \ + } \ + \ + inline bool operator<(const classname& left, const classname& right) { \ + return left.Compare(right) < 0; \ + } \ + \ + inline bool operator<=(const classname& left, const classname& right) { \ + return left.Compare(right) <= 0; \ + } \ + \ + inline bool operator>(const classname& left, const classname& right) { \ + return left.Compare(right) > 0; \ + } \ + \ + inline bool operator>=(const classname& left, const classname& right) { \ + return left.Compare(right) >= 0; \ + } + +namespace cru { +class CRU_BASE_API Object { + public: + Object() = default; + CRU_DEFAULT_COPY(Object) + CRU_DEFAULT_MOVE(Object) + virtual ~Object() = default; +}; + +struct CRU_BASE_API Interface { + Interface() = default; + CRU_DELETE_COPY(Interface) + CRU_DELETE_MOVE(Interface) + virtual ~Interface() = default; +}; + +[[noreturn]] void CRU_BASE_API UnreachableCode(); + +using Index = gsl::index; + +// https://www.boost.org/doc/libs/1_54_0/doc/html/hash/reference.html#boost.hash_combine +template +inline void hash_combine(std::size_t& s, const T& v) { + std::hash h; + s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); +} + +#define CRU_DEFINE_CLASS_LOG_TAG(tag) \ + private: \ + constexpr static StringView log_tag = tag; +} // namespace cru diff --git a/include/cru/common/Base.hpp b/include/cru/common/Base.hpp deleted file mode 100644 index bab4f733..00000000 --- a/include/cru/common/Base.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include "PreConfig.hpp" - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_BASE_EXPORT_API -#define CRU_BASE_API __declspec(dllexport) -#else -#define CRU_BASE_API __declspec(dllimport) -#endif -#else -#define CRU_BASE_API -#endif - -#include - -#define CRU_UNUSED(entity) static_cast(entity); - -#define CRU__CONCAT(a, b) a##b -#define CRU_MAKE_UNICODE_LITERAL(str) CRU__CONCAT(u, #str) - -#define CRU_DEFAULT_COPY(classname) \ - classname(const classname&) = default; \ - classname& operator=(const classname&) = default; - -#define CRU_DEFAULT_MOVE(classname) \ - classname(classname&&) = default; \ - classname& operator=(classname&&) = default; - -#define CRU_DELETE_COPY(classname) \ - classname(const classname&) = delete; \ - classname& operator=(const classname&) = delete; - -#define CRU_DELETE_MOVE(classname) \ - classname(classname&&) = delete; \ - classname& operator=(classname&&) = delete; - -#define CRU_DEFAULT_DESTRUCTOR(classname) ~classname() = default; - -#define CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(classname) \ - classname() = default; \ - ~classname() = default; - -#define CRU_DEFINE_COMPARE_OPERATORS(classname) \ - inline bool operator==(const classname& left, const classname& right) { \ - return left.Compare(right) == 0; \ - } \ - \ - inline bool operator!=(const classname& left, const classname& right) { \ - return left.Compare(right) != 0; \ - } \ - \ - inline bool operator<(const classname& left, const classname& right) { \ - return left.Compare(right) < 0; \ - } \ - \ - inline bool operator<=(const classname& left, const classname& right) { \ - return left.Compare(right) <= 0; \ - } \ - \ - inline bool operator>(const classname& left, const classname& right) { \ - return left.Compare(right) > 0; \ - } \ - \ - inline bool operator>=(const classname& left, const classname& right) { \ - return left.Compare(right) >= 0; \ - } - -namespace cru { -class CRU_BASE_API Object { - public: - Object() = default; - CRU_DEFAULT_COPY(Object) - CRU_DEFAULT_MOVE(Object) - virtual ~Object() = default; -}; - -struct CRU_BASE_API Interface { - Interface() = default; - CRU_DELETE_COPY(Interface) - CRU_DELETE_MOVE(Interface) - virtual ~Interface() = default; -}; - -[[noreturn]] void CRU_BASE_API UnreachableCode(); - -using Index = gsl::index; - -// https://www.boost.org/doc/libs/1_54_0/doc/html/hash/reference.html#boost.hash_combine -template -inline void hash_combine(std::size_t& s, const T& v) { - std::hash h; - s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); -} - -#define CRU_DEFINE_CLASS_LOG_TAG(tag) \ - private: \ - constexpr static StringView log_tag = tag; -} // namespace cru diff --git a/include/cru/common/Bitmask.h b/include/cru/common/Bitmask.h new file mode 100644 index 00000000..bd6a8309 --- /dev/null +++ b/include/cru/common/Bitmask.h @@ -0,0 +1,42 @@ +#pragma once +#include "Base.h" + +namespace cru { +template +struct Bitmask final { + using Underlying = TUnderlying; + + constexpr Bitmask() : value(0) {} + constexpr explicit Bitmask(TUnderlying value) : value(value) {} + + CRU_DEFAULT_COPY(Bitmask) + CRU_DEFAULT_MOVE(Bitmask) + + ~Bitmask() = default; + + Bitmask operator|(Bitmask rhs) const { return Bitmask(value | rhs.value); } + Bitmask operator&(Bitmask rhs) const { return Bitmask(value & rhs.value); } + Bitmask operator^(Bitmask rhs) const { return Bitmask(value ^ rhs.value); } + Bitmask operator~() const { return Bitmask(~value); } + Bitmask& operator|=(Bitmask rhs) { + value |= rhs.value; + return *this; + } + Bitmask& operator&=(Bitmask rhs) { + value &= rhs.value; + return *this; + } + Bitmask& operator^=(Bitmask rhs) { + value ^= rhs.value; + return *this; + } + + bool operator==(Bitmask rhs) const { return this->value == rhs.value; } + bool operator!=(Bitmask rhs) const { return this->value != rhs.value; } + + explicit operator TUnderlying() const { return value; } + operator bool() const { return value != 0; } + + TUnderlying value; +}; +} // namespace cru diff --git a/include/cru/common/Bitmask.hpp b/include/cru/common/Bitmask.hpp deleted file mode 100644 index c1b6443a..00000000 --- a/include/cru/common/Bitmask.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru { -template -struct Bitmask final { - using Underlying = TUnderlying; - - constexpr Bitmask() : value(0) {} - constexpr explicit Bitmask(TUnderlying value) : value(value) {} - - CRU_DEFAULT_COPY(Bitmask) - CRU_DEFAULT_MOVE(Bitmask) - - ~Bitmask() = default; - - Bitmask operator|(Bitmask rhs) const { return Bitmask(value | rhs.value); } - Bitmask operator&(Bitmask rhs) const { return Bitmask(value & rhs.value); } - Bitmask operator^(Bitmask rhs) const { return Bitmask(value ^ rhs.value); } - Bitmask operator~() const { return Bitmask(~value); } - Bitmask& operator|=(Bitmask rhs) { - value |= rhs.value; - return *this; - } - Bitmask& operator&=(Bitmask rhs) { - value &= rhs.value; - return *this; - } - Bitmask& operator^=(Bitmask rhs) { - value ^= rhs.value; - return *this; - } - - bool operator==(Bitmask rhs) const { return this->value == rhs.value; } - bool operator!=(Bitmask rhs) const { return this->value != rhs.value; } - - explicit operator TUnderlying() const { return value; } - operator bool() const { return value != 0; } - - TUnderlying value; -}; -} // namespace cru diff --git a/include/cru/common/ClonablePtr.h b/include/cru/common/ClonablePtr.h new file mode 100644 index 00000000..39b5b454 --- /dev/null +++ b/include/cru/common/ClonablePtr.h @@ -0,0 +1,216 @@ +#pragma once + +#include +#include +#include +#include + +namespace cru { +template +class ClonablePtr { + template + friend class ClonablePtr; + + public: + using element_type = typename std::unique_ptr::element_type; + using pointer = typename std::unique_ptr::pointer; + + ClonablePtr() = default; + ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} + explicit ClonablePtr(pointer p) noexcept : ptr_(p) {} + ClonablePtr(std::unique_ptr&& p) noexcept + : ptr_(std::move(p)) {} + template ::pointer, pointer>, + int> = 0> + ClonablePtr(std::unique_ptr&& p) : ptr_(std::move(p)) {} + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + ClonablePtr(ClonablePtr&& other) = default; + template ::pointer, pointer>, + int> = 0> + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + template ::pointer, pointer>, + int> = 0> + ClonablePtr(ClonablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {} + ClonablePtr& operator=(std::nullptr_t) noexcept { + ptr_ = nullptr; + return *this; + } + ClonablePtr& operator=(std::unique_ptr&& other) noexcept { + ptr_ = std::move(other); + return *this; + } + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(std::unique_ptr&& p) noexcept { + ptr_ = std::move(p); + return *this; + } + ClonablePtr& operator=(const ClonablePtr& other) { + if (this != &other) { + ptr_ = std::unique_ptr(other.ptr_->Clone()); + } + return *this; + } + ClonablePtr& operator=(ClonablePtr&& other) = default; + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(const ClonablePtr& other) noexcept { + if (this != &other) { + ptr_ = std::unique_ptr(other.ptr_->Clone()); + } + return *this; + } + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(ClonablePtr&& other) noexcept { + ptr_ = std::move(other.ptr_); + } + + ~ClonablePtr() = default; + + public: + pointer release() noexcept { return ptr_.release(); } + void reset(pointer p = pointer()) noexcept { ptr_.reset(p); } + void swap(ClonablePtr& other) noexcept { ptr_.swap(other.ptr_); } + + public: + pointer get() const noexcept { return ptr_.get(); } + + operator bool() const noexcept { return ptr_; } + + element_type& operator*() const noexcept { return *ptr_; } + pointer operator->() const noexcept { return ptr_.get(); } + + int Compare(const ClonablePtr& other) const noexcept { + if (ptr_ == other.ptr_) { + return 0; + } else if (ptr_ < other.ptr_) { + return -1; + } else { + return 1; + } + } + + int Compare(nullptr_t) const noexcept { return ptr_ ? 1 : 0; } + + private: + std::unique_ptr ptr_; +}; + +template +void swap(ClonablePtr& left, ClonablePtr& right) noexcept { + left.swap(right); +} + +template +bool operator==(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) == 0; +} + +template +bool operator!=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) != 0; +} + +template +bool operator<(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) < 0; +} + +template +bool operator<=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) <= 0; +} + +template +bool operator>(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) > 0; +} + +template +bool operator>=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) >= 0; +} + +template +bool operator==(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) == 0; +} + +template +bool operator!=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) != 0; +} + +template +bool operator<(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) < 0; +} + +template +bool operator<=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) <= 0; +} + +template +bool operator>(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) > 0; +} + +template +bool operator>=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) >= 0; +} + +template +bool operator==(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) == 0; +} + +template +bool operator!=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) != 0; +} + +template +bool operator<(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) > 0; +} + +template +bool operator<=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) >= 0; +} + +template +bool operator>(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) < 0; +} + +template +bool operator>=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) <= 0; +} + +} // namespace cru + +namespace std { +template +struct hash> { + std::size_t operator()(const cru::ClonablePtr& p) const { + return std::hash::pointer>(p.get()); + } +}; +} // namespace std diff --git a/include/cru/common/ClonablePtr.hpp b/include/cru/common/ClonablePtr.hpp deleted file mode 100644 index 39b5b454..00000000 --- a/include/cru/common/ClonablePtr.hpp +++ /dev/null @@ -1,216 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace cru { -template -class ClonablePtr { - template - friend class ClonablePtr; - - public: - using element_type = typename std::unique_ptr::element_type; - using pointer = typename std::unique_ptr::pointer; - - ClonablePtr() = default; - ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} - explicit ClonablePtr(pointer p) noexcept : ptr_(p) {} - ClonablePtr(std::unique_ptr&& p) noexcept - : ptr_(std::move(p)) {} - template ::pointer, pointer>, - int> = 0> - ClonablePtr(std::unique_ptr&& p) : ptr_(std::move(p)) {} - ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} - ClonablePtr(ClonablePtr&& other) = default; - template ::pointer, pointer>, - int> = 0> - ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} - template ::pointer, pointer>, - int> = 0> - ClonablePtr(ClonablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {} - ClonablePtr& operator=(std::nullptr_t) noexcept { - ptr_ = nullptr; - return *this; - } - ClonablePtr& operator=(std::unique_ptr&& other) noexcept { - ptr_ = std::move(other); - return *this; - } - template ::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(std::unique_ptr&& p) noexcept { - ptr_ = std::move(p); - return *this; - } - ClonablePtr& operator=(const ClonablePtr& other) { - if (this != &other) { - ptr_ = std::unique_ptr(other.ptr_->Clone()); - } - return *this; - } - ClonablePtr& operator=(ClonablePtr&& other) = default; - template ::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(const ClonablePtr& other) noexcept { - if (this != &other) { - ptr_ = std::unique_ptr(other.ptr_->Clone()); - } - return *this; - } - template ::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(ClonablePtr&& other) noexcept { - ptr_ = std::move(other.ptr_); - } - - ~ClonablePtr() = default; - - public: - pointer release() noexcept { return ptr_.release(); } - void reset(pointer p = pointer()) noexcept { ptr_.reset(p); } - void swap(ClonablePtr& other) noexcept { ptr_.swap(other.ptr_); } - - public: - pointer get() const noexcept { return ptr_.get(); } - - operator bool() const noexcept { return ptr_; } - - element_type& operator*() const noexcept { return *ptr_; } - pointer operator->() const noexcept { return ptr_.get(); } - - int Compare(const ClonablePtr& other) const noexcept { - if (ptr_ == other.ptr_) { - return 0; - } else if (ptr_ < other.ptr_) { - return -1; - } else { - return 1; - } - } - - int Compare(nullptr_t) const noexcept { return ptr_ ? 1 : 0; } - - private: - std::unique_ptr ptr_; -}; - -template -void swap(ClonablePtr& left, ClonablePtr& right) noexcept { - left.swap(right); -} - -template -bool operator==(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) == 0; -} - -template -bool operator!=(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) != 0; -} - -template -bool operator<(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) < 0; -} - -template -bool operator<=(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) <= 0; -} - -template -bool operator>(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) > 0; -} - -template -bool operator>=(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) >= 0; -} - -template -bool operator==(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) == 0; -} - -template -bool operator!=(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) != 0; -} - -template -bool operator<(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) < 0; -} - -template -bool operator<=(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) <= 0; -} - -template -bool operator>(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) > 0; -} - -template -bool operator>=(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) >= 0; -} - -template -bool operator==(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) == 0; -} - -template -bool operator!=(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) != 0; -} - -template -bool operator<(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) > 0; -} - -template -bool operator<=(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) >= 0; -} - -template -bool operator>(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) < 0; -} - -template -bool operator>=(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) <= 0; -} - -} // namespace cru - -namespace std { -template -struct hash> { - std::size_t operator()(const cru::ClonablePtr& p) const { - return std::hash::pointer>(p.get()); - } -}; -} // namespace std diff --git a/include/cru/common/Event.h b/include/cru/common/Event.h new file mode 100644 index 00000000..564afc40 --- /dev/null +++ b/include/cru/common/Event.h @@ -0,0 +1,281 @@ +#pragma once +#include "Base.h" + +#include "SelfResolvable.h" + +#include +#include +#include +#include +#include +#include + +namespace cru { +class EventRevoker; + +namespace details { +template +inline constexpr bool always_false_v = false; + +// Base class of all Event. +// It erases event args types and provides a +// unified form to create event revoker and +// revoke(remove) handler. +class EventBase : public SelfResolvable { + friend EventRevoker; + + protected: + using EventHandlerToken = long; + + EventBase() {} + CRU_DELETE_COPY(EventBase) + CRU_DEFAULT_MOVE(EventBase) + virtual ~EventBase() = default; + + // Remove the handler with the given token. If the token + // corresponds to no handler (which might have be revoked + // before), then nothing will be done. + virtual void RemoveHandler(EventHandlerToken token) = 0; + + // Create a revoker with the given token. + inline EventRevoker CreateRevoker(EventHandlerToken token); +}; +} // namespace details + +// A non-copyable and movable event revoker. +// Call function call operator to revoke the handler. +class EventRevoker { + friend details::EventBase; + + private: + EventRevoker(ObjectResolver&& resolver, + details::EventBase::EventHandlerToken token) + : resolver_(std::move(resolver)), token_(token) {} + + public: + EventRevoker(const EventRevoker& other) = default; + EventRevoker(EventRevoker&& other) = default; + EventRevoker& operator=(const EventRevoker& other) = default; + EventRevoker& operator=(EventRevoker&& other) = default; + ~EventRevoker() = default; + + // Revoke the registered handler. If the event has already + // been destroyed, then nothing will be done. If one of the + // copies calls this, then other copies's calls will have no + // effect. (They have the same token.) + void operator()() const { + if (const auto event = resolver_.Resolve()) { + event->RemoveHandler(token_); + } + } + + private: + ObjectResolver resolver_; + details::EventBase::EventHandlerToken token_; +}; + +inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { + return EventRevoker(CreateResolver(), token); +} + +// int -> int +// Point -> const Point& +// int& -> int& +template +using DeducedEventArgs = std::conditional_t< + std::is_lvalue_reference_v, TRaw, + std::conditional_t, TRaw, const TRaw&>>; + +struct IBaseEvent { + protected: + IBaseEvent() = default; + CRU_DELETE_COPY(IBaseEvent) + CRU_DEFAULT_MOVE(IBaseEvent) + ~IBaseEvent() = default; // Note that user can't destroy a Event via IEvent. + // So destructor should be protected. + + using SpyOnlyHandler = std::function; + + public: + virtual EventRevoker AddSpyOnlyHandler(SpyOnlyHandler handler) = 0; +}; + +// Provides an interface of event. +// IEvent only allow to add handler but not to raise the event. You may +// want to create an Event object and expose IEvent only so users won't +// be able to emit the event. +template +struct IEvent : virtual IBaseEvent { + public: + using EventArgs = DeducedEventArgs; + using EventHandler = std::function; + using ShortCircuitHandler = std::function; + + protected: + IEvent() = default; + CRU_DELETE_COPY(IEvent) + CRU_DEFAULT_MOVE(IEvent) + ~IEvent() = default; // Note that user can't destroy a Event via IEvent. So + // destructor should be protected. + + public: + virtual EventRevoker AddHandler(EventHandler handler) = 0; + virtual EventRevoker AddShortCircuitHandler(ShortCircuitHandler handler) = 0; + virtual EventRevoker PrependShortCircuitHandler( + ShortCircuitHandler handler) = 0; +}; + +// A non-copyable non-movable Event class. +// It stores a list of event handlers. +template +class Event : public details::EventBase, public IEvent { + using typename IEvent::EventArgs; + + using typename IBaseEvent::SpyOnlyHandler; + using typename IEvent::EventHandler; + using typename IEvent::ShortCircuitHandler; + + private: + struct HandlerData { + HandlerData(EventHandlerToken token, ShortCircuitHandler handler) + : token(token), handler(std::move(handler)) {} + EventHandlerToken token; + ShortCircuitHandler handler; + }; + + public: + Event() = default; + CRU_DELETE_COPY(Event) + CRU_DEFAULT_MOVE(Event) + ~Event() = default; + + EventRevoker AddSpyOnlyHandler(SpyOnlyHandler handler) override { + return AddShortCircuitHandler([handler = std::move(handler)](EventArgs) { + handler(); + return false; + }); + } + + EventRevoker AddHandler(EventHandler handler) override { + return AddShortCircuitHandler( + [handler = std::move(handler)](EventArgs args) { + handler(args); + return false; + }); + } + + // Handler return true to short circuit following handlers. + EventRevoker AddShortCircuitHandler(ShortCircuitHandler handler) override { + const auto token = current_token_++; + this->handler_data_list_.emplace_back(token, std::move(handler)); + return CreateRevoker(token); + } + + // Handler return true to short circuit following handlers. + EventRevoker PrependShortCircuitHandler( + ShortCircuitHandler handler) override { + const auto token = current_token_++; + this->handler_data_list_.emplace(this->handler_data_list_.cbegin(), token, + std::move(handler)); + return CreateRevoker(token); + } + + // This method will make a copy of all handlers. Because user might delete a + // handler in a handler, which may lead to seg fault as the handler is + // deleted while being executed. Thanks to this behavior, all handlers will + // be taken a snapshot when Raise is called, so even if you delete a handler + // during this period, all handlers in the snapshot will be executed. + void Raise(EventArgs args) { + std::vector handlers; + handlers.reserve(this->handler_data_list_.size()); + for (const auto& data : this->handler_data_list_) { + handlers.push_back(data.handler); + } + for (const auto& handler : handlers) { + auto short_circuit = handler(args); + if (short_circuit) return; + } + } + + protected: + void RemoveHandler(EventHandlerToken token) override { + const auto find_result = std::find_if( + this->handler_data_list_.cbegin(), this->handler_data_list_.cend(), + [token](const HandlerData& data) { return data.token == token; }); + if (find_result != this->handler_data_list_.cend()) { + this->handler_data_list_.erase(find_result); + } + } + + private: + std::vector handler_data_list_; + EventHandlerToken current_token_ = 0; +}; + +namespace details { +struct EventRevokerDestroyer { + void operator()(EventRevoker* p) { + (*p)(); + delete p; + } +}; +} // namespace details + +// A guard class for event revoker. Automatically revoke it when destroyed. +class EventRevokerGuard { + public: + EventRevokerGuard() = default; + explicit EventRevokerGuard(EventRevoker&& revoker) + : revoker_(new EventRevoker(std::move(revoker))) {} + EventRevokerGuard(const EventRevokerGuard& other) = delete; + EventRevokerGuard(EventRevokerGuard&& other) = default; + EventRevokerGuard& operator=(const EventRevokerGuard& other) = delete; + EventRevokerGuard& operator=(EventRevokerGuard&& other) = default; + ~EventRevokerGuard() = default; + + EventRevoker Get() { + // revoker is only null when this is moved + // you shouldn't use a moved instance + Expects(revoker_); + return *revoker_; + } + + EventRevoker Release() { return std::move(*revoker_.release()); } + + void Reset() { revoker_.reset(); } + + void Reset(EventRevoker&& revoker) { + revoker_.reset(new EventRevoker(std::move(revoker))); + } + + private: + std::unique_ptr revoker_; +}; + +class EventRevokerListGuard { + public: + EventRevokerListGuard() = default; + EventRevokerListGuard(const EventRevokerListGuard& other) = delete; + EventRevokerListGuard(EventRevokerListGuard&& other) = default; + EventRevokerListGuard& operator=(const EventRevokerListGuard& other) = delete; + EventRevokerListGuard& operator=(EventRevokerListGuard&& other) = default; + ~EventRevokerListGuard() = default; + + public: + void Add(EventRevoker&& revoker) { + event_revoker_guard_list_.push_back(EventRevokerGuard(std::move(revoker))); + } + + EventRevokerListGuard& operator+=(EventRevoker&& revoker) { + this->Add(std::move(revoker)); + return *this; + } + + void Clear() { event_revoker_guard_list_.clear(); } + + bool IsEmpty() const { return event_revoker_guard_list_.empty(); } + + private: + std::vector event_revoker_guard_list_; +}; +} // namespace cru diff --git a/include/cru/common/Event.hpp b/include/cru/common/Event.hpp deleted file mode 100644 index 5d60c5b3..00000000 --- a/include/cru/common/Event.hpp +++ /dev/null @@ -1,281 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "SelfResolvable.hpp" - -#include -#include -#include -#include -#include -#include - -namespace cru { -class EventRevoker; - -namespace details { -template -inline constexpr bool always_false_v = false; - -// Base class of all Event. -// It erases event args types and provides a -// unified form to create event revoker and -// revoke(remove) handler. -class EventBase : public SelfResolvable { - friend EventRevoker; - - protected: - using EventHandlerToken = long; - - EventBase() {} - CRU_DELETE_COPY(EventBase) - CRU_DEFAULT_MOVE(EventBase) - virtual ~EventBase() = default; - - // Remove the handler with the given token. If the token - // corresponds to no handler (which might have be revoked - // before), then nothing will be done. - virtual void RemoveHandler(EventHandlerToken token) = 0; - - // Create a revoker with the given token. - inline EventRevoker CreateRevoker(EventHandlerToken token); -}; -} // namespace details - -// A non-copyable and movable event revoker. -// Call function call operator to revoke the handler. -class EventRevoker { - friend details::EventBase; - - private: - EventRevoker(ObjectResolver&& resolver, - details::EventBase::EventHandlerToken token) - : resolver_(std::move(resolver)), token_(token) {} - - public: - EventRevoker(const EventRevoker& other) = default; - EventRevoker(EventRevoker&& other) = default; - EventRevoker& operator=(const EventRevoker& other) = default; - EventRevoker& operator=(EventRevoker&& other) = default; - ~EventRevoker() = default; - - // Revoke the registered handler. If the event has already - // been destroyed, then nothing will be done. If one of the - // copies calls this, then other copies's calls will have no - // effect. (They have the same token.) - void operator()() const { - if (const auto event = resolver_.Resolve()) { - event->RemoveHandler(token_); - } - } - - private: - ObjectResolver resolver_; - details::EventBase::EventHandlerToken token_; -}; - -inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { - return EventRevoker(CreateResolver(), token); -} - -// int -> int -// Point -> const Point& -// int& -> int& -template -using DeducedEventArgs = std::conditional_t< - std::is_lvalue_reference_v, TRaw, - std::conditional_t, TRaw, const TRaw&>>; - -struct IBaseEvent { - protected: - IBaseEvent() = default; - CRU_DELETE_COPY(IBaseEvent) - CRU_DEFAULT_MOVE(IBaseEvent) - ~IBaseEvent() = default; // Note that user can't destroy a Event via IEvent. - // So destructor should be protected. - - using SpyOnlyHandler = std::function; - - public: - virtual EventRevoker AddSpyOnlyHandler(SpyOnlyHandler handler) = 0; -}; - -// Provides an interface of event. -// IEvent only allow to add handler but not to raise the event. You may -// want to create an Event object and expose IEvent only so users won't -// be able to emit the event. -template -struct IEvent : virtual IBaseEvent { - public: - using EventArgs = DeducedEventArgs; - using EventHandler = std::function; - using ShortCircuitHandler = std::function; - - protected: - IEvent() = default; - CRU_DELETE_COPY(IEvent) - CRU_DEFAULT_MOVE(IEvent) - ~IEvent() = default; // Note that user can't destroy a Event via IEvent. So - // destructor should be protected. - - public: - virtual EventRevoker AddHandler(EventHandler handler) = 0; - virtual EventRevoker AddShortCircuitHandler(ShortCircuitHandler handler) = 0; - virtual EventRevoker PrependShortCircuitHandler( - ShortCircuitHandler handler) = 0; -}; - -// A non-copyable non-movable Event class. -// It stores a list of event handlers. -template -class Event : public details::EventBase, public IEvent { - using typename IEvent::EventArgs; - - using typename IBaseEvent::SpyOnlyHandler; - using typename IEvent::EventHandler; - using typename IEvent::ShortCircuitHandler; - - private: - struct HandlerData { - HandlerData(EventHandlerToken token, ShortCircuitHandler handler) - : token(token), handler(std::move(handler)) {} - EventHandlerToken token; - ShortCircuitHandler handler; - }; - - public: - Event() = default; - CRU_DELETE_COPY(Event) - CRU_DEFAULT_MOVE(Event) - ~Event() = default; - - EventRevoker AddSpyOnlyHandler(SpyOnlyHandler handler) override { - return AddShortCircuitHandler([handler = std::move(handler)](EventArgs) { - handler(); - return false; - }); - } - - EventRevoker AddHandler(EventHandler handler) override { - return AddShortCircuitHandler( - [handler = std::move(handler)](EventArgs args) { - handler(args); - return false; - }); - } - - // Handler return true to short circuit following handlers. - EventRevoker AddShortCircuitHandler(ShortCircuitHandler handler) override { - const auto token = current_token_++; - this->handler_data_list_.emplace_back(token, std::move(handler)); - return CreateRevoker(token); - } - - // Handler return true to short circuit following handlers. - EventRevoker PrependShortCircuitHandler( - ShortCircuitHandler handler) override { - const auto token = current_token_++; - this->handler_data_list_.emplace(this->handler_data_list_.cbegin(), token, - std::move(handler)); - return CreateRevoker(token); - } - - // This method will make a copy of all handlers. Because user might delete a - // handler in a handler, which may lead to seg fault as the handler is - // deleted while being executed. Thanks to this behavior, all handlers will - // be taken a snapshot when Raise is called, so even if you delete a handler - // during this period, all handlers in the snapshot will be executed. - void Raise(EventArgs args) { - std::vector handlers; - handlers.reserve(this->handler_data_list_.size()); - for (const auto& data : this->handler_data_list_) { - handlers.push_back(data.handler); - } - for (const auto& handler : handlers) { - auto short_circuit = handler(args); - if (short_circuit) return; - } - } - - protected: - void RemoveHandler(EventHandlerToken token) override { - const auto find_result = std::find_if( - this->handler_data_list_.cbegin(), this->handler_data_list_.cend(), - [token](const HandlerData& data) { return data.token == token; }); - if (find_result != this->handler_data_list_.cend()) { - this->handler_data_list_.erase(find_result); - } - } - - private: - std::vector handler_data_list_; - EventHandlerToken current_token_ = 0; -}; - -namespace details { -struct EventRevokerDestroyer { - void operator()(EventRevoker* p) { - (*p)(); - delete p; - } -}; -} // namespace details - -// A guard class for event revoker. Automatically revoke it when destroyed. -class EventRevokerGuard { - public: - EventRevokerGuard() = default; - explicit EventRevokerGuard(EventRevoker&& revoker) - : revoker_(new EventRevoker(std::move(revoker))) {} - EventRevokerGuard(const EventRevokerGuard& other) = delete; - EventRevokerGuard(EventRevokerGuard&& other) = default; - EventRevokerGuard& operator=(const EventRevokerGuard& other) = delete; - EventRevokerGuard& operator=(EventRevokerGuard&& other) = default; - ~EventRevokerGuard() = default; - - EventRevoker Get() { - // revoker is only null when this is moved - // you shouldn't use a moved instance - Expects(revoker_); - return *revoker_; - } - - EventRevoker Release() { return std::move(*revoker_.release()); } - - void Reset() { revoker_.reset(); } - - void Reset(EventRevoker&& revoker) { - revoker_.reset(new EventRevoker(std::move(revoker))); - } - - private: - std::unique_ptr revoker_; -}; - -class EventRevokerListGuard { - public: - EventRevokerListGuard() = default; - EventRevokerListGuard(const EventRevokerListGuard& other) = delete; - EventRevokerListGuard(EventRevokerListGuard&& other) = default; - EventRevokerListGuard& operator=(const EventRevokerListGuard& other) = delete; - EventRevokerListGuard& operator=(EventRevokerListGuard&& other) = default; - ~EventRevokerListGuard() = default; - - public: - void Add(EventRevoker&& revoker) { - event_revoker_guard_list_.push_back(EventRevokerGuard(std::move(revoker))); - } - - EventRevokerListGuard& operator+=(EventRevoker&& revoker) { - this->Add(std::move(revoker)); - return *this; - } - - void Clear() { event_revoker_guard_list_.clear(); } - - bool IsEmpty() const { return event_revoker_guard_list_.empty(); } - - private: - std::vector event_revoker_guard_list_; -}; -} // namespace cru diff --git a/include/cru/common/Exception.h b/include/cru/common/Exception.h new file mode 100644 index 00000000..365d2064 --- /dev/null +++ b/include/cru/common/Exception.h @@ -0,0 +1,32 @@ +#pragma once +#include "String.h" + +namespace cru { +#ifdef _MSC_VER +#pragma warning(disable : 4275) +#endif +class CRU_BASE_API Exception : public std::exception { + public: + Exception(); + explicit Exception(String message); + + CRU_DEFAULT_COPY(Exception) + CRU_DEFAULT_MOVE(Exception) + + ~Exception() override; + + public: + String GetMessage() const { return message_; } + + const char* what() const noexcept override; + + private: + String message_; + mutable std::string utf8_message_; +}; + +class CRU_BASE_API TextEncodeException : public Exception { + public: + using Exception::Exception; +}; +} // namespace cru diff --git a/include/cru/common/Exception.hpp b/include/cru/common/Exception.hpp deleted file mode 100644 index cb35469c..00000000 --- a/include/cru/common/Exception.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "String.hpp" - -namespace cru { -#ifdef _MSC_VER -#pragma warning(disable : 4275) -#endif -class CRU_BASE_API Exception : public std::exception { - public: - Exception(); - explicit Exception(String message); - - CRU_DEFAULT_COPY(Exception) - CRU_DEFAULT_MOVE(Exception) - - ~Exception() override; - - public: - String GetMessage() const { return message_; } - - const char* what() const noexcept override; - - private: - String message_; - mutable std::string utf8_message_; -}; - -class CRU_BASE_API TextEncodeException : public Exception { - public: - using Exception::Exception; -}; -} // namespace cru diff --git a/include/cru/common/Format.h b/include/cru/common/Format.h new file mode 100644 index 00000000..ede2998b --- /dev/null +++ b/include/cru/common/Format.h @@ -0,0 +1,143 @@ +#pragma once + +#include "Exception.h" +#include "String.h" + +#include + +namespace cru { +inline String ToString(bool value) { + return value ? String(u"true") : String(u"false"); +} + +template +std::enable_if_t, String> ToString(T value) { + std::array buffer; + auto result = + std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); + + if (result.ec == std::errc{}) { + } else { + throw std::invalid_argument("Failed to convert value to chars."); + } + + auto size = result.ptr - buffer.data(); + auto b = new char16_t[size + 1]; + b[size] = 0; + std::copy(buffer.data(), result.ptr, b); + return String::FromBuffer(b, size, size); +} + +template +std::enable_if_t, String> ToString(T value) { + auto str = std::to_string(value); + return String(str.cbegin(), str.cend()); +} + +template +std::enable_if_t< + std::is_convertible_v)), String>, + String> +ToString(const T& value, StringView option) { + CRU_UNUSED(option) + return ToString(value); +} + +inline String ToString(String value) { return value; } + +namespace details { +enum class FormatTokenType { PlaceHolder, Text }; +enum class FormatPlaceHolderType { None, Positioned, Named }; + +struct FormatToken { + static FormatToken Text() { + return FormatToken{FormatTokenType::Text, {}, {}, 0, {}, {}}; + } + + static FormatToken NonePlaceHolder(String option) { + return FormatToken(FormatTokenType::PlaceHolder, {}, + FormatPlaceHolderType::None, 0, {}, std::move(option)); + } + + static FormatToken PositionedPlaceHolder(int position, String option) { + return FormatToken(FormatTokenType::PlaceHolder, {}, + FormatPlaceHolderType::Positioned, position, {}, + std::move(option)); + } + + static FormatToken NamedPlaceHolder(String name, String option) { + return FormatToken(FormatTokenType::PlaceHolder, {}, + FormatPlaceHolderType::Named, 0, std::move(name), + std::move(option)); + } + + FormatToken(FormatTokenType type, String data, + FormatPlaceHolderType place_holder_type, + int place_holder_position, String place_holder_name, + String place_holder_option) + : type(type), + data(std::move(data)), + place_holder_type(place_holder_type), + place_holder_position(place_holder_position), + place_holder_name(std::move(place_holder_name)), + place_holder_option(std::move(place_holder_option)) {} + + CRU_DEFAULT_COPY(FormatToken) + CRU_DEFAULT_MOVE(FormatToken) + + CRU_DEFAULT_DESTRUCTOR(FormatToken) + + FormatTokenType type; + String data; + FormatPlaceHolderType place_holder_type; + int place_holder_position; + String place_holder_name; + String place_holder_option; +}; + +std::vector CRU_BASE_API ParseToFormatTokenList(const String& str); + +void CRU_BASE_API FormatAppendFromFormatTokenList( + String& current, const std::vector& format_token_list, + Index index); + +template +void FormatAppendFromFormatTokenList( + String& current, const std::vector& format_token_list, + Index index, TA&& args0, T&&... args) { + for (Index i = index; i < static_cast(format_token_list.size()); i++) { + const auto& token = format_token_list[i]; + if (token.type == FormatTokenType::PlaceHolder) { + if (token.place_holder_type == FormatPlaceHolderType::None) { + current += ToString(std::forward(args0), token.place_holder_option); + FormatAppendFromFormatTokenList(current, format_token_list, i + 1, + std::forward(args)...); + + return; + } else { + throw Exception( + u"Currently do not support positional or named place holder."); + } + } else { + current += token.data; + } + } +} +} // namespace details + +template +String Format(const String& format, T&&... args) { + String result; + + details::FormatAppendFromFormatTokenList( + result, details::ParseToFormatTokenList(format), 0, + std::forward(args)...); + + return result; +} + +template +String String::Format(T&&... args) const { + return cru::Format(*this, std::forward(args)...); +} +} // namespace cru diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp deleted file mode 100644 index 1ad71262..00000000 --- a/include/cru/common/Format.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#pragma once - -#include "Exception.hpp" -#include "String.hpp" - -#include - -namespace cru { -inline String ToString(bool value) { - return value ? String(u"true") : String(u"false"); -} - -template -std::enable_if_t, String> ToString(T value) { - std::array buffer; - auto result = - std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); - - if (result.ec == std::errc{}) { - } else { - throw std::invalid_argument("Failed to convert value to chars."); - } - - auto size = result.ptr - buffer.data(); - auto b = new char16_t[size + 1]; - b[size] = 0; - std::copy(buffer.data(), result.ptr, b); - return String::FromBuffer(b, size, size); -} - -template -std::enable_if_t, String> ToString(T value) { - auto str = std::to_string(value); - return String(str.cbegin(), str.cend()); -} - -template -std::enable_if_t< - std::is_convertible_v)), String>, - String> -ToString(const T& value, StringView option) { - CRU_UNUSED(option) - return ToString(value); -} - -inline String ToString(String value) { return value; } - -namespace details { -enum class FormatTokenType { PlaceHolder, Text }; -enum class FormatPlaceHolderType { None, Positioned, Named }; - -struct FormatToken { - static FormatToken Text() { - return FormatToken{FormatTokenType::Text, {}, {}, 0, {}, {}}; - } - - static FormatToken NonePlaceHolder(String option) { - return FormatToken(FormatTokenType::PlaceHolder, {}, - FormatPlaceHolderType::None, 0, {}, std::move(option)); - } - - static FormatToken PositionedPlaceHolder(int position, String option) { - return FormatToken(FormatTokenType::PlaceHolder, {}, - FormatPlaceHolderType::Positioned, position, {}, - std::move(option)); - } - - static FormatToken NamedPlaceHolder(String name, String option) { - return FormatToken(FormatTokenType::PlaceHolder, {}, - FormatPlaceHolderType::Named, 0, std::move(name), - std::move(option)); - } - - FormatToken(FormatTokenType type, String data, - FormatPlaceHolderType place_holder_type, - int place_holder_position, String place_holder_name, - String place_holder_option) - : type(type), - data(std::move(data)), - place_holder_type(place_holder_type), - place_holder_position(place_holder_position), - place_holder_name(std::move(place_holder_name)), - place_holder_option(std::move(place_holder_option)) {} - - CRU_DEFAULT_COPY(FormatToken) - CRU_DEFAULT_MOVE(FormatToken) - - CRU_DEFAULT_DESTRUCTOR(FormatToken) - - FormatTokenType type; - String data; - FormatPlaceHolderType place_holder_type; - int place_holder_position; - String place_holder_name; - String place_holder_option; -}; - -std::vector CRU_BASE_API ParseToFormatTokenList(const String& str); - -void CRU_BASE_API FormatAppendFromFormatTokenList( - String& current, const std::vector& format_token_list, - Index index); - -template -void FormatAppendFromFormatTokenList( - String& current, const std::vector& format_token_list, - Index index, TA&& args0, T&&... args) { - for (Index i = index; i < static_cast(format_token_list.size()); i++) { - const auto& token = format_token_list[i]; - if (token.type == FormatTokenType::PlaceHolder) { - if (token.place_holder_type == FormatPlaceHolderType::None) { - current += ToString(std::forward(args0), token.place_holder_option); - FormatAppendFromFormatTokenList(current, format_token_list, i + 1, - std::forward(args)...); - - return; - } else { - throw Exception( - u"Currently do not support positional or named place holder."); - } - } else { - current += token.data; - } - } -} -} // namespace details - -template -String Format(const String& format, T&&... args) { - String result; - - details::FormatAppendFromFormatTokenList( - result, details::ParseToFormatTokenList(format), 0, - std::forward(args)...); - - return result; -} - -template -String String::Format(T&&... args) const { - return cru::Format(*this, std::forward(args)...); -} -} // namespace cru diff --git a/include/cru/common/HandlerRegistry.h b/include/cru/common/HandlerRegistry.h new file mode 100644 index 00000000..e405d1fd --- /dev/null +++ b/include/cru/common/HandlerRegistry.h @@ -0,0 +1,87 @@ +#pragma once +#include "Base.h" + +#include +#include +#include +#include + +namespace cru { + +template +class HandlerRegistryIterator { + public: + using RawIterator = + typename std::vector>>::const_iterator; + + explicit HandlerRegistryIterator(RawIterator raw) : raw_(std::move(raw)) {} + + CRU_DELETE_COPY(HandlerRegistryIterator) + CRU_DELETE_MOVE(HandlerRegistryIterator) + + ~HandlerRegistryIterator() = default; + + const std::function& operator*() const { return raw_->second; } + const std::function* operator->() const { return &raw_->second; } + + HandlerRegistryIterator& operator++() { + ++raw_; + return *this; + } + + HandlerRegistryIterator operator++(int) { + auto c = *this; + this->operator++(); + return c; + } + + bool operator==(const HandlerRegistryIterator& other) const { + return this->raw_ == other.raw_; + } + + bool operator!=(const HandlerRegistryIterator& other) const { + return !this->operator==(other); + } + + private: + RawIterator raw_; +}; + +template +class HandlerRegistry final { + public: + HandlerRegistry() = default; + CRU_DEFAULT_COPY(HandlerRegistry) + CRU_DEFAULT_MOVE(HandlerRegistry) + ~HandlerRegistry() = default; + + public: + int AddHandler(std::function handler) { + auto id = current_id_++; + handler_list_.push_back({id, std::move(handler)}); + return id; + } + + void RemoveHandler(int id) { + auto result = std::find_if(handler_list_.cbegin(), handler_list_.cend(), + [id](const std::pair>& d) { + return d.first == id; + }); + if (result != handler_list_.cend()) { + handler_list_.erase(result); + } + } + + HandlerRegistryIterator begin() const { + return HandlerRegistryIterator(handler_list_.begin()); + } + + HandlerRegistryIterator end() const { + return HandlerRegistryIterator(handler_list_.end()); + } + + private: + int current_id_ = 1; + std::vector>> handler_list_; +}; +} // namespace cru diff --git a/include/cru/common/HandlerRegistry.hpp b/include/cru/common/HandlerRegistry.hpp deleted file mode 100644 index 8049e74b..00000000 --- a/include/cru/common/HandlerRegistry.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include -#include -#include -#include - -namespace cru { - -template -class HandlerRegistryIterator { - public: - using RawIterator = - typename std::vector>>::const_iterator; - - explicit HandlerRegistryIterator(RawIterator raw) : raw_(std::move(raw)) {} - - CRU_DELETE_COPY(HandlerRegistryIterator) - CRU_DELETE_MOVE(HandlerRegistryIterator) - - ~HandlerRegistryIterator() = default; - - const std::function& operator*() const { return raw_->second; } - const std::function* operator->() const { return &raw_->second; } - - HandlerRegistryIterator& operator++() { - ++raw_; - return *this; - } - - HandlerRegistryIterator operator++(int) { - auto c = *this; - this->operator++(); - return c; - } - - bool operator==(const HandlerRegistryIterator& other) const { - return this->raw_ == other.raw_; - } - - bool operator!=(const HandlerRegistryIterator& other) const { - return !this->operator==(other); - } - - private: - RawIterator raw_; -}; - -template -class HandlerRegistry final { - public: - HandlerRegistry() = default; - CRU_DEFAULT_COPY(HandlerRegistry) - CRU_DEFAULT_MOVE(HandlerRegistry) - ~HandlerRegistry() = default; - - public: - int AddHandler(std::function handler) { - auto id = current_id_++; - handler_list_.push_back({id, std::move(handler)}); - return id; - } - - void RemoveHandler(int id) { - auto result = std::find_if(handler_list_.cbegin(), handler_list_.cend(), - [id](const std::pair>& d) { - return d.first == id; - }); - if (result != handler_list_.cend()) { - handler_list_.erase(result); - } - } - - HandlerRegistryIterator begin() const { - return HandlerRegistryIterator(handler_list_.begin()); - } - - HandlerRegistryIterator end() const { - return HandlerRegistryIterator(handler_list_.end()); - } - - private: - int current_id_ = 1; - std::vector>> handler_list_; -}; -} // namespace cru diff --git a/include/cru/common/Logger.h b/include/cru/common/Logger.h new file mode 100644 index 00000000..25875651 --- /dev/null +++ b/include/cru/common/Logger.h @@ -0,0 +1,114 @@ +#pragma once +#include "Base.h" + +#include "String.h" +#include "Format.h" + +#include +#include + +namespace cru::log { + +enum class LogLevel { Debug, Info, Warn, Error }; + +struct CRU_BASE_API ILogSource : virtual Interface { + // Write the string s. LogLevel is just a helper. It has no effect on the + // content to write. + virtual void Write(LogLevel level, StringView s) = 0; +}; + +class CRU_BASE_API Logger : public Object { + public: + static Logger* GetInstance(); + + public: + Logger() = default; + + CRU_DELETE_COPY(Logger) + CRU_DELETE_MOVE(Logger) + + ~Logger() override = default; + + public: + void AddSource(std::unique_ptr source); + void RemoveSource(ILogSource* source); + + public: + void Log(LogLevel level, StringView message); + void Log(LogLevel level, StringView tag, StringView message); + + private: + std::list> sources_; +}; + +// TODO: Remove argument evaluation in Debug. +template +void Debug([[maybe_unused]] TArgs&&... args) { +#ifdef CRU_DEBUG + Logger::GetInstance()->Log(LogLevel::Debug, + Format(std::forward(args)...)); +#endif +} + +template +void Info(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Info, + Format(std::forward(args)...)); +} + +template +void Warn(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Warn, + Format(std::forward(args)...)); +} + +template +void Error(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Error, + Format(std::forward(args)...)); +} + +// TODO: Remove argument evaluation in Debug. +template +void TagDebug([[maybe_unused]] StringView tag, + [[maybe_unused]] TArgs&&... args) { +#ifdef CRU_DEBUG + Logger::GetInstance()->Log(LogLevel::Debug, tag, + Format(std::forward(args)...)); +#endif +} + +template +void TagInfo(StringView tag, TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Info, tag, + Format(std::forward(args)...)); +} + +template +void TagWarn(StringView tag, TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Warn, tag, + Format(std::forward(args)...)); +} + +template +void TagError(StringView tag, TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Error, tag, + Format(std::forward(args)...)); +} + +class StdioLogSource : public Object, public virtual ILogSource { + public: + explicit StdioLogSource(bool use_lock = false); + + CRU_DELETE_COPY(StdioLogSource) + CRU_DELETE_MOVE(StdioLogSource) + + ~StdioLogSource() override; + + public: + void Write(LogLevel level, StringView s) override; + + private: + bool use_lock_; +}; +} // namespace cru::log diff --git a/include/cru/common/Logger.hpp b/include/cru/common/Logger.hpp deleted file mode 100644 index c4a3e54a..00000000 --- a/include/cru/common/Logger.hpp +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "String.hpp" -#include "Format.hpp" - -#include -#include - -namespace cru::log { - -enum class LogLevel { Debug, Info, Warn, Error }; - -struct CRU_BASE_API ILogSource : virtual Interface { - // Write the string s. LogLevel is just a helper. It has no effect on the - // content to write. - virtual void Write(LogLevel level, StringView s) = 0; -}; - -class CRU_BASE_API Logger : public Object { - public: - static Logger* GetInstance(); - - public: - Logger() = default; - - CRU_DELETE_COPY(Logger) - CRU_DELETE_MOVE(Logger) - - ~Logger() override = default; - - public: - void AddSource(std::unique_ptr source); - void RemoveSource(ILogSource* source); - - public: - void Log(LogLevel level, StringView message); - void Log(LogLevel level, StringView tag, StringView message); - - private: - std::list> sources_; -}; - -// TODO: Remove argument evaluation in Debug. -template -void Debug([[maybe_unused]] TArgs&&... args) { -#ifdef CRU_DEBUG - Logger::GetInstance()->Log(LogLevel::Debug, - Format(std::forward(args)...)); -#endif -} - -template -void Info(TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Info, - Format(std::forward(args)...)); -} - -template -void Warn(TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Warn, - Format(std::forward(args)...)); -} - -template -void Error(TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Error, - Format(std::forward(args)...)); -} - -// TODO: Remove argument evaluation in Debug. -template -void TagDebug([[maybe_unused]] StringView tag, - [[maybe_unused]] TArgs&&... args) { -#ifdef CRU_DEBUG - Logger::GetInstance()->Log(LogLevel::Debug, tag, - Format(std::forward(args)...)); -#endif -} - -template -void TagInfo(StringView tag, TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Info, tag, - Format(std::forward(args)...)); -} - -template -void TagWarn(StringView tag, TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Warn, tag, - Format(std::forward(args)...)); -} - -template -void TagError(StringView tag, TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Error, tag, - Format(std::forward(args)...)); -} - -class StdioLogSource : public Object, public virtual ILogSource { - public: - explicit StdioLogSource(bool use_lock = false); - - CRU_DELETE_COPY(StdioLogSource) - CRU_DELETE_MOVE(StdioLogSource) - - ~StdioLogSource() override; - - public: - void Write(LogLevel level, StringView s) override; - - private: - bool use_lock_; -}; -} // namespace cru::log diff --git a/include/cru/common/PreConfig.h b/include/cru/common/PreConfig.h new file mode 100644 index 00000000..ba0f5bd8 --- /dev/null +++ b/include/cru/common/PreConfig.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef _MSC_VER +// disable the unnecessary warning about multi-inheritance +#pragma warning(disable : 4250) +// disable dll export template issue warning +#pragma warning(disable : 4251) +#endif + +#ifdef CRU_PLATFORM_WINDOWS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(CRU_PLATFORM_OSX) || defined(CRU_PLATFORM_LINUX) +#define CRU_PLATFORM_UNIX +#endif diff --git a/include/cru/common/PreConfig.hpp b/include/cru/common/PreConfig.hpp deleted file mode 100644 index ba0f5bd8..00000000 --- a/include/cru/common/PreConfig.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#ifdef _MSC_VER -// disable the unnecessary warning about multi-inheritance -#pragma warning(disable : 4250) -// disable dll export template issue warning -#pragma warning(disable : 4251) -#endif - -#ifdef CRU_PLATFORM_WINDOWS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#if defined(CRU_PLATFORM_OSX) || defined(CRU_PLATFORM_LINUX) -#define CRU_PLATFORM_UNIX -#endif diff --git a/include/cru/common/PropertyTree.h b/include/cru/common/PropertyTree.h new file mode 100644 index 00000000..54e185b9 --- /dev/null +++ b/include/cru/common/PropertyTree.h @@ -0,0 +1,63 @@ +#pragma once + +#include "Base.h" +#include "String.h" + +#include + +namespace cru { +class PropertyTree; + +class CRU_BASE_API PropertySubTreeRef { + public: + static String CombineKey(StringView left, StringView right); + + explicit PropertySubTreeRef(PropertyTree* tree, String path = {}); + + CRU_DEFAULT_COPY(PropertySubTreeRef); + CRU_DEFAULT_MOVE(PropertySubTreeRef); + + CRU_DEFAULT_DESTRUCTOR(PropertySubTreeRef); + + public: + PropertyTree* GetTree() const { return tree_; } + + String GetPath() const { return path_; } + void SetPath(String path) { path_ = std::move(path); } + + PropertySubTreeRef GetParent() const; + PropertySubTreeRef GetChild(const String& key) const; + + String GetValue(const String& key) const; + void SetValue(const String& key, String value); + void DeleteValue(const String& key); + + private: + PropertyTree* tree_; + String path_; +}; + +class CRU_BASE_API PropertyTree { + public: + static String CombineKey(StringView left, StringView right); + + PropertyTree() = default; + explicit PropertyTree(std::unordered_map values); + + CRU_DELETE_COPY(PropertyTree); + CRU_DELETE_MOVE(PropertyTree); + + CRU_DEFAULT_DESTRUCTOR(PropertyTree); + + public: + String GetValue(const String& key) const; + void SetValue(const String& key, String value); + void DeleteValue(const String& key); + + PropertySubTreeRef GetSubTreeRef(const String& path); + + private: + std::unordered_map values_; +}; + +} // namespace cru diff --git a/include/cru/common/PropertyTree.hpp b/include/cru/common/PropertyTree.hpp deleted file mode 100644 index 613bcc47..00000000 --- a/include/cru/common/PropertyTree.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "Base.hpp" -#include "String.hpp" - -#include - -namespace cru { -class PropertyTree; - -class CRU_BASE_API PropertySubTreeRef { - public: - static String CombineKey(StringView left, StringView right); - - explicit PropertySubTreeRef(PropertyTree* tree, String path = {}); - - CRU_DEFAULT_COPY(PropertySubTreeRef); - CRU_DEFAULT_MOVE(PropertySubTreeRef); - - CRU_DEFAULT_DESTRUCTOR(PropertySubTreeRef); - - public: - PropertyTree* GetTree() const { return tree_; } - - String GetPath() const { return path_; } - void SetPath(String path) { path_ = std::move(path); } - - PropertySubTreeRef GetParent() const; - PropertySubTreeRef GetChild(const String& key) const; - - String GetValue(const String& key) const; - void SetValue(const String& key, String value); - void DeleteValue(const String& key); - - private: - PropertyTree* tree_; - String path_; -}; - -class CRU_BASE_API PropertyTree { - public: - static String CombineKey(StringView left, StringView right); - - PropertyTree() = default; - explicit PropertyTree(std::unordered_map values); - - CRU_DELETE_COPY(PropertyTree); - CRU_DELETE_MOVE(PropertyTree); - - CRU_DEFAULT_DESTRUCTOR(PropertyTree); - - public: - String GetValue(const String& key) const; - void SetValue(const String& key, String value); - void DeleteValue(const String& key); - - PropertySubTreeRef GetSubTreeRef(const String& path); - - private: - std::unordered_map values_; -}; - -} // namespace cru diff --git a/include/cru/common/Range.h b/include/cru/common/Range.h new file mode 100644 index 00000000..e61d90ca --- /dev/null +++ b/include/cru/common/Range.h @@ -0,0 +1,43 @@ +#pragma once +#include "Base.h" + +namespace cru { +struct Range final { + constexpr static Range FromTwoSides(gsl::index start, gsl::index end) { + return Range(start, end - start); + } + + constexpr static Range FromTwoSides(gsl::index start, gsl::index end, + gsl::index offset) { + return Range(start + offset, end - start); + } + + constexpr Range() = default; + constexpr Range(const gsl::index position, const gsl::index count = 0) + : position(position), count(count) {} + + gsl::index GetStart() const { return position; } + gsl::index GetEnd() const { return position + count; } + + void ChangeEnd(gsl::index new_end) { count = new_end - position; } + + Range Normalize() const { + auto result = *this; + if (result.count < 0) { + result.position += result.count; + result.count = -result.count; + } + return result; + } + + Range CoerceInto(gsl::index min, gsl::index max) const { + auto coerce = [min, max](gsl::index index) { + return index > max ? max : (index < min ? min : index); + }; + return Range::FromTwoSides(coerce(GetStart()), coerce(GetEnd())); + } + + gsl::index position = 0; + gsl::index count = 0; +}; +} // namespace cru diff --git a/include/cru/common/Range.hpp b/include/cru/common/Range.hpp deleted file mode 100644 index ecc61243..00000000 --- a/include/cru/common/Range.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru { -struct Range final { - constexpr static Range FromTwoSides(gsl::index start, gsl::index end) { - return Range(start, end - start); - } - - constexpr static Range FromTwoSides(gsl::index start, gsl::index end, - gsl::index offset) { - return Range(start + offset, end - start); - } - - constexpr Range() = default; - constexpr Range(const gsl::index position, const gsl::index count = 0) - : position(position), count(count) {} - - gsl::index GetStart() const { return position; } - gsl::index GetEnd() const { return position + count; } - - void ChangeEnd(gsl::index new_end) { count = new_end - position; } - - Range Normalize() const { - auto result = *this; - if (result.count < 0) { - result.position += result.count; - result.count = -result.count; - } - return result; - } - - Range CoerceInto(gsl::index min, gsl::index max) const { - auto coerce = [min, max](gsl::index index) { - return index > max ? max : (index < min ? min : index); - }; - return Range::FromTwoSides(coerce(GetStart()), coerce(GetEnd())); - } - - gsl::index position = 0; - gsl::index count = 0; -}; -} // namespace cru diff --git a/include/cru/common/SelfResolvable.h b/include/cru/common/SelfResolvable.h new file mode 100644 index 00000000..c8acd4b9 --- /dev/null +++ b/include/cru/common/SelfResolvable.h @@ -0,0 +1,69 @@ +#pragma once +#include "PreConfig.h" + +#include +#include + +namespace cru { +template +class SelfResolvable; + +template +class ObjectResolver { + friend SelfResolvable; + + private: + ObjectResolver(const std::shared_ptr& resolver) : resolver_(resolver) {} + + public: + ObjectResolver(const ObjectResolver&) = default; + ObjectResolver& operator=(const ObjectResolver&) = default; + ObjectResolver(ObjectResolver&&) = default; + ObjectResolver& operator=(ObjectResolver&&) = default; + ~ObjectResolver() = default; + + T* Resolve() const { + // resolver_ is null only when this has been moved. + // You shouldn't resolve a moved resolver. So assert it. + Expects(resolver_); + return *resolver_; + } + + private: + std::shared_ptr resolver_; +}; + +template +class SelfResolvable { + public: + SelfResolvable() : resolver_(new T*(static_cast(this))) {} + SelfResolvable(const SelfResolvable&) = delete; + SelfResolvable& operator=(const SelfResolvable&) = delete; + + // Resolvers to old object will resolve to new object. + SelfResolvable(SelfResolvable&& other) + : resolver_(std::move(other.resolver_)) { + (*resolver_) = static_cast(this); + } + + // Old resolvers for this object will resolve to nullptr. + // Other's resolvers will now resolve to this. + SelfResolvable& operator=(SelfResolvable&& other) { + if (this != &other) { + (*resolver_) = nullptr; + resolver_ = std::move(other.resolver_); + (*resolver_) = static_cast(this); + } + return *this; + } + + virtual ~SelfResolvable() { + if (resolver_ != nullptr) (*resolver_) = nullptr; + } + + ObjectResolver CreateResolver() { return ObjectResolver(resolver_); } + + private: + std::shared_ptr resolver_; +}; +} // namespace cru diff --git a/include/cru/common/SelfResolvable.hpp b/include/cru/common/SelfResolvable.hpp deleted file mode 100644 index eaa4ce34..00000000 --- a/include/cru/common/SelfResolvable.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include "PreConfig.hpp" - -#include -#include - -namespace cru { -template -class SelfResolvable; - -template -class ObjectResolver { - friend SelfResolvable; - - private: - ObjectResolver(const std::shared_ptr& resolver) : resolver_(resolver) {} - - public: - ObjectResolver(const ObjectResolver&) = default; - ObjectResolver& operator=(const ObjectResolver&) = default; - ObjectResolver(ObjectResolver&&) = default; - ObjectResolver& operator=(ObjectResolver&&) = default; - ~ObjectResolver() = default; - - T* Resolve() const { - // resolver_ is null only when this has been moved. - // You shouldn't resolve a moved resolver. So assert it. - Expects(resolver_); - return *resolver_; - } - - private: - std::shared_ptr resolver_; -}; - -template -class SelfResolvable { - public: - SelfResolvable() : resolver_(new T*(static_cast(this))) {} - SelfResolvable(const SelfResolvable&) = delete; - SelfResolvable& operator=(const SelfResolvable&) = delete; - - // Resolvers to old object will resolve to new object. - SelfResolvable(SelfResolvable&& other) - : resolver_(std::move(other.resolver_)) { - (*resolver_) = static_cast(this); - } - - // Old resolvers for this object will resolve to nullptr. - // Other's resolvers will now resolve to this. - SelfResolvable& operator=(SelfResolvable&& other) { - if (this != &other) { - (*resolver_) = nullptr; - resolver_ = std::move(other.resolver_); - (*resolver_) = static_cast(this); - } - return *this; - } - - virtual ~SelfResolvable() { - if (resolver_ != nullptr) (*resolver_) = nullptr; - } - - ObjectResolver CreateResolver() { return ObjectResolver(resolver_); } - - private: - std::shared_ptr resolver_; -}; -} // namespace cru diff --git a/include/cru/common/String.h b/include/cru/common/String.h new file mode 100644 index 00000000..0b1b031b --- /dev/null +++ b/include/cru/common/String.h @@ -0,0 +1,436 @@ +#pragma once +#include "Base.h" + +#include "Range.h" +#include "StringUtil.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace cru { +class StringView; + +class CRU_BASE_API String { + public: + using value_type = char16_t; + using size_type = Index; + using difference_type = Index; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using iterator = value_type*; + using const_iterator = const value_type*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + public: + static String FromUtf8(const char* str); + static String FromUtf8(const char* str, Index size); + static String FromUtf8(std::string_view str) { + return FromUtf8(str.data(), str.size()); + } + + static String FromUtf16(const char16_t* str) { return String(str); } + static String FromUtf16(const char16_t* str, Index size) { + return String(str, size); + } + static String FromUtf16(std::u16string_view str) { + return FromUtf16(str.data(), str.size()); + } + + static inline String From(StringView str); + + // Never use this if you don't know what this mean! + static String FromBuffer(pointer buffer, Index size, Index capacity) { + return String{from_buffer_tag{}, buffer, size, capacity}; + } + + static String FromStdPath(const std::filesystem::path& path); + +#ifdef CRU_PLATFORM_WINDOWS + static String FromUtf16(wchar_t* str) { return String(str); } + static String FromUtf16(wchar_t* str, Index size) { + return String(str, size); + } +#endif + + public: + String() = default; + + explicit String(const_pointer str); + String(const_pointer str, size_type size); + + template + String(const char16_t (&str)[size]) + : String(reinterpret_cast(str), size - 1) {} + + template + String(Iter start, Iter end) { + for (; start != end; start++) { + append(*start); + } + } + + String(size_type size, value_type ch = 0); + + String(std::initializer_list l); + + explicit String(StringView str); + +#ifdef CRU_PLATFORM_WINDOWS + String(const wchar_t* str); + String(const wchar_t* str, Index size); + String(const std::wstring& str) : String(str.data(), str.size()) {} +#endif + + String(const String& other); + String(String&& other) noexcept; + + String& operator=(const String& other); + String& operator=(String&& other) noexcept; + + ~String(); + + private: + struct from_buffer_tag {}; + String(from_buffer_tag, pointer buffer, Index size, Index capacity); + + public: + bool empty() const { return this->size_ == 0; } + Index size() const { return this->size_; } + Index length() const { return this->size(); } + Index capacity() const { return this->capacity_; } + pointer data() { return this->buffer_; } + const_pointer data() const { return this->buffer_; } + + void resize(Index new_size); + void reserve(Index new_capacity); + void shrink_to_fit(); + + reference front() { return this->operator[](0); } + const_reference front() const { return this->operator[](0); } + + reference back() { return this->operator[](size_ - 1); } + const_reference back() const { return this->operator[](size_ - 1); } + + const_pointer c_str() const { return buffer_; } + + reference operator[](Index index) { return buffer_[index]; } + const_reference operator[](Index index) const { return buffer_[index]; } + + public: + iterator begin() { return this->buffer_; } + const_iterator begin() const { return this->buffer_; } + const_iterator cbegin() const { return this->buffer_; } + + iterator end() { return this->buffer_ + this->size_; } + const_iterator end() const { return this->buffer_ + this->size_; } + const_iterator cend() const { return this->buffer_ + this->size_; } + + reverse_iterator rbegin() { return reverse_iterator{end()}; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator{end()}; + } + const_reverse_iterator crbegin() const { + return const_reverse_iterator{cend()}; + } + + reverse_iterator rend() { return reverse_iterator{begin()}; } + const_reverse_iterator rend() const { + return const_reverse_iterator{begin()}; + } + const_reverse_iterator crend() const { + return const_reverse_iterator{cbegin()}; + } + + public: + void clear(); + iterator insert(const_iterator pos, value_type value) { + return this->insert(pos, &value, 1); + } + iterator insert(const_iterator pos, const_iterator str, Index size); + iterator insert(const_iterator pos, StringView str); + iterator erase(const_iterator pos) { return this->erase(pos, pos + 1); } + iterator erase(const_iterator start, const_iterator end); + void push_back(value_type value) { this->append(value); } + void pop_back() { this->erase(cend() - 1); } + void append(value_type value) { this->insert(cend(), value); } + void append(const_iterator str, Index size) { + this->insert(cend(), str, size); + } + inline void append(StringView str); + + String substr(size_type start, size_type size = -1) const { + if (size == -1) { + size = this->size_ - start; + } + return String(this->buffer_ + start, size); + } + + String& operator+=(value_type value) { + this->append(value); + return *this; + } + String& operator+=(StringView other); + + public: + operator std::u16string_view() const { + return std::u16string_view(data(), size()); + } + + StringView View() const; + + public: + Index Find(value_type value, Index start = 0) const; + std::vector Split(value_type separator, + bool remove_space_line = false) const; + std::vector SplitToLines(bool remove_space_line = false) const; + + bool StartWith(StringView str) const; + bool EndWith(StringView str) const; + + String& TrimStart(); + String& TrimEnd(); + String& Trim(); + + public: + void AppendCodePoint(CodePoint code_point); + + Utf16CodePointIterator CodePointIterator() const { + return Utf16CodePointIterator(buffer_, size_); + } + + Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; + Index IndexFromCodePointToCodeUnit(Index code_point_index) const; + Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; + Range RangeFromCodePointToCodeUnit(Range code_point_range) const; + + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + std::vector ParseToFloatList(value_type separator = u' ') const; + std::vector ParseToDoubleList(value_type separator = u' ') const; + +#ifdef CRU_PLATFORM_WINDOWS + const wchar_t* WinCStr() const { + return reinterpret_cast(c_str()); + } +#endif + + template + String Format(T&&... args) const; + + std::string ToUtf8() const; + + int Compare(const String& other) const; + int CaseInsensitiveCompare(const String& other) const; + bool CaseInsensitiveEqual(const String& other) const { + return CaseInsensitiveCompare(other) == 0; + } + + private: + static char16_t kEmptyBuffer[1]; + + private: + char16_t* buffer_ = kEmptyBuffer; + Index size_ = 0; // not including trailing '\0' + Index capacity_ = 0; // always 1 smaller than real buffer size +}; + +class CRU_BASE_API StringView { + public: + static double_conversion::StringToDoubleConverter + kDefaultStringToDoubleConverter; + + using value_type = char16_t; + using size_type = Index; + using difference_type = Index; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using iterator = const value_type*; + using const_iterator = const value_type*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + StringView() = default; + + constexpr StringView(const_pointer ptr, Index size) + : ptr_(ptr), size_(size) {} + + template + constexpr StringView(const value_type (&array)[size]) + : StringView(array, size - 1) {} + + StringView(const String& str) : StringView(str.data(), str.size()) {} + + CRU_DEFAULT_COPY(StringView) + CRU_DEFAULT_MOVE(StringView) + + ~StringView() = default; + + bool empty() const { return size_ == 0; } + Index size() const { return size_; } + const value_type* data() const { return ptr_; } + + public: + iterator begin() { return this->ptr_; } + const_iterator begin() const { return this->ptr_; } + const_iterator cbegin() const { return this->ptr_; } + + iterator end() { return this->ptr_ + this->size_; } + const_iterator end() const { return this->ptr_ + this->size_; } + const_iterator cend() const { return this->ptr_ + this->size_; } + + reverse_iterator rbegin() { return reverse_iterator{end()}; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator{end()}; + } + const_reverse_iterator crbegin() const { + return const_reverse_iterator{cend()}; + } + + reverse_iterator rend() { return reverse_iterator{begin()}; } + const_reverse_iterator rend() const { + return const_reverse_iterator{begin()}; + } + const_reverse_iterator crend() const { + return const_reverse_iterator{cbegin()}; + } + + StringView substr(Index pos); + StringView substr(Index pos, Index size); + + value_type operator[](Index index) const { return ptr_[index]; } + + operator std::u16string_view() const { + return std::u16string_view(data(), size()); + } + + public: + int Compare(const StringView& other) const; + int CaseInsensitiveCompare(const StringView& other) const; + bool CaseInsensitiveEqual(const StringView& other) const { + return CaseInsensitiveCompare(other) == 0; + } + + String ToString() const { return String(ptr_, size_); } + + Utf16CodePointIterator CodePointIterator() const { + return Utf16CodePointIterator(ptr_, size_); + } + + Index Find(value_type value, Index start = 0) const; + std::vector Split(value_type separator, + bool remove_space_line = false) const; + std::vector SplitToLines(bool remove_space_line = false) const; + + bool StartWith(StringView str) const; + bool EndWith(StringView str) const; + + Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; + Index IndexFromCodePointToCodeUnit(Index code_point_index) const; + Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; + Range RangeFromCodePointToCodeUnit(Range code_point_range) const; + + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + std::vector ParseToFloatList(value_type separator = u' ') const; + std::vector ParseToDoubleList(value_type separator = u' ') const; + + std::string ToUtf8() const; + + private: + const char16_t* ptr_; + Index size_; +}; + +CRU_DEFINE_COMPARE_OPERATORS(String) + +inline String operator+(const String& left, const String& right) { + String result(left); + result += right; + return result; +} + +CRU_DEFINE_COMPARE_OPERATORS(StringView) + +inline String::iterator String::insert(const_iterator pos, StringView str) { + return insert(pos, str.data(), str.size()); +} + +inline void String::append(StringView str) { + this->append(str.data(), str.size()); +} + +inline String String::From(StringView str) { return str.ToString(); } + +inline String::String(StringView str) : String(str.data(), str.size()) {} + +inline String ToString(StringView value) { return value.ToString(); } + +inline CodePoint Utf16PreviousCodePoint(StringView str, Index current, + Index* previous_position) { + return Utf16PreviousCodePoint(str.data(), str.size(), current, + previous_position); +} + +inline CodePoint Utf16NextCodePoint(StringView str, Index current, + Index* next_position) { + return Utf16NextCodePoint(str.data(), str.size(), current, next_position); +} + +inline bool Utf16IsValidInsertPosition(StringView str, Index position) { + return Utf16IsValidInsertPosition(str.data(), str.size(), position); +} + +// Return position after the character making predicate returns true or 0 if no +// character doing so. +inline Index CRU_BASE_API +Utf16BackwardUntil(StringView str, Index position, + const std::function& predicate) { + return Utf16BackwardUntil(str.data(), str.size(), position, predicate); +} +// Return position before the character making predicate returns true or +// str.size() if no character doing so. +inline Index CRU_BASE_API +Utf16ForwardUntil(StringView str, Index position, + const std::function& predicate) { + return Utf16ForwardUntil(str.data(), str.size(), position, predicate); +} + +inline Index Utf16PreviousWord(StringView str, Index position, + bool* is_space = nullptr) { + return Utf16PreviousWord(str.data(), str.size(), position, is_space); +} + +inline Index Utf16NextWord(StringView str, Index position, + bool* is_space = nullptr) { + return Utf16NextWord(str.data(), str.size(), position, is_space); +} + +String CRU_BASE_API ToLower(StringView s); +String CRU_BASE_API ToUpper(StringView s); +} // namespace cru + +template <> +struct std::hash { + std::size_t operator()(const cru::String& value) const { + return std::hash{}(std::u16string_view( + reinterpret_cast(value.data()), value.size())); + } +}; + +template <> +struct std::hash { + std::size_t operator()(const cru::StringView& value) const { + return std::hash{}(std::u16string_view( + reinterpret_cast(value.data()), value.size())); + } +}; diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp deleted file mode 100644 index c1f957c0..00000000 --- a/include/cru/common/String.hpp +++ /dev/null @@ -1,436 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "Range.hpp" -#include "StringUtil.hpp" - -#include -#include -#include -#include -#include -#include -#include - -namespace cru { -class StringView; - -class CRU_BASE_API String { - public: - using value_type = char16_t; - using size_type = Index; - using difference_type = Index; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; - using iterator = value_type*; - using const_iterator = const value_type*; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - public: - static String FromUtf8(const char* str); - static String FromUtf8(const char* str, Index size); - static String FromUtf8(std::string_view str) { - return FromUtf8(str.data(), str.size()); - } - - static String FromUtf16(const char16_t* str) { return String(str); } - static String FromUtf16(const char16_t* str, Index size) { - return String(str, size); - } - static String FromUtf16(std::u16string_view str) { - return FromUtf16(str.data(), str.size()); - } - - static inline String From(StringView str); - - // Never use this if you don't know what this mean! - static String FromBuffer(pointer buffer, Index size, Index capacity) { - return String{from_buffer_tag{}, buffer, size, capacity}; - } - - static String FromStdPath(const std::filesystem::path& path); - -#ifdef CRU_PLATFORM_WINDOWS - static String FromUtf16(wchar_t* str) { return String(str); } - static String FromUtf16(wchar_t* str, Index size) { - return String(str, size); - } -#endif - - public: - String() = default; - - explicit String(const_pointer str); - String(const_pointer str, size_type size); - - template - String(const char16_t (&str)[size]) - : String(reinterpret_cast(str), size - 1) {} - - template - String(Iter start, Iter end) { - for (; start != end; start++) { - append(*start); - } - } - - String(size_type size, value_type ch = 0); - - String(std::initializer_list l); - - explicit String(StringView str); - -#ifdef CRU_PLATFORM_WINDOWS - String(const wchar_t* str); - String(const wchar_t* str, Index size); - String(const std::wstring& str) : String(str.data(), str.size()) {} -#endif - - String(const String& other); - String(String&& other) noexcept; - - String& operator=(const String& other); - String& operator=(String&& other) noexcept; - - ~String(); - - private: - struct from_buffer_tag {}; - String(from_buffer_tag, pointer buffer, Index size, Index capacity); - - public: - bool empty() const { return this->size_ == 0; } - Index size() const { return this->size_; } - Index length() const { return this->size(); } - Index capacity() const { return this->capacity_; } - pointer data() { return this->buffer_; } - const_pointer data() const { return this->buffer_; } - - void resize(Index new_size); - void reserve(Index new_capacity); - void shrink_to_fit(); - - reference front() { return this->operator[](0); } - const_reference front() const { return this->operator[](0); } - - reference back() { return this->operator[](size_ - 1); } - const_reference back() const { return this->operator[](size_ - 1); } - - const_pointer c_str() const { return buffer_; } - - reference operator[](Index index) { return buffer_[index]; } - const_reference operator[](Index index) const { return buffer_[index]; } - - public: - iterator begin() { return this->buffer_; } - const_iterator begin() const { return this->buffer_; } - const_iterator cbegin() const { return this->buffer_; } - - iterator end() { return this->buffer_ + this->size_; } - const_iterator end() const { return this->buffer_ + this->size_; } - const_iterator cend() const { return this->buffer_ + this->size_; } - - reverse_iterator rbegin() { return reverse_iterator{end()}; } - const_reverse_iterator rbegin() const { - return const_reverse_iterator{end()}; - } - const_reverse_iterator crbegin() const { - return const_reverse_iterator{cend()}; - } - - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rend() const { - return const_reverse_iterator{begin()}; - } - const_reverse_iterator crend() const { - return const_reverse_iterator{cbegin()}; - } - - public: - void clear(); - iterator insert(const_iterator pos, value_type value) { - return this->insert(pos, &value, 1); - } - iterator insert(const_iterator pos, const_iterator str, Index size); - iterator insert(const_iterator pos, StringView str); - iterator erase(const_iterator pos) { return this->erase(pos, pos + 1); } - iterator erase(const_iterator start, const_iterator end); - void push_back(value_type value) { this->append(value); } - void pop_back() { this->erase(cend() - 1); } - void append(value_type value) { this->insert(cend(), value); } - void append(const_iterator str, Index size) { - this->insert(cend(), str, size); - } - inline void append(StringView str); - - String substr(size_type start, size_type size = -1) const { - if (size == -1) { - size = this->size_ - start; - } - return String(this->buffer_ + start, size); - } - - String& operator+=(value_type value) { - this->append(value); - return *this; - } - String& operator+=(StringView other); - - public: - operator std::u16string_view() const { - return std::u16string_view(data(), size()); - } - - StringView View() const; - - public: - Index Find(value_type value, Index start = 0) const; - std::vector Split(value_type separator, - bool remove_space_line = false) const; - std::vector SplitToLines(bool remove_space_line = false) const; - - bool StartWith(StringView str) const; - bool EndWith(StringView str) const; - - String& TrimStart(); - String& TrimEnd(); - String& Trim(); - - public: - void AppendCodePoint(CodePoint code_point); - - Utf16CodePointIterator CodePointIterator() const { - return Utf16CodePointIterator(buffer_, size_); - } - - Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; - Index IndexFromCodePointToCodeUnit(Index code_point_index) const; - Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; - Range RangeFromCodePointToCodeUnit(Range code_point_range) const; - - float ParseToFloat(Index* processed_characters_count = nullptr) const; - double ParseToDouble(Index* processed_characters_count = nullptr) const; - std::vector ParseToFloatList(value_type separator = u' ') const; - std::vector ParseToDoubleList(value_type separator = u' ') const; - -#ifdef CRU_PLATFORM_WINDOWS - const wchar_t* WinCStr() const { - return reinterpret_cast(c_str()); - } -#endif - - template - String Format(T&&... args) const; - - std::string ToUtf8() const; - - int Compare(const String& other) const; - int CaseInsensitiveCompare(const String& other) const; - bool CaseInsensitiveEqual(const String& other) const { - return CaseInsensitiveCompare(other) == 0; - } - - private: - static char16_t kEmptyBuffer[1]; - - private: - char16_t* buffer_ = kEmptyBuffer; - Index size_ = 0; // not including trailing '\0' - Index capacity_ = 0; // always 1 smaller than real buffer size -}; - -class CRU_BASE_API StringView { - public: - static double_conversion::StringToDoubleConverter - kDefaultStringToDoubleConverter; - - using value_type = char16_t; - using size_type = Index; - using difference_type = Index; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; - using iterator = const value_type*; - using const_iterator = const value_type*; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - StringView() = default; - - constexpr StringView(const_pointer ptr, Index size) - : ptr_(ptr), size_(size) {} - - template - constexpr StringView(const value_type (&array)[size]) - : StringView(array, size - 1) {} - - StringView(const String& str) : StringView(str.data(), str.size()) {} - - CRU_DEFAULT_COPY(StringView) - CRU_DEFAULT_MOVE(StringView) - - ~StringView() = default; - - bool empty() const { return size_ == 0; } - Index size() const { return size_; } - const value_type* data() const { return ptr_; } - - public: - iterator begin() { return this->ptr_; } - const_iterator begin() const { return this->ptr_; } - const_iterator cbegin() const { return this->ptr_; } - - iterator end() { return this->ptr_ + this->size_; } - const_iterator end() const { return this->ptr_ + this->size_; } - const_iterator cend() const { return this->ptr_ + this->size_; } - - reverse_iterator rbegin() { return reverse_iterator{end()}; } - const_reverse_iterator rbegin() const { - return const_reverse_iterator{end()}; - } - const_reverse_iterator crbegin() const { - return const_reverse_iterator{cend()}; - } - - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rend() const { - return const_reverse_iterator{begin()}; - } - const_reverse_iterator crend() const { - return const_reverse_iterator{cbegin()}; - } - - StringView substr(Index pos); - StringView substr(Index pos, Index size); - - value_type operator[](Index index) const { return ptr_[index]; } - - operator std::u16string_view() const { - return std::u16string_view(data(), size()); - } - - public: - int Compare(const StringView& other) const; - int CaseInsensitiveCompare(const StringView& other) const; - bool CaseInsensitiveEqual(const StringView& other) const { - return CaseInsensitiveCompare(other) == 0; - } - - String ToString() const { return String(ptr_, size_); } - - Utf16CodePointIterator CodePointIterator() const { - return Utf16CodePointIterator(ptr_, size_); - } - - Index Find(value_type value, Index start = 0) const; - std::vector Split(value_type separator, - bool remove_space_line = false) const; - std::vector SplitToLines(bool remove_space_line = false) const; - - bool StartWith(StringView str) const; - bool EndWith(StringView str) const; - - Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; - Index IndexFromCodePointToCodeUnit(Index code_point_index) const; - Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; - Range RangeFromCodePointToCodeUnit(Range code_point_range) const; - - float ParseToFloat(Index* processed_characters_count = nullptr) const; - double ParseToDouble(Index* processed_characters_count = nullptr) const; - std::vector ParseToFloatList(value_type separator = u' ') const; - std::vector ParseToDoubleList(value_type separator = u' ') const; - - std::string ToUtf8() const; - - private: - const char16_t* ptr_; - Index size_; -}; - -CRU_DEFINE_COMPARE_OPERATORS(String) - -inline String operator+(const String& left, const String& right) { - String result(left); - result += right; - return result; -} - -CRU_DEFINE_COMPARE_OPERATORS(StringView) - -inline String::iterator String::insert(const_iterator pos, StringView str) { - return insert(pos, str.data(), str.size()); -} - -inline void String::append(StringView str) { - this->append(str.data(), str.size()); -} - -inline String String::From(StringView str) { return str.ToString(); } - -inline String::String(StringView str) : String(str.data(), str.size()) {} - -inline String ToString(StringView value) { return value.ToString(); } - -inline CodePoint Utf16PreviousCodePoint(StringView str, Index current, - Index* previous_position) { - return Utf16PreviousCodePoint(str.data(), str.size(), current, - previous_position); -} - -inline CodePoint Utf16NextCodePoint(StringView str, Index current, - Index* next_position) { - return Utf16NextCodePoint(str.data(), str.size(), current, next_position); -} - -inline bool Utf16IsValidInsertPosition(StringView str, Index position) { - return Utf16IsValidInsertPosition(str.data(), str.size(), position); -} - -// Return position after the character making predicate returns true or 0 if no -// character doing so. -inline Index CRU_BASE_API -Utf16BackwardUntil(StringView str, Index position, - const std::function& predicate) { - return Utf16BackwardUntil(str.data(), str.size(), position, predicate); -} -// Return position before the character making predicate returns true or -// str.size() if no character doing so. -inline Index CRU_BASE_API -Utf16ForwardUntil(StringView str, Index position, - const std::function& predicate) { - return Utf16ForwardUntil(str.data(), str.size(), position, predicate); -} - -inline Index Utf16PreviousWord(StringView str, Index position, - bool* is_space = nullptr) { - return Utf16PreviousWord(str.data(), str.size(), position, is_space); -} - -inline Index Utf16NextWord(StringView str, Index position, - bool* is_space = nullptr) { - return Utf16NextWord(str.data(), str.size(), position, is_space); -} - -String CRU_BASE_API ToLower(StringView s); -String CRU_BASE_API ToUpper(StringView s); -} // namespace cru - -template <> -struct std::hash { - std::size_t operator()(const cru::String& value) const { - return std::hash{}(std::u16string_view( - reinterpret_cast(value.data()), value.size())); - } -}; - -template <> -struct std::hash { - std::size_t operator()(const cru::StringView& value) const { - return std::hash{}(std::u16string_view( - reinterpret_cast(value.data()), value.size())); - } -}; diff --git a/include/cru/common/StringUtil.h b/include/cru/common/StringUtil.h new file mode 100644 index 00000000..19948250 --- /dev/null +++ b/include/cru/common/StringUtil.h @@ -0,0 +1,223 @@ +#pragma once +#include "Base.h" + +#include + +namespace cru { +using CodePoint = std::int32_t; +constexpr CodePoint k_invalid_code_point = -1; + +inline bool IsUtf16SurrogatePairCodeUnit(char16_t c) { + return c >= 0xD800 && c <= 0xDFFF; +} + +inline bool IsUtf16SurrogatePairLeading(char16_t c) { + return c >= 0xD800 && c <= 0xDBFF; +} + +inline bool IsUtf16SurrogatePairTrailing(char16_t c) { + return c >= 0xDC00 && c <= 0xDFFF; +} + +CodePoint CRU_BASE_API Utf8NextCodePoint(const char* ptr, Index size, + Index current, Index* next_position); + +CodePoint CRU_BASE_API Utf16NextCodePoint(const char16_t* ptr, Index size, + Index current, Index* next_position); +CodePoint CRU_BASE_API Utf16PreviousCodePoint(const char16_t* ptr, Index size, + Index current, + Index* previous_position); + +template +using NextCodePointFunctionType = CodePoint (*)(const CharType*, Index, Index, + Index*); + +template NextCodePointFunction> +class CodePointIterator { + public: + using difference_type = Index; + using value_type = CodePoint; + using pointer = void; + using reference = value_type; + using iterator_category = std::forward_iterator_tag; + + public: + struct past_end_tag_t {}; + + explicit CodePointIterator(const CharType* ptr, Index size, Index current = 0) + : ptr_(ptr), size_(size), position_(current) {} + explicit CodePointIterator(const CharType* ptr, Index size, past_end_tag_t) + : ptr_(ptr), size_(size), position_(size) {} + + CRU_DEFAULT_COPY(CodePointIterator) + CRU_DEFAULT_MOVE(CodePointIterator) + + ~CodePointIterator() = default; + + public: + const CharType* GetPtr() const { return ptr_; } + Index GetSize() const { return size_; } + Index GetPosition() const { return position_; } + + bool IsPastEnd() const { return position_ == static_cast(size_); } + + public: + CodePointIterator begin() const { return *this; } + CodePointIterator end() const { + return CodePointIterator{ptr_, size_, past_end_tag_t{}}; + } + + public: + bool operator==(const CodePointIterator& other) const { + // You should compare iterator that iterate on the same string. + Expects(this->ptr_ == other.ptr_ && this->size_ == other.size_); + return this->position_ == other.position_; + } + bool operator!=(const CodePointIterator& other) const { + return !this->operator==(other); + } + + CodePointIterator& operator++() { + Expects(!IsPastEnd()); + Forward(); + return *this; + } + + CodePointIterator operator++(int) { + Expects(!IsPastEnd()); + CodePointIterator old = *this; + Forward(); + return old; + } + + CodePoint operator*() const { + return NextCodePointFunction(ptr_, size_, position_, &next_position_cache_); + } + + private: + void Forward() { + if (next_position_cache_ > position_) { + position_ = next_position_cache_; + } else { + NextCodePointFunction(ptr_, size_, position_, &position_); + } + } + + private: + const CharType* ptr_; + Index size_; + Index position_; + mutable Index next_position_cache_ = 0; +}; + +using Utf8CodePointIterator = CodePointIterator; + +using Utf16CodePointIterator = CodePointIterator; + +namespace details { +template +inline std::enable_if_t, ReturnType> ExtractBits( + UInt n) { + return static_cast(n & ((1u << number_of_bit) - 1)); +} +} // namespace details + +template +bool Utf8EncodeCodePointAppend(CodePoint code_point, TStr& str) { + auto write_continue_byte = [&str](std::uint8_t byte6) { + str.push_back((1u << 7) + (((1u << 6) - 1) & byte6)); + }; + + if (code_point >= 0 && code_point <= 0x007F) { + str.push_back(static_cast(code_point)); + return true; + } else if (code_point >= 0x0080 && code_point <= 0x07FF) { + std::uint32_t unsigned_code_point = code_point; + str.push_back( + static_cast(details::ExtractBits( + (unsigned_code_point >> 6)) + + 0b11000000)); + write_continue_byte(details::ExtractBits( + unsigned_code_point)); + return true; + } else if (code_point >= 0x0800 && code_point <= 0xFFFF) { + std::uint32_t unsigned_code_point = code_point; + str.push_back( + static_cast(details::ExtractBits( + (unsigned_code_point >> (6 * 2))) + + 0b11100000)); + write_continue_byte(details::ExtractBits( + unsigned_code_point >> 6)); + write_continue_byte(details::ExtractBits( + unsigned_code_point)); + return true; + } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { + std::uint32_t unsigned_code_point = code_point; + str.push_back( + static_cast(details::ExtractBits( + (unsigned_code_point >> (6 * 3))) + + 0b11110000)); + write_continue_byte(details::ExtractBits( + unsigned_code_point >> (6 * 2))); + write_continue_byte(details::ExtractBits( + unsigned_code_point >> 6)); + write_continue_byte(details::ExtractBits( + unsigned_code_point)); + return true; + } else { + return false; + } +} + +template +bool Utf16EncodeCodePointAppend(CodePoint code_point, TStr& str) { + if ((code_point >= 0 && code_point <= 0xD7FF) || + (code_point >= 0xE000 && code_point <= 0xFFFF)) { + str.push_back(static_cast(code_point)); + return true; + } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { + std::uint32_t u = code_point - 0x10000; + str.push_back(static_cast( + details::ExtractBits(u >> 10) + + 0xD800u)); + str.push_back(static_cast( + details::ExtractBits(u) + 0xDC00u)); + return true; + } else { + return false; + } +} + +// If given s is not a valid utf16 string, return value is UD. +bool CRU_BASE_API Utf16IsValidInsertPosition(const char16_t* ptr, Index size, + Index position); + +// Return position after the character making predicate returns true or 0 if no +// character doing so. +Index CRU_BASE_API +Utf16BackwardUntil(const char16_t* ptr, Index size, Index position, + const std::function& predicate); +// Return position before the character making predicate returns true or +// str.size() if no character doing so. +Index CRU_BASE_API +Utf16ForwardUntil(const char16_t* ptr, Index size, Index position, + const std::function& predicate); + +Index CRU_BASE_API Utf16PreviousWord(const char16_t* ptr, Index size, + Index position, bool* is_space = nullptr); +Index CRU_BASE_API Utf16NextWord(const char16_t* ptr, Index size, + Index position, bool* is_space = nullptr); + +char16_t CRU_BASE_API ToLower(char16_t c); +char16_t CRU_BASE_API ToUpper(char16_t c); + +bool CRU_BASE_API IsWhitespace(char16_t c); +bool CRU_BASE_API IsDigit(char16_t c); + +Utf8CodePointIterator CRU_BASE_API CreateUtf8Iterator(const std::byte* buffer, + Index size); +Utf8CodePointIterator CRU_BASE_API +CreateUtf8Iterator(const std::vector& buffer); + +} // namespace cru diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp deleted file mode 100644 index c840960d..00000000 --- a/include/cru/common/StringUtil.hpp +++ /dev/null @@ -1,223 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include - -namespace cru { -using CodePoint = std::int32_t; -constexpr CodePoint k_invalid_code_point = -1; - -inline bool IsUtf16SurrogatePairCodeUnit(char16_t c) { - return c >= 0xD800 && c <= 0xDFFF; -} - -inline bool IsUtf16SurrogatePairLeading(char16_t c) { - return c >= 0xD800 && c <= 0xDBFF; -} - -inline bool IsUtf16SurrogatePairTrailing(char16_t c) { - return c >= 0xDC00 && c <= 0xDFFF; -} - -CodePoint CRU_BASE_API Utf8NextCodePoint(const char* ptr, Index size, - Index current, Index* next_position); - -CodePoint CRU_BASE_API Utf16NextCodePoint(const char16_t* ptr, Index size, - Index current, Index* next_position); -CodePoint CRU_BASE_API Utf16PreviousCodePoint(const char16_t* ptr, Index size, - Index current, - Index* previous_position); - -template -using NextCodePointFunctionType = CodePoint (*)(const CharType*, Index, Index, - Index*); - -template NextCodePointFunction> -class CodePointIterator { - public: - using difference_type = Index; - using value_type = CodePoint; - using pointer = void; - using reference = value_type; - using iterator_category = std::forward_iterator_tag; - - public: - struct past_end_tag_t {}; - - explicit CodePointIterator(const CharType* ptr, Index size, Index current = 0) - : ptr_(ptr), size_(size), position_(current) {} - explicit CodePointIterator(const CharType* ptr, Index size, past_end_tag_t) - : ptr_(ptr), size_(size), position_(size) {} - - CRU_DEFAULT_COPY(CodePointIterator) - CRU_DEFAULT_MOVE(CodePointIterator) - - ~CodePointIterator() = default; - - public: - const CharType* GetPtr() const { return ptr_; } - Index GetSize() const { return size_; } - Index GetPosition() const { return position_; } - - bool IsPastEnd() const { return position_ == static_cast(size_); } - - public: - CodePointIterator begin() const { return *this; } - CodePointIterator end() const { - return CodePointIterator{ptr_, size_, past_end_tag_t{}}; - } - - public: - bool operator==(const CodePointIterator& other) const { - // You should compare iterator that iterate on the same string. - Expects(this->ptr_ == other.ptr_ && this->size_ == other.size_); - return this->position_ == other.position_; - } - bool operator!=(const CodePointIterator& other) const { - return !this->operator==(other); - } - - CodePointIterator& operator++() { - Expects(!IsPastEnd()); - Forward(); - return *this; - } - - CodePointIterator operator++(int) { - Expects(!IsPastEnd()); - CodePointIterator old = *this; - Forward(); - return old; - } - - CodePoint operator*() const { - return NextCodePointFunction(ptr_, size_, position_, &next_position_cache_); - } - - private: - void Forward() { - if (next_position_cache_ > position_) { - position_ = next_position_cache_; - } else { - NextCodePointFunction(ptr_, size_, position_, &position_); - } - } - - private: - const CharType* ptr_; - Index size_; - Index position_; - mutable Index next_position_cache_ = 0; -}; - -using Utf8CodePointIterator = CodePointIterator; - -using Utf16CodePointIterator = CodePointIterator; - -namespace details { -template -inline std::enable_if_t, ReturnType> ExtractBits( - UInt n) { - return static_cast(n & ((1u << number_of_bit) - 1)); -} -} // namespace details - -template -bool Utf8EncodeCodePointAppend(CodePoint code_point, TStr& str) { - auto write_continue_byte = [&str](std::uint8_t byte6) { - str.push_back((1u << 7) + (((1u << 6) - 1) & byte6)); - }; - - if (code_point >= 0 && code_point <= 0x007F) { - str.push_back(static_cast(code_point)); - return true; - } else if (code_point >= 0x0080 && code_point <= 0x07FF) { - std::uint32_t unsigned_code_point = code_point; - str.push_back( - static_cast(details::ExtractBits( - (unsigned_code_point >> 6)) + - 0b11000000)); - write_continue_byte(details::ExtractBits( - unsigned_code_point)); - return true; - } else if (code_point >= 0x0800 && code_point <= 0xFFFF) { - std::uint32_t unsigned_code_point = code_point; - str.push_back( - static_cast(details::ExtractBits( - (unsigned_code_point >> (6 * 2))) + - 0b11100000)); - write_continue_byte(details::ExtractBits( - unsigned_code_point >> 6)); - write_continue_byte(details::ExtractBits( - unsigned_code_point)); - return true; - } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { - std::uint32_t unsigned_code_point = code_point; - str.push_back( - static_cast(details::ExtractBits( - (unsigned_code_point >> (6 * 3))) + - 0b11110000)); - write_continue_byte(details::ExtractBits( - unsigned_code_point >> (6 * 2))); - write_continue_byte(details::ExtractBits( - unsigned_code_point >> 6)); - write_continue_byte(details::ExtractBits( - unsigned_code_point)); - return true; - } else { - return false; - } -} - -template -bool Utf16EncodeCodePointAppend(CodePoint code_point, TStr& str) { - if ((code_point >= 0 && code_point <= 0xD7FF) || - (code_point >= 0xE000 && code_point <= 0xFFFF)) { - str.push_back(static_cast(code_point)); - return true; - } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { - std::uint32_t u = code_point - 0x10000; - str.push_back(static_cast( - details::ExtractBits(u >> 10) + - 0xD800u)); - str.push_back(static_cast( - details::ExtractBits(u) + 0xDC00u)); - return true; - } else { - return false; - } -} - -// If given s is not a valid utf16 string, return value is UD. -bool CRU_BASE_API Utf16IsValidInsertPosition(const char16_t* ptr, Index size, - Index position); - -// Return position after the character making predicate returns true or 0 if no -// character doing so. -Index CRU_BASE_API -Utf16BackwardUntil(const char16_t* ptr, Index size, Index position, - const std::function& predicate); -// Return position before the character making predicate returns true or -// str.size() if no character doing so. -Index CRU_BASE_API -Utf16ForwardUntil(const char16_t* ptr, Index size, Index position, - const std::function& predicate); - -Index CRU_BASE_API Utf16PreviousWord(const char16_t* ptr, Index size, - Index position, bool* is_space = nullptr); -Index CRU_BASE_API Utf16NextWord(const char16_t* ptr, Index size, - Index position, bool* is_space = nullptr); - -char16_t CRU_BASE_API ToLower(char16_t c); -char16_t CRU_BASE_API ToUpper(char16_t c); - -bool CRU_BASE_API IsWhitespace(char16_t c); -bool CRU_BASE_API IsDigit(char16_t c); - -Utf8CodePointIterator CRU_BASE_API CreateUtf8Iterator(const std::byte* buffer, - Index size); -Utf8CodePointIterator CRU_BASE_API -CreateUtf8Iterator(const std::vector& buffer); - -} // namespace cru diff --git a/include/cru/common/io/FileStream.h b/include/cru/common/io/FileStream.h new file mode 100644 index 00000000..4f1499be --- /dev/null +++ b/include/cru/common/io/FileStream.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef CRU_PLATFORM_UNIX +#include "../platform/unix/UnixFileStream.h" +namespace cru::io { +using FileStream = platform::unix::UnixFileStream; +} +#elif CRU_PLATFORM_WINDOWS +#include "../platform/win/Win32FileStream.h" +namespace cru::io { +using FileStream = platform::win::Win32FileStream; +} +#endif diff --git a/include/cru/common/io/FileStream.hpp b/include/cru/common/io/FileStream.hpp deleted file mode 100644 index 86c4c037..00000000 --- a/include/cru/common/io/FileStream.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifdef CRU_PLATFORM_UNIX -#include "../platform/unix/UnixFileStream.hpp" -namespace cru::io { -using FileStream = platform::unix::UnixFileStream; -} -#elif CRU_PLATFORM_WINDOWS -#include "../platform/win/Win32FileStream.hpp" -namespace cru::io { -using FileStream = platform::win::Win32FileStream; -} -#endif diff --git a/include/cru/common/io/MemoryStream.h b/include/cru/common/io/MemoryStream.h new file mode 100644 index 00000000..a6243d67 --- /dev/null +++ b/include/cru/common/io/MemoryStream.h @@ -0,0 +1,44 @@ +#pragma once + +#include "Stream.h" + +#include + +namespace cru::io { +class CRU_BASE_API MemoryStream : public Stream { + public: + MemoryStream() = default; + MemoryStream( + std::byte* buffer, Index size, bool read_only = false, + std::function release_func = {}) + : buffer_(buffer), + size_(size), + read_only_(read_only), + release_func_(std::move(release_func)) {} + + CRU_DELETE_COPY(MemoryStream) + CRU_DELETE_MOVE(MemoryStream) + + ~MemoryStream() override; + + public: + bool CanSeek() override; + Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + + bool CanRead() override; + Index Read(std::byte* buffer, Index offset, Index size) override; + + bool CanWrite() override; + Index Write(const std::byte* buffer, Index offset, Index size) override; + + std::byte* GetBuffer() const { return buffer_; } + Index GetSize() override { return size_; } + + private: + std::byte* buffer_ = nullptr; + Index size_ = 0; + Index position_ = 0; + bool read_only_ = false; + std::function release_func_; +}; +} // namespace cru::io diff --git a/include/cru/common/io/MemoryStream.hpp b/include/cru/common/io/MemoryStream.hpp deleted file mode 100644 index 29da7b9f..00000000 --- a/include/cru/common/io/MemoryStream.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "Stream.hpp" - -#include - -namespace cru::io { -class CRU_BASE_API MemoryStream : public Stream { - public: - MemoryStream() = default; - MemoryStream( - std::byte* buffer, Index size, bool read_only = false, - std::function release_func = {}) - : buffer_(buffer), - size_(size), - read_only_(read_only), - release_func_(std::move(release_func)) {} - - CRU_DELETE_COPY(MemoryStream) - CRU_DELETE_MOVE(MemoryStream) - - ~MemoryStream() override; - - public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - - std::byte* GetBuffer() const { return buffer_; } - Index GetSize() override { return size_; } - - private: - std::byte* buffer_ = nullptr; - Index size_ = 0; - Index position_ = 0; - bool read_only_ = false; - std::function release_func_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/OpenFileFlag.h b/include/cru/common/io/OpenFileFlag.h new file mode 100644 index 00000000..b0bceddc --- /dev/null +++ b/include/cru/common/io/OpenFileFlag.h @@ -0,0 +1,18 @@ +#pragma once + +#include "../Bitmask.h" + +namespace cru::io { +namespace details { +struct OpenFileFlagTag {}; +} // namespace details +using OpenFileFlag = Bitmask; + +struct OpenFileFlags { + static constexpr OpenFileFlag Read{0x1}; + static constexpr OpenFileFlag Write{0x2}; + static constexpr OpenFileFlag Append{0x4}; + static constexpr OpenFileFlag Create{0x8}; + static constexpr OpenFileFlag ThrowOnExist{0x10}; +}; +} // namespace cru::io diff --git a/include/cru/common/io/OpenFileFlag.hpp b/include/cru/common/io/OpenFileFlag.hpp deleted file mode 100644 index 3319bb4f..00000000 --- a/include/cru/common/io/OpenFileFlag.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "../Bitmask.hpp" - -namespace cru::io { -namespace details { -struct OpenFileFlagTag {}; -} // namespace details -using OpenFileFlag = Bitmask; - -struct OpenFileFlags { - static constexpr OpenFileFlag Read{0x1}; - static constexpr OpenFileFlag Write{0x2}; - static constexpr OpenFileFlag Append{0x4}; - static constexpr OpenFileFlag Create{0x8}; - static constexpr OpenFileFlag ThrowOnExist{0x10}; -}; -} // namespace cru::io diff --git a/include/cru/common/io/Resource.h b/include/cru/common/io/Resource.h new file mode 100644 index 00000000..1d5313a6 --- /dev/null +++ b/include/cru/common/io/Resource.h @@ -0,0 +1,8 @@ +#pragma once +#include "../Base.h" + +#include + +namespace cru::io { +std::filesystem::path CRU_BASE_API GetResourceDir(); +} diff --git a/include/cru/common/io/Resource.hpp b/include/cru/common/io/Resource.hpp deleted file mode 100644 index 4fd00bdd..00000000 --- a/include/cru/common/io/Resource.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include - -namespace cru::io { -std::filesystem::path CRU_BASE_API GetResourceDir(); -} diff --git a/include/cru/common/io/Stream.h b/include/cru/common/io/Stream.h new file mode 100644 index 00000000..66be4468 --- /dev/null +++ b/include/cru/common/io/Stream.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../Base.h" + +#include "../String.h" + +#include +#include + +namespace cru::io { +class CRU_BASE_API Stream : public Object { + public: + enum class SeekOrigin { Current, Begin, End }; + + Stream() = default; + + CRU_DELETE_COPY(Stream) + CRU_DELETE_MOVE(Stream) + + ~Stream() override = default; + + public: + virtual bool CanSeek() = 0; + virtual Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) = 0; + virtual Index Tell(); + virtual void Rewind(); + virtual Index GetSize(); + + virtual bool CanRead() = 0; + virtual Index Read(std::byte* buffer, Index offset, Index size) = 0; + virtual Index Read(std::byte* buffer, Index size); + + virtual bool CanWrite() = 0; + virtual Index Write(const std::byte* buffer, Index offset, Index size) = 0; + virtual Index Write(const std::byte* buffer, Index size); + Index Write(const char* buffer, Index offset, Index size); + Index Write(const char* buffer, Index size); + + virtual std::vector ReadAll(); + + // Utf8 encoding. + String ReadAllAsString(); + + virtual void Flush(); + + virtual void Close(); +}; +} // namespace cru::io diff --git a/include/cru/common/io/Stream.hpp b/include/cru/common/io/Stream.hpp deleted file mode 100644 index 131e82e9..00000000 --- a/include/cru/common/io/Stream.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "../Base.hpp" - -#include "../String.hpp" - -#include -#include - -namespace cru::io { -class CRU_BASE_API Stream : public Object { - public: - enum class SeekOrigin { Current, Begin, End }; - - Stream() = default; - - CRU_DELETE_COPY(Stream) - CRU_DELETE_MOVE(Stream) - - ~Stream() override = default; - - public: - virtual bool CanSeek() = 0; - virtual Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) = 0; - virtual Index Tell(); - virtual void Rewind(); - virtual Index GetSize(); - - virtual bool CanRead() = 0; - virtual Index Read(std::byte* buffer, Index offset, Index size) = 0; - virtual Index Read(std::byte* buffer, Index size); - - virtual bool CanWrite() = 0; - virtual Index Write(const std::byte* buffer, Index offset, Index size) = 0; - virtual Index Write(const std::byte* buffer, Index size); - Index Write(const char* buffer, Index offset, Index size); - Index Write(const char* buffer, Index size); - - virtual std::vector ReadAll(); - - // Utf8 encoding. - String ReadAllAsString(); - - virtual void Flush(); - - virtual void Close(); -}; -} // namespace cru::io diff --git a/include/cru/common/platform/Exception.h b/include/cru/common/platform/Exception.h new file mode 100644 index 00000000..c1b649f3 --- /dev/null +++ b/include/cru/common/platform/Exception.h @@ -0,0 +1,15 @@ +#pragma once +#include "../Base.h" +#include "../Exception.h" + +namespace cru::platform { +class CRU_BASE_API PlatformException : public Exception { + public: + using Exception::Exception; // inherit constructors + + CRU_DEFAULT_COPY(PlatformException) + CRU_DEFAULT_MOVE(PlatformException) + + CRU_DEFAULT_DESTRUCTOR(PlatformException) +}; +} // namespace cru::platform diff --git a/include/cru/common/platform/Exception.hpp b/include/cru/common/platform/Exception.hpp deleted file mode 100644 index 0241947b..00000000 --- a/include/cru/common/platform/Exception.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "../Base.hpp" -#include "../Exception.hpp" - -namespace cru::platform { -class CRU_BASE_API PlatformException : public Exception { - public: - using Exception::Exception; // inherit constructors - - CRU_DEFAULT_COPY(PlatformException) - CRU_DEFAULT_MOVE(PlatformException) - - CRU_DEFAULT_DESTRUCTOR(PlatformException) -}; -} // namespace cru::platform diff --git a/include/cru/common/platform/osx/Convert.h b/include/cru/common/platform/osx/Convert.h new file mode 100644 index 00000000..503576be --- /dev/null +++ b/include/cru/common/platform/osx/Convert.h @@ -0,0 +1,17 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_OSX + +#include "../../String.h" + +#include + +namespace cru::platform::osx { +CFStringRef Convert(const String& string); +String Convert(CFStringRef string); + +CFRange Convert(const Range& range); +Range Convert(const CFRange& range); +} // namespace cru::platform::osx + +#endif diff --git a/include/cru/common/platform/osx/Convert.hpp b/include/cru/common/platform/osx/Convert.hpp deleted file mode 100644 index a2d8beae..00000000 --- a/include/cru/common/platform/osx/Convert.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_OSX - -#include "../../String.hpp" - -#include - -namespace cru::platform::osx { -CFStringRef Convert(const String& string); -String Convert(CFStringRef string); - -CFRange Convert(const Range& range); -Range Convert(const CFRange& range); -} // namespace cru::platform::osx - -#endif diff --git a/include/cru/common/platform/osx/Exception.h b/include/cru/common/platform/osx/Exception.h new file mode 100644 index 00000000..53e874e9 --- /dev/null +++ b/include/cru/common/platform/osx/Exception.h @@ -0,0 +1,14 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_OSX + +#include "../Exception.h" + +namespace cru::platform::osx { +class OsxException : public PlatformException { + public: + using PlatformException::PlatformException; +}; +} // namespace cru::platform::osx + +#endif diff --git a/include/cru/common/platform/osx/Exception.hpp b/include/cru/common/platform/osx/Exception.hpp deleted file mode 100644 index 49527c69..00000000 --- a/include/cru/common/platform/osx/Exception.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_OSX - -#include "../Exception.hpp" - -namespace cru::platform::osx { -class OsxException : public PlatformException { - public: - using PlatformException::PlatformException; -}; -} // namespace cru::platform::osx - -#endif diff --git a/include/cru/common/platform/unix/ErrnoException.h b/include/cru/common/platform/unix/ErrnoException.h new file mode 100644 index 00000000..00e1864b --- /dev/null +++ b/include/cru/common/platform/unix/ErrnoException.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_UNIX + +#include "../Exception.h" + +namespace cru::platform::unix { +class ErrnoException : public PlatformException { + public: + ErrnoException() : ErrnoException(String{}) {} + explicit ErrnoException(const String& message); + ErrnoException(const String& message, int errno_code); + + CRU_DELETE_COPY(ErrnoException) + CRU_DELETE_MOVE(ErrnoException) + + ~ErrnoException() override = default; + + int GetErrnoCode() const { return errno_code_; } + + private: + int errno_code_; +}; +} // namespace cru::platform::unix + +#endif diff --git a/include/cru/common/platform/unix/ErrnoException.hpp b/include/cru/common/platform/unix/ErrnoException.hpp deleted file mode 100644 index 2982e26a..00000000 --- a/include/cru/common/platform/unix/ErrnoException.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_UNIX - -#include "../Exception.hpp" - -namespace cru::platform::unix { -class ErrnoException : public PlatformException { - public: - ErrnoException() : ErrnoException(String{}) {} - explicit ErrnoException(const String& message); - ErrnoException(const String& message, int errno_code); - - CRU_DELETE_COPY(ErrnoException) - CRU_DELETE_MOVE(ErrnoException) - - ~ErrnoException() override = default; - - int GetErrnoCode() const { return errno_code_; } - - private: - int errno_code_; -}; -} // namespace cru::platform::unix - -#endif diff --git a/include/cru/common/platform/unix/UnixFileStream.h b/include/cru/common/platform/unix/UnixFileStream.h new file mode 100644 index 00000000..0c8ef340 --- /dev/null +++ b/include/cru/common/platform/unix/UnixFileStream.h @@ -0,0 +1,46 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_UNIX + +#include "../../String.h" +#include "../../io/OpenFileFlag.h" +#include "../../io/Stream.h" + +namespace cru::platform::unix { +class UnixFileStream : public io::Stream { + public: + UnixFileStream(String path, io::OpenFileFlag flags); + + CRU_DELETE_COPY(UnixFileStream) + CRU_DELETE_MOVE(UnixFileStream) + + ~UnixFileStream() override; + + public: + bool CanSeek() override; + Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + + bool CanRead() override; + Index Read(std::byte* buffer, Index offset, Index size) override; + using Stream::Read; + + bool CanWrite() override; + Index Write(const std::byte* buffer, Index offset, Index size) override; + using Stream::Write; + + void Close() override; + + private: + void CheckClosed(); + + private: + String path_; + io::OpenFileFlag flags_; + int file_descriptor_; + bool closed_ = false; +}; +} // namespace cru::platform::unix + +#endif diff --git a/include/cru/common/platform/unix/UnixFileStream.hpp b/include/cru/common/platform/unix/UnixFileStream.hpp deleted file mode 100644 index 76355f2f..00000000 --- a/include/cru/common/platform/unix/UnixFileStream.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_UNIX - -#include "../../String.hpp" -#include "../../io/OpenFileFlag.hpp" -#include "../../io/Stream.hpp" - -namespace cru::platform::unix { -class UnixFileStream : public io::Stream { - public: - UnixFileStream(String path, io::OpenFileFlag flags); - - CRU_DELETE_COPY(UnixFileStream) - CRU_DELETE_MOVE(UnixFileStream) - - ~UnixFileStream() override; - - public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - using Stream::Read; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - using Stream::Write; - - void Close() override; - - private: - void CheckClosed(); - - private: - String path_; - io::OpenFileFlag flags_; - int file_descriptor_; - bool closed_ = false; -}; -} // namespace cru::platform::unix - -#endif diff --git a/include/cru/common/platform/win/ComAutoInit.h b/include/cru/common/platform/win/ComAutoInit.h new file mode 100644 index 00000000..cc968e4b --- /dev/null +++ b/include/cru/common/platform/win/ComAutoInit.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_WINDOWS + +#include "WinPreConfig.h" +#include "cru/common/Base.h" + +namespace cru::platform::win { +class CRU_BASE_API ComAutoInit { + public: + ComAutoInit(); + + CRU_DELETE_COPY(ComAutoInit) + CRU_DELETE_MOVE(ComAutoInit) + + ~ComAutoInit(); +}; +} // namespace cru::platform::win + +#endif diff --git a/include/cru/common/platform/win/ComAutoInit.hpp b/include/cru/common/platform/win/ComAutoInit.hpp deleted file mode 100644 index 131f3f30..00000000 --- a/include/cru/common/platform/win/ComAutoInit.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.hpp" -#include "cru/common/Base.hpp" - -namespace cru::platform::win { -class CRU_BASE_API ComAutoInit { - public: - ComAutoInit(); - - CRU_DELETE_COPY(ComAutoInit) - CRU_DELETE_MOVE(ComAutoInit) - - ~ComAutoInit(); -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/Exception.h b/include/cru/common/platform/win/Exception.h new file mode 100644 index 00000000..3e63b191 --- /dev/null +++ b/include/cru/common/platform/win/Exception.h @@ -0,0 +1,56 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_WINDOWS + +#include "WinPreConfig.h" + +#include "../Exception.h" + +#include +#include + +namespace cru::platform::win { +class CRU_BASE_API HResultError : public platform::PlatformException { + public: + explicit HResultError(HRESULT h_result); + explicit HResultError(HRESULT h_result, std::string_view message); + + CRU_DEFAULT_COPY(HResultError) + CRU_DEFAULT_MOVE(HResultError) + + ~HResultError() override = default; + + HRESULT GetHResult() const { return h_result_; } + + private: + HRESULT h_result_; +}; + +inline void ThrowIfFailed(const HRESULT h_result) { + if (FAILED(h_result)) throw HResultError(h_result); +} + +inline void ThrowIfFailed(const HRESULT h_result, std::string_view message) { + if (FAILED(h_result)) throw HResultError(h_result, message); +} + +class CRU_BASE_API Win32Error : public platform::PlatformException { + public: + // ::GetLastError is automatically called to get the error code. + // The same as Win32Error(::GetLastError(), message) + explicit Win32Error(String message); + Win32Error(DWORD error_code, String message); + + CRU_DEFAULT_COPY(Win32Error) + CRU_DEFAULT_MOVE(Win32Error) + + ~Win32Error() override = default; + + DWORD GetErrorCode() const { return error_code_; } + + private: + DWORD error_code_; +}; +} // namespace cru::platform::win + +#endif diff --git a/include/cru/common/platform/win/Exception.hpp b/include/cru/common/platform/win/Exception.hpp deleted file mode 100644 index 4e332b4f..00000000 --- a/include/cru/common/platform/win/Exception.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.hpp" - -#include "../Exception.hpp" - -#include -#include - -namespace cru::platform::win { -class CRU_BASE_API HResultError : public platform::PlatformException { - public: - explicit HResultError(HRESULT h_result); - explicit HResultError(HRESULT h_result, std::string_view message); - - CRU_DEFAULT_COPY(HResultError) - CRU_DEFAULT_MOVE(HResultError) - - ~HResultError() override = default; - - HRESULT GetHResult() const { return h_result_; } - - private: - HRESULT h_result_; -}; - -inline void ThrowIfFailed(const HRESULT h_result) { - if (FAILED(h_result)) throw HResultError(h_result); -} - -inline void ThrowIfFailed(const HRESULT h_result, std::string_view message) { - if (FAILED(h_result)) throw HResultError(h_result, message); -} - -class CRU_BASE_API Win32Error : public platform::PlatformException { - public: - // ::GetLastError is automatically called to get the error code. - // The same as Win32Error(::GetLastError(), message) - explicit Win32Error(String message); - Win32Error(DWORD error_code, String message); - - CRU_DEFAULT_COPY(Win32Error) - CRU_DEFAULT_MOVE(Win32Error) - - ~Win32Error() override = default; - - DWORD GetErrorCode() const { return error_code_; } - - private: - DWORD error_code_; -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/StreamConvert.h b/include/cru/common/platform/win/StreamConvert.h new file mode 100644 index 00000000..3499604a --- /dev/null +++ b/include/cru/common/platform/win/StreamConvert.h @@ -0,0 +1,14 @@ +#pragma once +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_WINDOWS + +#include "../../io/Stream.h" + +#include + +namespace cru::platform::win { +CRU_BASE_API IStream* ConvertStreamToComStream(io::Stream* stream); +} + +#endif diff --git a/include/cru/common/platform/win/StreamConvert.hpp b/include/cru/common/platform/win/StreamConvert.hpp deleted file mode 100644 index 80800115..00000000 --- a/include/cru/common/platform/win/StreamConvert.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_WINDOWS - -#include "../../io/Stream.hpp" - -#include - -namespace cru::platform::win { -CRU_BASE_API IStream* ConvertStreamToComStream(io::Stream* stream); -} - -#endif diff --git a/include/cru/common/platform/win/Win32FileStream.h b/include/cru/common/platform/win/Win32FileStream.h new file mode 100644 index 00000000..521fd58d --- /dev/null +++ b/include/cru/common/platform/win/Win32FileStream.h @@ -0,0 +1,54 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_WINDOWS + +#include "../../String.h" +#include "../../io/OpenFileFlag.h" +#include "../../io/Stream.h" + +namespace cru::platform::win { +namespace details { +class Win32FileStreamPrivate; +} + +class CRU_BASE_API Win32FileStream : public io::Stream { + public: + Win32FileStream(String path, io::OpenFileFlag flags); + + CRU_DELETE_COPY(Win32FileStream) + CRU_DELETE_MOVE(Win32FileStream) + + ~Win32FileStream() override; + + public: + bool CanSeek() override; + Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + + bool CanRead() override; + Index Read(std::byte* buffer, Index offset, Index size) override; + using Stream::Read; + + bool CanWrite() override; + Index Write(const std::byte* buffer, Index offset, Index size) override; + using Stream::Write; + + void Close() override; + + String GetPath() const { return path_; } + io::OpenFileFlag GetOpenFileFlags() const { return flags_; } + + private: + void CheckClosed(); + + private: + String path_; + io::OpenFileFlag flags_; + bool closed_ = false; + + details::Win32FileStreamPrivate* p_; +}; +} // namespace cru::platform::win + +#endif diff --git a/include/cru/common/platform/win/Win32FileStream.hpp b/include/cru/common/platform/win/Win32FileStream.hpp deleted file mode 100644 index b5511ba3..00000000 --- a/include/cru/common/platform/win/Win32FileStream.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_WINDOWS - -#include "../../String.hpp" -#include "../../io/OpenFileFlag.hpp" -#include "../../io/Stream.hpp" - -namespace cru::platform::win { -namespace details { -class Win32FileStreamPrivate; -} - -class CRU_BASE_API Win32FileStream : public io::Stream { - public: - Win32FileStream(String path, io::OpenFileFlag flags); - - CRU_DELETE_COPY(Win32FileStream) - CRU_DELETE_MOVE(Win32FileStream) - - ~Win32FileStream() override; - - public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - using Stream::Read; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - using Stream::Write; - - void Close() override; - - String GetPath() const { return path_; } - io::OpenFileFlag GetOpenFileFlags() const { return flags_; } - - private: - void CheckClosed(); - - private: - String path_; - io::OpenFileFlag flags_; - bool closed_ = false; - - details::Win32FileStreamPrivate* p_; -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/WinPreConfig.h b/include/cru/common/platform/win/WinPreConfig.h new file mode 100644 index 00000000..c2284df3 --- /dev/null +++ b/include/cru/common/platform/win/WinPreConfig.h @@ -0,0 +1,13 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_WINDOWS + +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include +#undef CreateWindow +#undef DrawText +#undef CreateFont +#undef CreateEvent + +#endif diff --git a/include/cru/common/platform/win/WinPreConfig.hpp b/include/cru/common/platform/win/WinPreConfig.hpp deleted file mode 100644 index ac397820..00000000 --- a/include/cru/common/platform/win/WinPreConfig.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_WINDOWS - -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN -#include -#undef CreateWindow -#undef DrawText -#undef CreateFont -#undef CreateEvent - -#endif diff --git a/include/cru/osx/Convert.h b/include/cru/osx/Convert.h new file mode 100644 index 00000000..bf32174a --- /dev/null +++ b/include/cru/osx/Convert.h @@ -0,0 +1,2 @@ +#pragma once +#include "cru/common/platform/osx/Convert.h" diff --git a/include/cru/osx/Convert.hpp b/include/cru/osx/Convert.hpp deleted file mode 100644 index ec1d5d6b..00000000 --- a/include/cru/osx/Convert.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#include "cru/common/platform/osx/Convert.hpp" diff --git a/include/cru/osx/Exception.h b/include/cru/osx/Exception.h new file mode 100644 index 00000000..c346b970 --- /dev/null +++ b/include/cru/osx/Exception.h @@ -0,0 +1,3 @@ +#pragma once +#include "cru/common/platform/osx/Exception.h" +#include "cru/platform/Exception.h" diff --git a/include/cru/osx/Exception.hpp b/include/cru/osx/Exception.hpp deleted file mode 100644 index 5776ab72..00000000 --- a/include/cru/osx/Exception.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -#include "cru/common/platform/osx/Exception.hpp" -#include "cru/platform/Exception.hpp" diff --git a/include/cru/osx/Resource.h b/include/cru/osx/Resource.h new file mode 100644 index 00000000..d30ee31b --- /dev/null +++ b/include/cru/osx/Resource.h @@ -0,0 +1,13 @@ +#pragma once +#include "cru/platform/Resource.h" + +namespace cru::platform::osx { +class OsxResource : public Object, public virtual IPlatformResource { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(OsxResource) + CRU_DELETE_COPY(OsxResource) + CRU_DELETE_MOVE(OsxResource) + + String GetPlatformId() const override { return u"OSX"; } +}; +} // namespace cru::platform::osx diff --git a/include/cru/osx/Resource.hpp b/include/cru/osx/Resource.hpp deleted file mode 100644 index b1f673f8..00000000 --- a/include/cru/osx/Resource.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "cru/platform/Resource.hpp" - -namespace cru::platform::osx { -class OsxResource : public Object, public virtual IPlatformResource { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(OsxResource) - CRU_DELETE_COPY(OsxResource) - CRU_DELETE_MOVE(OsxResource) - - String GetPlatformId() const override { return u"OSX"; } -}; -} // namespace cru::platform::osx diff --git a/include/cru/osx/graphics/quartz/Brush.h b/include/cru/osx/graphics/quartz/Brush.h new file mode 100644 index 00000000..677a0b6c --- /dev/null +++ b/include/cru/osx/graphics/quartz/Brush.h @@ -0,0 +1,47 @@ +#pragma once +#include "Resource.h" +#include "cru/common/Base.h" +#include "cru/platform/graphics/Base.h" +#include "cru/platform/graphics/Brush.h" + +#include + +#include + +namespace cru::platform::graphics::osx::quartz { +class QuartzBrush : public OsxQuartzResource, public virtual IBrush { + public: + QuartzBrush(IGraphicsFactory* graphics_factory) + : OsxQuartzResource(graphics_factory) {} + CRU_DELETE_COPY(QuartzBrush) + CRU_DELETE_MOVE(QuartzBrush) + ~QuartzBrush() override = default; + + public: + virtual void Select(CGContextRef context) = 0; +}; + +class QuartzSolidColorBrush : public QuartzBrush, + public virtual ISolidColorBrush { + public: + QuartzSolidColorBrush(IGraphicsFactory* graphics_factory, const Color& color); + + CRU_DELETE_COPY(QuartzSolidColorBrush) + CRU_DELETE_MOVE(QuartzSolidColorBrush) + + ~QuartzSolidColorBrush() override; + + Color GetColor() override { return color_; } + void SetColor(const Color& color) override; + + CGColorRef GetCGColorRef() const { return cg_color_; } + + void Select(CGContextRef context) override; + + String GetDebugString() override; + + private: + Color color_; + CGColorRef cg_color_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Brush.hpp b/include/cru/osx/graphics/quartz/Brush.hpp deleted file mode 100644 index 1fa26794..00000000 --- a/include/cru/osx/graphics/quartz/Brush.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/Base.hpp" -#include "cru/platform/graphics/Brush.hpp" - -#include - -#include - -namespace cru::platform::graphics::osx::quartz { -class QuartzBrush : public OsxQuartzResource, public virtual IBrush { - public: - QuartzBrush(IGraphicsFactory* graphics_factory) - : OsxQuartzResource(graphics_factory) {} - CRU_DELETE_COPY(QuartzBrush) - CRU_DELETE_MOVE(QuartzBrush) - ~QuartzBrush() override = default; - - public: - virtual void Select(CGContextRef context) = 0; -}; - -class QuartzSolidColorBrush : public QuartzBrush, - public virtual ISolidColorBrush { - public: - QuartzSolidColorBrush(IGraphicsFactory* graphics_factory, const Color& color); - - CRU_DELETE_COPY(QuartzSolidColorBrush) - CRU_DELETE_MOVE(QuartzSolidColorBrush) - - ~QuartzSolidColorBrush() override; - - Color GetColor() override { return color_; } - void SetColor(const Color& color) override; - - CGColorRef GetCGColorRef() const { return cg_color_; } - - void Select(CGContextRef context) override; - - String GetDebugString() override; - - private: - Color color_; - CGColorRef cg_color_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Convert.h b/include/cru/osx/graphics/quartz/Convert.h new file mode 100644 index 00000000..8d486069 --- /dev/null +++ b/include/cru/osx/graphics/quartz/Convert.h @@ -0,0 +1,23 @@ +#pragma once +#include "cru/common/Range.h" +#include "cru/common/String.h" +#include "cru/common/io/Stream.h" +#include "cru/platform/Matrix.h" + +#include + +namespace cru::platform::graphics::osx::quartz { +CGAffineTransform Convert(const Matrix& matrix); +Matrix Convert(const CGAffineTransform& matrix); + +CGPoint Convert(const Point& point); +Point Convert(const CGPoint& point); + +CGSize Convert(const Size& size); +Size Convert(const CGSize& size); + +CGRect Convert(const Rect& rect); +Rect Convert(const CGRect& rect); + +CGDataProviderRef ConvertStreamToCGDataProvider(io::Stream* stream); +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Convert.hpp b/include/cru/osx/graphics/quartz/Convert.hpp deleted file mode 100644 index ba2b1be1..00000000 --- a/include/cru/osx/graphics/quartz/Convert.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "cru/common/Range.hpp" -#include "cru/common/String.hpp" -#include "cru/common/io/Stream.hpp" -#include "cru/platform/Matrix.hpp" - -#include - -namespace cru::platform::graphics::osx::quartz { -CGAffineTransform Convert(const Matrix& matrix); -Matrix Convert(const CGAffineTransform& matrix); - -CGPoint Convert(const Point& point); -Point Convert(const CGPoint& point); - -CGSize Convert(const Size& size); -Size Convert(const CGSize& size); - -CGRect Convert(const Rect& rect); -Rect Convert(const CGRect& rect); - -CGDataProviderRef ConvertStreamToCGDataProvider(io::Stream* stream); -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Factory.h b/include/cru/osx/graphics/quartz/Factory.h new file mode 100644 index 00000000..1a5abdc1 --- /dev/null +++ b/include/cru/osx/graphics/quartz/Factory.h @@ -0,0 +1,35 @@ +#pragma once +#include "Resource.h" +#include "cru/common/Base.h" +#include "cru/osx/graphics/quartz/ImageFactory.h" +#include "cru/platform/graphics/Factory.h" +#include "cru/platform/graphics/ImageFactory.h" + +namespace cru::platform::graphics::osx::quartz { +class QuartzGraphicsFactory : public OsxQuartzResource, + public virtual IGraphicsFactory { + public: + QuartzGraphicsFactory(); + + CRU_DELETE_COPY(QuartzGraphicsFactory) + CRU_DELETE_MOVE(QuartzGraphicsFactory) + + ~QuartzGraphicsFactory() override; + + public: + std::unique_ptr CreateSolidColorBrush() override; + + std::unique_ptr CreateGeometryBuilder() override; + + std::unique_ptr CreateFont(String font_family, + float font_size) override; + + std::unique_ptr CreateTextLayout(std::shared_ptr font, + String text) override; + + IImageFactory* GetImageFactory() override; + + private: + std::unique_ptr image_factory_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Factory.hpp b/include/cru/osx/graphics/quartz/Factory.hpp deleted file mode 100644 index 59433b54..00000000 --- a/include/cru/osx/graphics/quartz/Factory.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/common/Base.hpp" -#include "cru/osx/graphics/quartz/ImageFactory.hpp" -#include "cru/platform/graphics/Factory.hpp" -#include "cru/platform/graphics/ImageFactory.hpp" - -namespace cru::platform::graphics::osx::quartz { -class QuartzGraphicsFactory : public OsxQuartzResource, - public virtual IGraphicsFactory { - public: - QuartzGraphicsFactory(); - - CRU_DELETE_COPY(QuartzGraphicsFactory) - CRU_DELETE_MOVE(QuartzGraphicsFactory) - - ~QuartzGraphicsFactory() override; - - public: - std::unique_ptr CreateSolidColorBrush() override; - - std::unique_ptr CreateGeometryBuilder() override; - - std::unique_ptr CreateFont(String font_family, - float font_size) override; - - std::unique_ptr CreateTextLayout(std::shared_ptr font, - String text) override; - - IImageFactory* GetImageFactory() override; - - private: - std::unique_ptr image_factory_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Font.h b/include/cru/osx/graphics/quartz/Font.h new file mode 100644 index 00000000..d53c6a20 --- /dev/null +++ b/include/cru/osx/graphics/quartz/Font.h @@ -0,0 +1,25 @@ +#pragma once +#include "Resource.h" +#include "cru/common/Base.h" +#include "cru/platform/graphics/Font.h" + +#include + +namespace cru::platform::graphics::osx::quartz { +class OsxCTFont : public OsxQuartzResource, public virtual IFont { + public: + OsxCTFont(IGraphicsFactory* graphics_factory, const String& name, float size); + + CRU_DELETE_COPY(OsxCTFont) + CRU_DELETE_MOVE(OsxCTFont) + + ~OsxCTFont() override; + + CTFontRef GetCTFont() const { return ct_font_; } + + float GetFontSize() override; + + private: + CTFontRef ct_font_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Font.hpp b/include/cru/osx/graphics/quartz/Font.hpp deleted file mode 100644 index 1ea2b891..00000000 --- a/include/cru/osx/graphics/quartz/Font.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/Font.hpp" - -#include - -namespace cru::platform::graphics::osx::quartz { -class OsxCTFont : public OsxQuartzResource, public virtual IFont { - public: - OsxCTFont(IGraphicsFactory* graphics_factory, const String& name, float size); - - CRU_DELETE_COPY(OsxCTFont) - CRU_DELETE_MOVE(OsxCTFont) - - ~OsxCTFont() override; - - CTFontRef GetCTFont() const { return ct_font_; } - - float GetFontSize() override; - - private: - CTFontRef ct_font_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Geometry.h b/include/cru/osx/graphics/quartz/Geometry.h new file mode 100644 index 00000000..8e42491b --- /dev/null +++ b/include/cru/osx/graphics/quartz/Geometry.h @@ -0,0 +1,48 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/graphics/Geometry.h" + +#include + +#include + +namespace cru::platform::graphics::osx::quartz { +class QuartzGeometry : public OsxQuartzResource, public virtual IGeometry { + public: + QuartzGeometry(IGraphicsFactory *graphics_factory, CGPathRef cg_path); + + CRU_DELETE_COPY(QuartzGeometry) + CRU_DELETE_MOVE(QuartzGeometry) + + ~QuartzGeometry() override; + + CGPathRef GetCGPath() const { return cg_path_; } + + bool FillContains(const Point &point) override; + + private: + CGPathRef cg_path_; +}; + +class QuartzGeometryBuilder : public OsxQuartzResource, + public virtual IGeometryBuilder { + public: + explicit QuartzGeometryBuilder(IGraphicsFactory *graphics_factory); + + CRU_DELETE_COPY(QuartzGeometryBuilder) + CRU_DELETE_MOVE(QuartzGeometryBuilder) + + ~QuartzGeometryBuilder() override; + + void BeginFigure(const Point &point) override; + void CloseFigure(bool close) override; + void LineTo(const Point &point) override; + void QuadraticBezierTo(const Point &control_point, + const Point &end_point) override; + + std::unique_ptr Build() override; + + private: + CGMutablePathRef cg_mutable_path_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Geometry.hpp b/include/cru/osx/graphics/quartz/Geometry.hpp deleted file mode 100644 index 565c5b86..00000000 --- a/include/cru/osx/graphics/quartz/Geometry.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/graphics/Geometry.hpp" - -#include - -#include - -namespace cru::platform::graphics::osx::quartz { -class QuartzGeometry : public OsxQuartzResource, public virtual IGeometry { - public: - QuartzGeometry(IGraphicsFactory *graphics_factory, CGPathRef cg_path); - - CRU_DELETE_COPY(QuartzGeometry) - CRU_DELETE_MOVE(QuartzGeometry) - - ~QuartzGeometry() override; - - CGPathRef GetCGPath() const { return cg_path_; } - - bool FillContains(const Point &point) override; - - private: - CGPathRef cg_path_; -}; - -class QuartzGeometryBuilder : public OsxQuartzResource, - public virtual IGeometryBuilder { - public: - explicit QuartzGeometryBuilder(IGraphicsFactory *graphics_factory); - - CRU_DELETE_COPY(QuartzGeometryBuilder) - CRU_DELETE_MOVE(QuartzGeometryBuilder) - - ~QuartzGeometryBuilder() override; - - void BeginFigure(const Point &point) override; - void CloseFigure(bool close) override; - void LineTo(const Point &point) override; - void QuadraticBezierTo(const Point &control_point, - const Point &end_point) override; - - std::unique_ptr Build() override; - - private: - CGMutablePathRef cg_mutable_path_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Image.h b/include/cru/osx/graphics/quartz/Image.h new file mode 100644 index 00000000..458f5db0 --- /dev/null +++ b/include/cru/osx/graphics/quartz/Image.h @@ -0,0 +1,32 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/graphics/Image.h" +#include "cru/platform/graphics/ImageFactory.h" + +#include + +namespace cru::platform::graphics::osx::quartz { +class QuartzImage : public OsxQuartzResource, public virtual IImage { + public: + QuartzImage(IGraphicsFactory* graphics_factory, IImageFactory* image_factory, + CGImageRef image, bool auto_release); + + CRU_DELETE_COPY(QuartzImage) + CRU_DELETE_MOVE(QuartzImage) + + ~QuartzImage() override; + + public: + float GetWidth() override; + float GetHeight() override; + + std::unique_ptr CreateWithRect(const Rect& rect) override; + + CGImageRef GetCGImage() const { return image_; } + + private: + IImageFactory* image_factory_; + CGImageRef image_; + bool auto_release_ = false; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Image.hpp b/include/cru/osx/graphics/quartz/Image.hpp deleted file mode 100644 index 62b7fa8b..00000000 --- a/include/cru/osx/graphics/quartz/Image.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/graphics/Image.hpp" -#include "cru/platform/graphics/ImageFactory.hpp" - -#include - -namespace cru::platform::graphics::osx::quartz { -class QuartzImage : public OsxQuartzResource, public virtual IImage { - public: - QuartzImage(IGraphicsFactory* graphics_factory, IImageFactory* image_factory, - CGImageRef image, bool auto_release); - - CRU_DELETE_COPY(QuartzImage) - CRU_DELETE_MOVE(QuartzImage) - - ~QuartzImage() override; - - public: - float GetWidth() override; - float GetHeight() override; - - std::unique_ptr CreateWithRect(const Rect& rect) override; - - CGImageRef GetCGImage() const { return image_; } - - private: - IImageFactory* image_factory_; - CGImageRef image_; - bool auto_release_ = false; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/ImageFactory.h b/include/cru/osx/graphics/quartz/ImageFactory.h new file mode 100644 index 00000000..e9854738 --- /dev/null +++ b/include/cru/osx/graphics/quartz/ImageFactory.h @@ -0,0 +1,19 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/graphics/ImageFactory.h" + +namespace cru::platform::graphics::osx::quartz { +class QuartzImageFactory : public OsxQuartzResource, + public virtual IImageFactory { + public: + explicit QuartzImageFactory(IGraphicsFactory* graphics_factory); + + CRU_DELETE_COPY(QuartzImageFactory) + CRU_DELETE_MOVE(QuartzImageFactory) + + ~QuartzImageFactory() override; + + public: + std::unique_ptr DecodeFromStream(io::Stream* stream) override; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/ImageFactory.hpp b/include/cru/osx/graphics/quartz/ImageFactory.hpp deleted file mode 100644 index 027f3f2a..00000000 --- a/include/cru/osx/graphics/quartz/ImageFactory.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/graphics/ImageFactory.hpp" - -namespace cru::platform::graphics::osx::quartz { -class QuartzImageFactory : public OsxQuartzResource, - public virtual IImageFactory { - public: - explicit QuartzImageFactory(IGraphicsFactory* graphics_factory); - - CRU_DELETE_COPY(QuartzImageFactory) - CRU_DELETE_MOVE(QuartzImageFactory) - - ~QuartzImageFactory() override; - - public: - std::unique_ptr DecodeFromStream(io::Stream* stream) override; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Painter.h b/include/cru/osx/graphics/quartz/Painter.h new file mode 100644 index 00000000..19428583 --- /dev/null +++ b/include/cru/osx/graphics/quartz/Painter.h @@ -0,0 +1,83 @@ +#pragma once +#include "Resource.h" +#include "cru/common/Base.h" +#include "cru/platform/graphics/Base.h" +#include "cru/platform/graphics/Painter.h" + +#include + +#include + +namespace cru::platform::graphics::osx::quartz { +class QuartzCGContextPainter : public OsxQuartzResource, + public virtual IPainter { + CRU_DEFINE_CLASS_LOG_TAG( + u"cru::platform::graphics::osx::quartz::QuartzCGContextPainter") + + public: + explicit QuartzCGContextPainter( + IGraphicsFactory* graphics_factory, CGContextRef cg_context, + bool auto_release, const Size& size, + std::function on_end_draw); + + CRU_DELETE_COPY(QuartzCGContextPainter) + CRU_DELETE_MOVE(QuartzCGContextPainter) + + ~QuartzCGContextPainter() override; + + public: + Matrix GetTransform() override; + void SetTransform(const Matrix& matrix) override; + + void ConcatTransform(const Matrix& matrix) override; + + void Clear(const Color& color) override; + + void DrawLine(const Point& start, const Point& end, IBrush* brush, + float width) override; + void StrokeRectangle(const Rect& rectangle, IBrush* brush, + float width) override; + void FillRectangle(const Rect& rectangle, IBrush* brush) override; + void StrokeEllipse(const Rect& outline_rect, IBrush* brush, + float width) override; + void FillEllipse(const Rect& outline_rect, IBrush* brush) override; + + void StrokeGeometry(IGeometry* geometry, IBrush* brush, float width) override; + void FillGeometry(IGeometry* geometry, IBrush* brush) override; + + void DrawText(const Point& offset, ITextLayout* text_layout, + IBrush* brush) override; + + void DrawImage(const Point& offset, IImage* image) override; + + void PushLayer(const Rect& bounds) override; + + void PopLayer() override; + + void EndDraw() override; + + void PushState() override; + + void PopState() override; + + private: + void SetLineWidth(float width); + + void DoEndDraw(); + + void Validate(); + + private: + CGContextRef cg_context_; + + bool auto_release_; + + Size size_; + + Matrix transform_; + + std::function on_end_draw_; + + std::vector clip_stack_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Painter.hpp b/include/cru/osx/graphics/quartz/Painter.hpp deleted file mode 100644 index e5b8e767..00000000 --- a/include/cru/osx/graphics/quartz/Painter.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/Base.hpp" -#include "cru/platform/graphics/Painter.hpp" - -#include - -#include - -namespace cru::platform::graphics::osx::quartz { -class QuartzCGContextPainter : public OsxQuartzResource, - public virtual IPainter { - CRU_DEFINE_CLASS_LOG_TAG( - u"cru::platform::graphics::osx::quartz::QuartzCGContextPainter") - - public: - explicit QuartzCGContextPainter( - IGraphicsFactory* graphics_factory, CGContextRef cg_context, - bool auto_release, const Size& size, - std::function on_end_draw); - - CRU_DELETE_COPY(QuartzCGContextPainter) - CRU_DELETE_MOVE(QuartzCGContextPainter) - - ~QuartzCGContextPainter() override; - - public: - Matrix GetTransform() override; - void SetTransform(const Matrix& matrix) override; - - void ConcatTransform(const Matrix& matrix) override; - - void Clear(const Color& color) override; - - void DrawLine(const Point& start, const Point& end, IBrush* brush, - float width) override; - void StrokeRectangle(const Rect& rectangle, IBrush* brush, - float width) override; - void FillRectangle(const Rect& rectangle, IBrush* brush) override; - void StrokeEllipse(const Rect& outline_rect, IBrush* brush, - float width) override; - void FillEllipse(const Rect& outline_rect, IBrush* brush) override; - - void StrokeGeometry(IGeometry* geometry, IBrush* brush, float width) override; - void FillGeometry(IGeometry* geometry, IBrush* brush) override; - - void DrawText(const Point& offset, ITextLayout* text_layout, - IBrush* brush) override; - - void DrawImage(const Point& offset, IImage* image) override; - - void PushLayer(const Rect& bounds) override; - - void PopLayer() override; - - void EndDraw() override; - - void PushState() override; - - void PopState() override; - - private: - void SetLineWidth(float width); - - void DoEndDraw(); - - void Validate(); - - private: - CGContextRef cg_context_; - - bool auto_release_; - - Size size_; - - Matrix transform_; - - std::function on_end_draw_; - - std::vector clip_stack_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Resource.h b/include/cru/osx/graphics/quartz/Resource.h new file mode 100644 index 00000000..916a376f --- /dev/null +++ b/include/cru/osx/graphics/quartz/Resource.h @@ -0,0 +1,25 @@ +#pragma once +#include "cru/osx/Resource.h" +#include "cru/platform/graphics/Base.h" +#include "cru/platform/graphics/Resource.h" + +namespace cru::platform::graphics::osx::quartz { +class OsxQuartzResource : public platform::osx::OsxResource, + public virtual IGraphicsResource { + public: + explicit OsxQuartzResource(IGraphicsFactory* graphics_factory) + : graphics_factory_(graphics_factory) {} + + CRU_DELETE_COPY(OsxQuartzResource) + CRU_DELETE_MOVE(OsxQuartzResource) + ~OsxQuartzResource() override = default; + + public: + String GetPlatformId() const override { return u"OSX Quartz"; } + + IGraphicsFactory* GetGraphicsFactory() override { return graphics_factory_; } + + private: + IGraphicsFactory* graphics_factory_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/Resource.hpp b/include/cru/osx/graphics/quartz/Resource.hpp deleted file mode 100644 index 8b8f8bbc..00000000 --- a/include/cru/osx/graphics/quartz/Resource.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "cru/osx/Resource.hpp" -#include "cru/platform/graphics/Base.hpp" -#include "cru/platform/graphics/Resource.hpp" - -namespace cru::platform::graphics::osx::quartz { -class OsxQuartzResource : public platform::osx::OsxResource, - public virtual IGraphicsResource { - public: - explicit OsxQuartzResource(IGraphicsFactory* graphics_factory) - : graphics_factory_(graphics_factory) {} - - CRU_DELETE_COPY(OsxQuartzResource) - CRU_DELETE_MOVE(OsxQuartzResource) - ~OsxQuartzResource() override = default; - - public: - String GetPlatformId() const override { return u"OSX Quartz"; } - - IGraphicsFactory* GetGraphicsFactory() override { return graphics_factory_; } - - private: - IGraphicsFactory* graphics_factory_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/TextLayout.h b/include/cru/osx/graphics/quartz/TextLayout.h new file mode 100644 index 00000000..c0abc7f9 --- /dev/null +++ b/include/cru/osx/graphics/quartz/TextLayout.h @@ -0,0 +1,95 @@ +#pragma once +#include "Resource.h" + +#include "Font.h" +#include "cru/common/Base.h" +#include "cru/platform/graphics/TextLayout.h" + +#include + +namespace cru::platform::graphics::osx::quartz { +class OsxCTTextLayout : public OsxQuartzResource, public virtual ITextLayout { + public: + OsxCTTextLayout(IGraphicsFactory* graphics_factory, + std::shared_ptr font, const String& str); + + CRU_DELETE_COPY(OsxCTTextLayout) + CRU_DELETE_MOVE(OsxCTTextLayout) + + ~OsxCTTextLayout() override; + + public: + String GetText() override { return text_; } + void SetText(String new_text) override; + + std::shared_ptr GetFont() override { return font_; } + void SetFont(std::shared_ptr font) override; + + void SetMaxWidth(float max_width) override; + void SetMaxHeight(float max_height) override; + + bool IsEditMode() override; + void SetEditMode(bool enable) override; + + Index GetLineIndexFromCharIndex(Index char_index) override; + Index GetLineCount() override; + float GetLineHeight(Index line_index) override; + + Rect GetTextBounds(bool includingTrailingSpace = false) override; + std::vector TextRangeRect(const TextRange& text_range) override; + Rect TextSinglePoint(Index position, bool trailing) override; + TextHitTestResult HitTest(const Point& point) override; + + CTFrameRef GetCTFrameRef() const { return ct_frame_; } + + CTFrameRef CreateFrameWithColor(const Color& color); + + Matrix GetTransform() { return transform_; } + + String GetDebugString() override; + + private: + void DoSetText(String text); + + void ReleaseResource(); + void RecreateFrame(); + + CGRect DoGetTextBounds(bool includingTrailingSpace = false); + CGRect DoGetTextBoundsIncludingEmptyLines( + bool includingTrailingSpace = false); + std::vector DoTextRangeRect(const TextRange& text_range); + CGRect DoTextSinglePoint(Index position, bool trailing); + + private: + float max_width_; + float max_height_; + + bool edit_mode_; + + std::shared_ptr font_; + + String text_; + String actual_text_; + CFMutableAttributedStringRef cf_attributed_text_; + + CTFramesetterRef ct_framesetter_ = nullptr; + float suggest_height_; + CTFrameRef ct_frame_ = nullptr; + int line_count_; + std::vector line_origins_; + std::vector lines_; + std::vector line_ascents_; + std::vector line_descents_; + std::vector line_heights_; + // The empty line count in the front of the lines. + int head_empty_line_count_; + // The trailing empty line count in the back of the lines. + int tail_empty_line_count_; + + // Just for cache. + CGRect text_bounds_without_trailing_space_; + CGRect text_bounds_with_trailing_space_; + + Matrix transform_; +}; +} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/graphics/quartz/TextLayout.hpp b/include/cru/osx/graphics/quartz/TextLayout.hpp deleted file mode 100644 index 2c6347db..00000000 --- a/include/cru/osx/graphics/quartz/TextLayout.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "Font.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/TextLayout.hpp" - -#include - -namespace cru::platform::graphics::osx::quartz { -class OsxCTTextLayout : public OsxQuartzResource, public virtual ITextLayout { - public: - OsxCTTextLayout(IGraphicsFactory* graphics_factory, - std::shared_ptr font, const String& str); - - CRU_DELETE_COPY(OsxCTTextLayout) - CRU_DELETE_MOVE(OsxCTTextLayout) - - ~OsxCTTextLayout() override; - - public: - String GetText() override { return text_; } - void SetText(String new_text) override; - - std::shared_ptr GetFont() override { return font_; } - void SetFont(std::shared_ptr font) override; - - void SetMaxWidth(float max_width) override; - void SetMaxHeight(float max_height) override; - - bool IsEditMode() override; - void SetEditMode(bool enable) override; - - Index GetLineIndexFromCharIndex(Index char_index) override; - Index GetLineCount() override; - float GetLineHeight(Index line_index) override; - - Rect GetTextBounds(bool includingTrailingSpace = false) override; - std::vector TextRangeRect(const TextRange& text_range) override; - Rect TextSinglePoint(Index position, bool trailing) override; - TextHitTestResult HitTest(const Point& point) override; - - CTFrameRef GetCTFrameRef() const { return ct_frame_; } - - CTFrameRef CreateFrameWithColor(const Color& color); - - Matrix GetTransform() { return transform_; } - - String GetDebugString() override; - - private: - void DoSetText(String text); - - void ReleaseResource(); - void RecreateFrame(); - - CGRect DoGetTextBounds(bool includingTrailingSpace = false); - CGRect DoGetTextBoundsIncludingEmptyLines( - bool includingTrailingSpace = false); - std::vector DoTextRangeRect(const TextRange& text_range); - CGRect DoTextSinglePoint(Index position, bool trailing); - - private: - float max_width_; - float max_height_; - - bool edit_mode_; - - std::shared_ptr font_; - - String text_; - String actual_text_; - CFMutableAttributedStringRef cf_attributed_text_; - - CTFramesetterRef ct_framesetter_ = nullptr; - float suggest_height_; - CTFrameRef ct_frame_ = nullptr; - int line_count_; - std::vector line_origins_; - std::vector lines_; - std::vector line_ascents_; - std::vector line_descents_; - std::vector line_heights_; - // The empty line count in the front of the lines. - int head_empty_line_count_; - // The trailing empty line count in the back of the lines. - int tail_empty_line_count_; - - // Just for cache. - CGRect text_bounds_without_trailing_space_; - CGRect text_bounds_with_trailing_space_; - - Matrix transform_; -}; -} // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/osx/gui/Clipboard.h b/include/cru/osx/gui/Clipboard.h new file mode 100644 index 00000000..b4dcce4c --- /dev/null +++ b/include/cru/osx/gui/Clipboard.h @@ -0,0 +1,31 @@ +#pragma once +#include "Resource.h" + +#include "cru/platform/gui/Base.h" +#include "cru/platform/gui/Clipboard.h" + +#include + +namespace cru::platform::gui::osx { +namespace details { +class OsxClipboardPrivate; +} + +class OsxClipboard : public OsxGuiResource, public virtual IClipboard { + public: + OsxClipboard(cru::platform::gui::IUiApplication* ui_application, + std::unique_ptr p); + + CRU_DELETE_COPY(OsxClipboard) + CRU_DELETE_MOVE(OsxClipboard) + + ~OsxClipboard() override; + + public: + String GetText() override; + void SetText(String text) override; + + private: + std::unique_ptr p_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Clipboard.hpp b/include/cru/osx/gui/Clipboard.hpp deleted file mode 100644 index fea97140..00000000 --- a/include/cru/osx/gui/Clipboard.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "cru/platform/gui/Base.hpp" -#include "cru/platform/gui/Clipboard.hpp" - -#include - -namespace cru::platform::gui::osx { -namespace details { -class OsxClipboardPrivate; -} - -class OsxClipboard : public OsxGuiResource, public virtual IClipboard { - public: - OsxClipboard(cru::platform::gui::IUiApplication* ui_application, - std::unique_ptr p); - - CRU_DELETE_COPY(OsxClipboard) - CRU_DELETE_MOVE(OsxClipboard) - - ~OsxClipboard() override; - - public: - String GetText() override; - void SetText(String text) override; - - private: - std::unique_ptr p_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Cursor.h b/include/cru/osx/gui/Cursor.h new file mode 100644 index 00000000..6cfd400a --- /dev/null +++ b/include/cru/osx/gui/Cursor.h @@ -0,0 +1,43 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/gui/Cursor.h" + +#include + +namespace cru::platform::gui::osx { +namespace details { +class OsxWindowPrivate; +class OsxCursorPrivate; +class OsxCursorManagerPrivate; +} // namespace details + +class OsxCursor : public OsxGuiResource, public virtual ICursor { + friend class OsxWindow; + friend class details::OsxWindowPrivate; + + public: + OsxCursor(IUiApplication* ui_application, SystemCursorType cursor_type); + CRU_DELETE_COPY(OsxCursor) + CRU_DELETE_MOVE(OsxCursor) + + ~OsxCursor() override; + + private: + std::unique_ptr p_; +}; + +class OsxCursorManager : public OsxGuiResource, public virtual ICursorManager { + public: + explicit OsxCursorManager(IUiApplication* ui_application); + + CRU_DELETE_COPY(OsxCursorManager) + CRU_DELETE_MOVE(OsxCursorManager) + + ~OsxCursorManager() override; + + std::shared_ptr GetSystemCursor(SystemCursorType type) override; + + private: + std::unique_ptr p_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Cursor.hpp b/include/cru/osx/gui/Cursor.hpp deleted file mode 100644 index 497f5853..00000000 --- a/include/cru/osx/gui/Cursor.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/gui/Cursor.hpp" - -#include - -namespace cru::platform::gui::osx { -namespace details { -class OsxWindowPrivate; -class OsxCursorPrivate; -class OsxCursorManagerPrivate; -} // namespace details - -class OsxCursor : public OsxGuiResource, public virtual ICursor { - friend class OsxWindow; - friend class details::OsxWindowPrivate; - - public: - OsxCursor(IUiApplication* ui_application, SystemCursorType cursor_type); - CRU_DELETE_COPY(OsxCursor) - CRU_DELETE_MOVE(OsxCursor) - - ~OsxCursor() override; - - private: - std::unique_ptr p_; -}; - -class OsxCursorManager : public OsxGuiResource, public virtual ICursorManager { - public: - explicit OsxCursorManager(IUiApplication* ui_application); - - CRU_DELETE_COPY(OsxCursorManager) - CRU_DELETE_MOVE(OsxCursorManager) - - ~OsxCursorManager() override; - - std::shared_ptr GetSystemCursor(SystemCursorType type) override; - - private: - std::unique_ptr p_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/InputMethod.h b/include/cru/osx/gui/InputMethod.h new file mode 100644 index 00000000..cbfdae6c --- /dev/null +++ b/include/cru/osx/gui/InputMethod.h @@ -0,0 +1,56 @@ +#pragma once +#include "Resource.h" + +#include "cru/platform/gui/InputMethod.h" + +namespace cru::platform::gui::osx { +class OsxWindow; + +namespace details { +class OsxWindowPrivate; +class OsxInputMethodContextPrivate; +} // namespace details + +class OsxInputMethodContext : public OsxGuiResource, + public virtual IInputMethodContext { + friend OsxWindow; + friend details::OsxWindowPrivate; + friend details::OsxInputMethodContextPrivate; + + public: + explicit OsxInputMethodContext(OsxWindow* window); + + CRU_DELETE_COPY(OsxInputMethodContext) + CRU_DELETE_MOVE(OsxInputMethodContext) + + ~OsxInputMethodContext() override; + + public: + bool ShouldManuallyDrawCompositionText() override; + + void EnableIME() override; + + void DisableIME() override; + + void CompleteComposition() override; + + void CancelComposition() override; + + CompositionText GetCompositionText() override; + + void SetCandidateWindowPosition(const Point& point) override; + + IEvent* CompositionStartEvent() override; + + IEvent* CompositionEndEvent() override; + + IEvent* CompositionEvent() override; + + IEvent* TextEvent() override; + + bool IsEnabled(); + + private: + std::unique_ptr p_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/InputMethod.hpp b/include/cru/osx/gui/InputMethod.hpp deleted file mode 100644 index d184a722..00000000 --- a/include/cru/osx/gui/InputMethod.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "cru/platform/gui/InputMethod.hpp" - -namespace cru::platform::gui::osx { -class OsxWindow; - -namespace details { -class OsxWindowPrivate; -class OsxInputMethodContextPrivate; -} // namespace details - -class OsxInputMethodContext : public OsxGuiResource, - public virtual IInputMethodContext { - friend OsxWindow; - friend details::OsxWindowPrivate; - friend details::OsxInputMethodContextPrivate; - - public: - explicit OsxInputMethodContext(OsxWindow* window); - - CRU_DELETE_COPY(OsxInputMethodContext) - CRU_DELETE_MOVE(OsxInputMethodContext) - - ~OsxInputMethodContext() override; - - public: - bool ShouldManuallyDrawCompositionText() override; - - void EnableIME() override; - - void DisableIME() override; - - void CompleteComposition() override; - - void CancelComposition() override; - - CompositionText GetCompositionText() override; - - void SetCandidateWindowPosition(const Point& point) override; - - IEvent* CompositionStartEvent() override; - - IEvent* CompositionEndEvent() override; - - IEvent* CompositionEvent() override; - - IEvent* TextEvent() override; - - bool IsEnabled(); - - private: - std::unique_ptr p_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Keyboard.h b/include/cru/osx/gui/Keyboard.h new file mode 100644 index 00000000..89e0fa05 --- /dev/null +++ b/include/cru/osx/gui/Keyboard.h @@ -0,0 +1,7 @@ +#pragma once +#include "cru/platform/gui/Keyboard.h" + +namespace cru::platform::gui::osx { +KeyCode KeyCodeFromOsxToCru(unsigned short n); +unsigned short KeyCodeFromCruToOsx(KeyCode k); +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Keyboard.hpp b/include/cru/osx/gui/Keyboard.hpp deleted file mode 100644 index ae5b3ccf..00000000 --- a/include/cru/osx/gui/Keyboard.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "cru/platform/gui/Keyboard.hpp" - -namespace cru::platform::gui::osx { -KeyCode KeyCodeFromOsxToCru(unsigned short n); -unsigned short KeyCodeFromCruToOsx(KeyCode k); -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Menu.h b/include/cru/osx/gui/Menu.h new file mode 100644 index 00000000..c5cc756a --- /dev/null +++ b/include/cru/osx/gui/Menu.h @@ -0,0 +1,67 @@ +#pragma once +#include "Resource.h" + +#include "cru/platform/gui/Menu.h" + +namespace cru::platform::gui::osx { +namespace details { +struct OsxMenuItemPrivate; +struct OsxMenuPrivate; +} // namespace details + +class OsxMenu; + +class OsxMenuItem : public OsxGuiResource, public virtual IMenuItem { + friend OsxMenu; + friend details::OsxMenuPrivate; + + private: + explicit OsxMenuItem(IUiApplication* ui_application); + + public: + CRU_DELETE_COPY(OsxMenuItem) + CRU_DELETE_MOVE(OsxMenuItem) + + ~OsxMenuItem() override; + + public: + String GetTitle() override; + void SetTitle(String title) override; + bool IsEnabled() override; + void SetEnabled(bool enabled) override; + IMenu* GetParentMenu() override; + IMenu* GetSubmenu() override; + void SetKeyboardShortcut(KeyCode key, KeyModifier modifiers) override; + void DeleteKeyboardShortcut() override; + void SetOnClickHandler(std::function handler) override; + + private: + details::OsxMenuItemPrivate* p_; +}; + +class OsxMenu : public OsxGuiResource, public virtual IMenu { + friend OsxMenuItem; + friend details::OsxMenuPrivate; + friend details::OsxMenuItemPrivate; + + private: + explicit OsxMenu(IUiApplication* ui_application); + + public: + static OsxMenu* CreateOrGetApplicationMenu(IUiApplication* ui_application); + + CRU_DELETE_COPY(OsxMenu) + CRU_DELETE_MOVE(OsxMenu) + + ~OsxMenu() override; + + public: + IMenuItem* GetItemAt(int index) override; + int GetItemCount() override; + IMenuItem* CreateItemAt(int index) override; + void RemoveItemAt(int index) override; + + private: + details::OsxMenuPrivate* p_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Menu.hpp b/include/cru/osx/gui/Menu.hpp deleted file mode 100644 index fe3bf3f9..00000000 --- a/include/cru/osx/gui/Menu.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "cru/platform/gui/Menu.hpp" - -namespace cru::platform::gui::osx { -namespace details { -struct OsxMenuItemPrivate; -struct OsxMenuPrivate; -} // namespace details - -class OsxMenu; - -class OsxMenuItem : public OsxGuiResource, public virtual IMenuItem { - friend OsxMenu; - friend details::OsxMenuPrivate; - - private: - explicit OsxMenuItem(IUiApplication* ui_application); - - public: - CRU_DELETE_COPY(OsxMenuItem) - CRU_DELETE_MOVE(OsxMenuItem) - - ~OsxMenuItem() override; - - public: - String GetTitle() override; - void SetTitle(String title) override; - bool IsEnabled() override; - void SetEnabled(bool enabled) override; - IMenu* GetParentMenu() override; - IMenu* GetSubmenu() override; - void SetKeyboardShortcut(KeyCode key, KeyModifier modifiers) override; - void DeleteKeyboardShortcut() override; - void SetOnClickHandler(std::function handler) override; - - private: - details::OsxMenuItemPrivate* p_; -}; - -class OsxMenu : public OsxGuiResource, public virtual IMenu { - friend OsxMenuItem; - friend details::OsxMenuPrivate; - friend details::OsxMenuItemPrivate; - - private: - explicit OsxMenu(IUiApplication* ui_application); - - public: - static OsxMenu* CreateOrGetApplicationMenu(IUiApplication* ui_application); - - CRU_DELETE_COPY(OsxMenu) - CRU_DELETE_MOVE(OsxMenu) - - ~OsxMenu() override; - - public: - IMenuItem* GetItemAt(int index) override; - int GetItemCount() override; - IMenuItem* CreateItemAt(int index) override; - void RemoveItemAt(int index) override; - - private: - details::OsxMenuPrivate* p_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Resource.h b/include/cru/osx/gui/Resource.h new file mode 100644 index 00000000..bc3f9cd6 --- /dev/null +++ b/include/cru/osx/gui/Resource.h @@ -0,0 +1,24 @@ +#pragma once +#include "../Resource.h" + +#include "cru/platform/gui/Base.h" + +namespace cru::platform::gui::osx { +class OsxGuiResource : public platform::osx::OsxResource { + public: + explicit OsxGuiResource(IUiApplication* ui_application); + + CRU_DELETE_COPY(OsxGuiResource) + CRU_DELETE_MOVE(OsxGuiResource) + + ~OsxGuiResource() override = default; + + public: + String GetPlatformId() const override { return u"OSX GUI"; } + + IUiApplication* GetUiApplication() const { return ui_application_; } + + private: + IUiApplication* ui_application_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Resource.hpp b/include/cru/osx/gui/Resource.hpp deleted file mode 100644 index 3e44bb9b..00000000 --- a/include/cru/osx/gui/Resource.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "../Resource.hpp" - -#include "cru/platform/gui/Base.hpp" - -namespace cru::platform::gui::osx { -class OsxGuiResource : public platform::osx::OsxResource { - public: - explicit OsxGuiResource(IUiApplication* ui_application); - - CRU_DELETE_COPY(OsxGuiResource) - CRU_DELETE_MOVE(OsxGuiResource) - - ~OsxGuiResource() override = default; - - public: - String GetPlatformId() const override { return u"OSX GUI"; } - - IUiApplication* GetUiApplication() const { return ui_application_; } - - private: - IUiApplication* ui_application_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/UiApplication.h b/include/cru/osx/gui/UiApplication.h new file mode 100644 index 00000000..2d2c119c --- /dev/null +++ b/include/cru/osx/gui/UiApplication.h @@ -0,0 +1,64 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/gui/UiApplication.h" + +#include +#include + +namespace cru::platform::gui::osx { +class OsxWindow; + +namespace details { +class OsxUiApplicationPrivate; +} + +class OsxUiApplication : public OsxGuiResource, public virtual IUiApplication { + friend details::OsxUiApplicationPrivate; + friend OsxWindow; + + public: + OsxUiApplication(); + + CRU_DELETE_COPY(OsxUiApplication) + CRU_DELETE_MOVE(OsxUiApplication) + + ~OsxUiApplication() override; + + public: + int Run() override; + + void RequestQuit(int quit_code) override; + void AddOnQuitHandler(std::function handler) override; + bool IsQuitOnAllWindowClosed() override; + void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) override; + + long long SetImmediate(std::function action) override; + long long SetTimeout(std::chrono::milliseconds milliseconds, + std::function action) override; + long long SetInterval(std::chrono::milliseconds milliseconds, + std::function action) override; + void CancelTimer(long long id) override; + + std::vector GetAllWindow() override; + + INativeWindow* CreateWindow() override; + + cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override; + + ICursorManager* GetCursorManager() override; + + IClipboard* GetClipboard() override; + + IMenu* GetApplicationMenu() override; + + std::optional ShowSaveDialog(SaveDialogOptions options) override; + + std::optional> ShowOpenDialog( + OpenDialogOptions options) override; + + private: + void UnregisterWindow(OsxWindow* window); + + std::unique_ptr p_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/UiApplication.hpp b/include/cru/osx/gui/UiApplication.hpp deleted file mode 100644 index 003df8cc..00000000 --- a/include/cru/osx/gui/UiApplication.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/gui/UiApplication.hpp" - -#include -#include - -namespace cru::platform::gui::osx { -class OsxWindow; - -namespace details { -class OsxUiApplicationPrivate; -} - -class OsxUiApplication : public OsxGuiResource, public virtual IUiApplication { - friend details::OsxUiApplicationPrivate; - friend OsxWindow; - - public: - OsxUiApplication(); - - CRU_DELETE_COPY(OsxUiApplication) - CRU_DELETE_MOVE(OsxUiApplication) - - ~OsxUiApplication() override; - - public: - int Run() override; - - void RequestQuit(int quit_code) override; - void AddOnQuitHandler(std::function handler) override; - bool IsQuitOnAllWindowClosed() override; - void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) override; - - long long SetImmediate(std::function action) override; - long long SetTimeout(std::chrono::milliseconds milliseconds, - std::function action) override; - long long SetInterval(std::chrono::milliseconds milliseconds, - std::function action) override; - void CancelTimer(long long id) override; - - std::vector GetAllWindow() override; - - INativeWindow* CreateWindow() override; - - cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override; - - ICursorManager* GetCursorManager() override; - - IClipboard* GetClipboard() override; - - IMenu* GetApplicationMenu() override; - - std::optional ShowSaveDialog(SaveDialogOptions options) override; - - std::optional> ShowOpenDialog( - OpenDialogOptions options) override; - - private: - void UnregisterWindow(OsxWindow* window); - - std::unique_ptr p_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Window.h b/include/cru/osx/gui/Window.h new file mode 100644 index 00000000..6cefbe8e --- /dev/null +++ b/include/cru/osx/gui/Window.h @@ -0,0 +1,90 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/gui/Base.h" +#include "cru/platform/gui/InputMethod.h" +#include "cru/platform/gui/Window.h" + +#include + +namespace cru::platform::gui::osx { +namespace details { +class OsxWindowPrivate; +class OsxInputMethodContextPrivate; +} // namespace details + +class OsxUiApplication; +class OsxInputMethodContext; + +class OsxWindow : public OsxGuiResource, public INativeWindow { + friend details::OsxWindowPrivate; + friend details::OsxInputMethodContextPrivate; + + public: + OsxWindow(OsxUiApplication* ui_application); + + CRU_DELETE_COPY(OsxWindow) + CRU_DELETE_MOVE(OsxWindow) + + ~OsxWindow() override; + + public: + void Close() override; + + INativeWindow* GetParent() override; + void SetParent(INativeWindow* parent) override; + + WindowStyleFlag GetStyleFlag() override; + void SetStyleFlag(WindowStyleFlag flag) override; + + String GetTitle() override; + void SetTitle(String title) override; + + WindowVisibilityType GetVisibility() override; + void SetVisibility(WindowVisibilityType visibility) override; + + Size GetClientSize() override; + void SetClientSize(const Size& size) override; + + Rect GetClientRect() override; + void SetClientRect(const Rect& rect) override; + + Rect GetWindowRect() override; + void SetWindowRect(const Rect& rect) override; + + bool RequestFocus() override; + + Point GetMousePosition() override; + + bool CaptureMouse() override; + bool ReleaseMouse() override; + + void SetCursor(std::shared_ptr cursor) override; + + void SetToForeground() override; + + void RequestRepaint() override; + + std::unique_ptr BeginPaint() override; + + IEvent* CreateEvent() override; + IEvent* DestroyEvent() override; + IEvent* PaintEvent() override; + + IEvent* VisibilityChangeEvent() override; + IEvent* ResizeEvent() override; + IEvent* FocusEvent() override; + + IEvent* MouseEnterLeaveEvent() override; + IEvent* MouseMoveEvent() override; + IEvent* MouseDownEvent() override; + IEvent* MouseUpEvent() override; + IEvent* MouseWheelEvent() override; + IEvent* KeyDownEvent() override; + IEvent* KeyUpEvent() override; + + IInputMethodContext* GetInputMethodContext() override; + + private: + std::unique_ptr p_; +}; +} // namespace cru::platform::gui::osx diff --git a/include/cru/osx/gui/Window.hpp b/include/cru/osx/gui/Window.hpp deleted file mode 100644 index 904a0188..00000000 --- a/include/cru/osx/gui/Window.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/gui/Base.hpp" -#include "cru/platform/gui/InputMethod.hpp" -#include "cru/platform/gui/Window.hpp" - -#include - -namespace cru::platform::gui::osx { -namespace details { -class OsxWindowPrivate; -class OsxInputMethodContextPrivate; -} // namespace details - -class OsxUiApplication; -class OsxInputMethodContext; - -class OsxWindow : public OsxGuiResource, public INativeWindow { - friend details::OsxWindowPrivate; - friend details::OsxInputMethodContextPrivate; - - public: - OsxWindow(OsxUiApplication* ui_application); - - CRU_DELETE_COPY(OsxWindow) - CRU_DELETE_MOVE(OsxWindow) - - ~OsxWindow() override; - - public: - void Close() override; - - INativeWindow* GetParent() override; - void SetParent(INativeWindow* parent) override; - - WindowStyleFlag GetStyleFlag() override; - void SetStyleFlag(WindowStyleFlag flag) override; - - String GetTitle() override; - void SetTitle(String title) override; - - WindowVisibilityType GetVisibility() override; - void SetVisibility(WindowVisibilityType visibility) override; - - Size GetClientSize() override; - void SetClientSize(const Size& size) override; - - Rect GetClientRect() override; - void SetClientRect(const Rect& rect) override; - - Rect GetWindowRect() override; - void SetWindowRect(const Rect& rect) override; - - bool RequestFocus() override; - - Point GetMousePosition() override; - - bool CaptureMouse() override; - bool ReleaseMouse() override; - - void SetCursor(std::shared_ptr cursor) override; - - void SetToForeground() override; - - void RequestRepaint() override; - - std::unique_ptr BeginPaint() override; - - IEvent* CreateEvent() override; - IEvent* DestroyEvent() override; - IEvent* PaintEvent() override; - - IEvent* VisibilityChangeEvent() override; - IEvent* ResizeEvent() override; - IEvent* FocusEvent() override; - - IEvent* MouseEnterLeaveEvent() override; - IEvent* MouseMoveEvent() override; - IEvent* MouseDownEvent() override; - IEvent* MouseUpEvent() override; - IEvent* MouseWheelEvent() override; - IEvent* KeyDownEvent() override; - IEvent* KeyUpEvent() override; - - IInputMethodContext* GetInputMethodContext() override; - - private: - std::unique_ptr p_; -}; -} // namespace cru::platform::gui::osx diff --git a/include/cru/parse/Base.h b/include/cru/parse/Base.h new file mode 100644 index 00000000..8f3a05e9 --- /dev/null +++ b/include/cru/parse/Base.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PARSE_EXPORT_API +#define CRU_PARSE_API __declspec(dllexport) +#else +#define CRU_PARSE_API __declspec(dllimport) +#endif +#else +#define CRU_PARSE_API +#endif diff --git a/include/cru/parse/Base.hpp b/include/cru/parse/Base.hpp deleted file mode 100644 index 8f3a05e9..00000000 --- a/include/cru/parse/Base.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_PARSE_EXPORT_API -#define CRU_PARSE_API __declspec(dllexport) -#else -#define CRU_PARSE_API __declspec(dllimport) -#endif -#else -#define CRU_PARSE_API -#endif diff --git a/include/cru/parse/Grammar.h b/include/cru/parse/Grammar.h new file mode 100644 index 00000000..7dd1eec0 --- /dev/null +++ b/include/cru/parse/Grammar.h @@ -0,0 +1,62 @@ +#pragma once +#include "Production.h" + +#include +#include + +namespace cru::parse { +class CRU_PARSE_API Grammar : public Object { + public: + Grammar(); + + CRU_DELETE_COPY(Grammar) + CRU_DELETE_MOVE(Grammar) + + ~Grammar() override; + + public: + void SetStartSymbol(Nonterminal* start_symbol); + + Terminal* CreateTerminal(String name); + Nonterminal* CreateNonterminal(String name); + Production* CreateProduction(String name, Nonterminal* left, + std::vector right); + + bool RemoveSymbol(Symbol* symbol); + bool RemoveProduction(Production* production); + + public: // Getters + Nonterminal* GetStartSymbol() const { return start_symbol_; } + const std::vector& GetTerminals() const { return terminals_; } + const std::vector& GetNonterminals() const { + return nonterminals_; + } + const std::vector& GetSymbols() const { return symbols_; } + const std::vector& GetProductions() const { + return productions_; + } + + Grammar* Clone() const; + + public: // Algorithms + std::unordered_map> + GenerateLeftProductionMap() const; + + // Algorithm 4.19. + // Require grammar has no cycles or empty-productions. + void EliminateLeftRecursions(); + + // Algorithm 4.21 + void LeftFactor(); + + public: + String ProductionsToString() const; + + private: + Nonterminal* start_symbol_ = nullptr; + std::vector terminals_; + std::vector nonterminals_; + std::vector symbols_; + std::vector productions_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/Grammar.hpp b/include/cru/parse/Grammar.hpp deleted file mode 100644 index 8dc1833f..00000000 --- a/include/cru/parse/Grammar.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include "Production.hpp" - -#include -#include - -namespace cru::parse { -class CRU_PARSE_API Grammar : public Object { - public: - Grammar(); - - CRU_DELETE_COPY(Grammar) - CRU_DELETE_MOVE(Grammar) - - ~Grammar() override; - - public: - void SetStartSymbol(Nonterminal* start_symbol); - - Terminal* CreateTerminal(String name); - Nonterminal* CreateNonterminal(String name); - Production* CreateProduction(String name, Nonterminal* left, - std::vector right); - - bool RemoveSymbol(Symbol* symbol); - bool RemoveProduction(Production* production); - - public: // Getters - Nonterminal* GetStartSymbol() const { return start_symbol_; } - const std::vector& GetTerminals() const { return terminals_; } - const std::vector& GetNonterminals() const { - return nonterminals_; - } - const std::vector& GetSymbols() const { return symbols_; } - const std::vector& GetProductions() const { - return productions_; - } - - Grammar* Clone() const; - - public: // Algorithms - std::unordered_map> - GenerateLeftProductionMap() const; - - // Algorithm 4.19. - // Require grammar has no cycles or empty-productions. - void EliminateLeftRecursions(); - - // Algorithm 4.21 - void LeftFactor(); - - public: - String ProductionsToString() const; - - private: - Nonterminal* start_symbol_ = nullptr; - std::vector terminals_; - std::vector nonterminals_; - std::vector symbols_; - std::vector productions_; -}; -} // namespace cru::parse diff --git a/include/cru/parse/Nonterminal.h b/include/cru/parse/Nonterminal.h new file mode 100644 index 00000000..0ea15149 --- /dev/null +++ b/include/cru/parse/Nonterminal.h @@ -0,0 +1,14 @@ +#pragma once +#include "Symbol.h" + +namespace cru::parse { +class CRU_PARSE_API Nonterminal : public Symbol { + public: + Nonterminal(Grammar* grammar, String name); + + CRU_DELETE_COPY(Nonterminal) + CRU_DELETE_MOVE(Nonterminal) + + ~Nonterminal() override; +}; +} // namespace cru::parse diff --git a/include/cru/parse/Nonterminal.hpp b/include/cru/parse/Nonterminal.hpp deleted file mode 100644 index b01c7c8a..00000000 --- a/include/cru/parse/Nonterminal.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "Symbol.hpp" - -namespace cru::parse { -class CRU_PARSE_API Nonterminal : public Symbol { - public: - Nonterminal(Grammar* grammar, String name); - - CRU_DELETE_COPY(Nonterminal) - CRU_DELETE_MOVE(Nonterminal) - - ~Nonterminal() override; -}; -} // namespace cru::parse diff --git a/include/cru/parse/ParsingAlgorithm.h b/include/cru/parse/ParsingAlgorithm.h new file mode 100644 index 00000000..ae2dd0b5 --- /dev/null +++ b/include/cru/parse/ParsingAlgorithm.h @@ -0,0 +1,22 @@ +#pragma once +#include "Grammar.h" + +namespace cru::parse { +class ParsingAlgorithmContext; + +// Represents a parsing algorithm. +// It does not relate to any specific grammar. +// It is used to validate a grammar and create a parsing algorithm context. +class CRU_PARSE_API ParsingAlgorithm { + public: + ParsingAlgorithm() = default; + + CRU_DELETE_COPY(ParsingAlgorithm) + CRU_DELETE_MOVE(ParsingAlgorithm) + + virtual ~ParsingAlgorithm() = default; + + virtual bool CanHandle(Grammar* grammar) const = 0; + virtual ParsingAlgorithmContext* CreateContext(Grammar* grammar) const = 0; +}; +} // namespace cru::parse diff --git a/include/cru/parse/ParsingAlgorithm.hpp b/include/cru/parse/ParsingAlgorithm.hpp deleted file mode 100644 index 8f38c0ab..00000000 --- a/include/cru/parse/ParsingAlgorithm.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "Grammar.hpp" - -namespace cru::parse { -class ParsingAlgorithmContext; - -// Represents a parsing algorithm. -// It does not relate to any specific grammar. -// It is used to validate a grammar and create a parsing algorithm context. -class CRU_PARSE_API ParsingAlgorithm { - public: - ParsingAlgorithm() = default; - - CRU_DELETE_COPY(ParsingAlgorithm) - CRU_DELETE_MOVE(ParsingAlgorithm) - - virtual ~ParsingAlgorithm() = default; - - virtual bool CanHandle(Grammar* grammar) const = 0; - virtual ParsingAlgorithmContext* CreateContext(Grammar* grammar) const = 0; -}; -} // namespace cru::parse diff --git a/include/cru/parse/ParsingAlgorithmContext.h b/include/cru/parse/ParsingAlgorithmContext.h new file mode 100644 index 00000000..fe46c4d2 --- /dev/null +++ b/include/cru/parse/ParsingAlgorithmContext.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include "Grammar.h" +#include "cru/parse/ParsingTreeNode.h" +#include "cru/parse/Terminal.h" + +namespace cru::parse { +class ParsingAlgorithm; + +// A parsing algorithm context contains all data a parsing algorithm needs to +// parse for a grammar. It does not relate to any input. For example, it can +// contain any state machine. +class CRU_PARSE_API ParsingAlgorithmContext { + public: + ParsingAlgorithmContext(Grammar* grammar, const ParsingAlgorithm* algorithm); + + CRU_DELETE_COPY(ParsingAlgorithmContext) + CRU_DELETE_MOVE(ParsingAlgorithmContext) + + virtual ~ParsingAlgorithmContext(); + + virtual ParsingTreeNode* Parse(const std::vector& input) = 0; + + private: + Grammar* grammar_; + const ParsingAlgorithm* algorithm_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/ParsingAlgorithmContext.hpp b/include/cru/parse/ParsingAlgorithmContext.hpp deleted file mode 100644 index b959462c..00000000 --- a/include/cru/parse/ParsingAlgorithmContext.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include -#include "Grammar.hpp" -#include "cru/parse/ParsingTreeNode.hpp" -#include "cru/parse/Terminal.hpp" - -namespace cru::parse { -class ParsingAlgorithm; - -// A parsing algorithm context contains all data a parsing algorithm needs to -// parse for a grammar. It does not relate to any input. For example, it can -// contain any state machine. -class CRU_PARSE_API ParsingAlgorithmContext { - public: - ParsingAlgorithmContext(Grammar* grammar, const ParsingAlgorithm* algorithm); - - CRU_DELETE_COPY(ParsingAlgorithmContext) - CRU_DELETE_MOVE(ParsingAlgorithmContext) - - virtual ~ParsingAlgorithmContext(); - - virtual ParsingTreeNode* Parse(const std::vector& input) = 0; - - private: - Grammar* grammar_; - const ParsingAlgorithm* algorithm_; -}; -} // namespace cru::parse diff --git a/include/cru/parse/ParsingContext.h b/include/cru/parse/ParsingContext.h new file mode 100644 index 00000000..02dc4c9c --- /dev/null +++ b/include/cru/parse/ParsingContext.h @@ -0,0 +1,22 @@ +#pragma once +#include "ParsingAlgorithmContext.h" +#include "cru/parse/ParsingTreeNode.h" + +namespace cru::parse { +// A parsing context contains all info that a program needs to know when parsing +// a input sequence of terminals. +class CRU_PARSE_API ParsingContext { + public: + ParsingContext(const ParsingAlgorithmContext* parsing_algorithm_context, + std::vector input); + + CRU_DELETE_COPY(ParsingContext) + CRU_DELETE_MOVE(ParsingContext) + + ~ParsingContext(); + + private: + const ParsingAlgorithmContext* parsing_algorithm_context_; + std::vector input_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/ParsingContext.hpp b/include/cru/parse/ParsingContext.hpp deleted file mode 100644 index cfb850b9..00000000 --- a/include/cru/parse/ParsingContext.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "ParsingAlgorithmContext.hpp" -#include "cru/parse/ParsingTreeNode.hpp" - -namespace cru::parse { -// A parsing context contains all info that a program needs to know when parsing -// a input sequence of terminals. -class CRU_PARSE_API ParsingContext { - public: - ParsingContext(const ParsingAlgorithmContext* parsing_algorithm_context, - std::vector input); - - CRU_DELETE_COPY(ParsingContext) - CRU_DELETE_MOVE(ParsingContext) - - ~ParsingContext(); - - private: - const ParsingAlgorithmContext* parsing_algorithm_context_; - std::vector input_; -}; -} // namespace cru::parse diff --git a/include/cru/parse/ParsingTreeNode.h b/include/cru/parse/ParsingTreeNode.h new file mode 100644 index 00000000..05b1006c --- /dev/null +++ b/include/cru/parse/ParsingTreeNode.h @@ -0,0 +1,33 @@ +#pragma once +#include "Grammar.h" + +#include + +namespace cru::parse { +class CRU_PARSE_API ParsingTreeNode { + public: + ParsingTreeNode(Symbol* symbol, Production* production); + + CRU_DELETE_COPY(ParsingTreeNode) + CRU_DELETE_MOVE(ParsingTreeNode) + + // In destructor, it will delete all children. + ~ParsingTreeNode(); + + public: + Symbol* GetSymbol() const { return symbol_; } + Production* GetProduction() const { return production_; } + Grammar* GetGrammar() const; + + const std::vector& GetChildren() const { return children_; } + + void AddChild(ParsingTreeNode* child); + void AddChild(ParsingTreeNode* child, Index index); + void RemoveChild(Index index); + + private: + Symbol* symbol_; + Production* production_; + std::vector children_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/ParsingTreeNode.hpp b/include/cru/parse/ParsingTreeNode.hpp deleted file mode 100644 index 7119ca0b..00000000 --- a/include/cru/parse/ParsingTreeNode.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "Grammar.hpp" - -#include - -namespace cru::parse { -class CRU_PARSE_API ParsingTreeNode { - public: - ParsingTreeNode(Symbol* symbol, Production* production); - - CRU_DELETE_COPY(ParsingTreeNode) - CRU_DELETE_MOVE(ParsingTreeNode) - - // In destructor, it will delete all children. - ~ParsingTreeNode(); - - public: - Symbol* GetSymbol() const { return symbol_; } - Production* GetProduction() const { return production_; } - Grammar* GetGrammar() const; - - const std::vector& GetChildren() const { return children_; } - - void AddChild(ParsingTreeNode* child); - void AddChild(ParsingTreeNode* child, Index index); - void RemoveChild(Index index); - - private: - Symbol* symbol_; - Production* production_; - std::vector children_; -}; -} // namespace cru::parse diff --git a/include/cru/parse/Production.h b/include/cru/parse/Production.h new file mode 100644 index 00000000..d5ababe6 --- /dev/null +++ b/include/cru/parse/Production.h @@ -0,0 +1,43 @@ +#pragma once +#include "cru/common/String.h" + +#include "Nonterminal.h" +#include "Terminal.h" + +#include + +namespace cru::parse { +class CRU_PARSE_API Production : public Object { + public: + Production(Grammar* grammar, String name, Nonterminal* left, + std::vector right); + + CRU_DELETE_COPY(Production) + CRU_DELETE_MOVE(Production) + + ~Production() override; + + public: + Grammar* GetGrammar() const { return grammar_; } + + String GetName() const { return name_; } + void SetName(String name) { name_ = std::move(name); } + + Nonterminal* GetLeft() const { return left_; } + void SetLeft(Nonterminal* left); + + const std::vector& GetRight() const { return right_; } + void SetRight(std::vector right); + + bool IsLeftRecursion() const { + return !right_.empty() && left_ == right_.front(); + } + + private: + Grammar* grammar_; + String name_; + + Nonterminal* left_; + std::vector right_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/Production.hpp b/include/cru/parse/Production.hpp deleted file mode 100644 index cb3c79c0..00000000 --- a/include/cru/parse/Production.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "cru/common/String.hpp" - -#include "Nonterminal.hpp" -#include "Terminal.hpp" - -#include - -namespace cru::parse { -class CRU_PARSE_API Production : public Object { - public: - Production(Grammar* grammar, String name, Nonterminal* left, - std::vector right); - - CRU_DELETE_COPY(Production) - CRU_DELETE_MOVE(Production) - - ~Production() override; - - public: - Grammar* GetGrammar() const { return grammar_; } - - String GetName() const { return name_; } - void SetName(String name) { name_ = std::move(name); } - - Nonterminal* GetLeft() const { return left_; } - void SetLeft(Nonterminal* left); - - const std::vector& GetRight() const { return right_; } - void SetRight(std::vector right); - - bool IsLeftRecursion() const { - return !right_.empty() && left_ == right_.front(); - } - - private: - Grammar* grammar_; - String name_; - - Nonterminal* left_; - std::vector right_; -}; -} // namespace cru::parse diff --git a/include/cru/parse/RecursiveDescentAlgorithm.h b/include/cru/parse/RecursiveDescentAlgorithm.h new file mode 100644 index 00000000..9da4b8fe --- /dev/null +++ b/include/cru/parse/RecursiveDescentAlgorithm.h @@ -0,0 +1,19 @@ +#pragma once + +#include "ParsingAlgorithm.h" + +namespace cru::parse { +class CRU_PARSE_API RecursiveDescentAlgorithm : public ParsingAlgorithm { + public: + RecursiveDescentAlgorithm() = default; + + CRU_DELETE_COPY(RecursiveDescentAlgorithm) + CRU_DELETE_MOVE(RecursiveDescentAlgorithm) + + ~RecursiveDescentAlgorithm() override = default; + + public: + bool CanHandle(Grammar* grammar) const override; + ParsingAlgorithmContext* CreateContext(Grammar* grammar) const override; +}; +} // namespace cru::parse diff --git a/include/cru/parse/RecursiveDescentAlgorithm.hpp b/include/cru/parse/RecursiveDescentAlgorithm.hpp deleted file mode 100644 index 373724ea..00000000 --- a/include/cru/parse/RecursiveDescentAlgorithm.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "ParsingAlgorithm.hpp" - -namespace cru::parse { -class CRU_PARSE_API RecursiveDescentAlgorithm : public ParsingAlgorithm { - public: - RecursiveDescentAlgorithm() = default; - - CRU_DELETE_COPY(RecursiveDescentAlgorithm) - CRU_DELETE_MOVE(RecursiveDescentAlgorithm) - - ~RecursiveDescentAlgorithm() override = default; - - public: - bool CanHandle(Grammar* grammar) const override; - ParsingAlgorithmContext* CreateContext(Grammar* grammar) const override; -}; -} // namespace cru::parse diff --git a/include/cru/parse/RecursiveDescentAlgorithmContext.h b/include/cru/parse/RecursiveDescentAlgorithmContext.h new file mode 100644 index 00000000..00acf479 --- /dev/null +++ b/include/cru/parse/RecursiveDescentAlgorithmContext.h @@ -0,0 +1,22 @@ +#pragma once + +#include "ParsingAlgorithmContext.h" +#include "cru/parse/ParsingTreeNode.h" +#include "cru/parse/RecursiveDescentAlgorithm.h" +#include "cru/parse/Terminal.h" + +namespace cru::parse { +class CRU_PARSE_API RecursiveDescentAlgorithmContext : public ParsingAlgorithmContext { + public: + RecursiveDescentAlgorithmContext(Grammar* grammar, + const RecursiveDescentAlgorithm* algorithm); + + CRU_DELETE_COPY(RecursiveDescentAlgorithmContext) + CRU_DELETE_MOVE(RecursiveDescentAlgorithmContext) + + ~RecursiveDescentAlgorithmContext() override; + + public: + ParsingTreeNode* Parse(const std::vector& input) override; +}; +} // namespace cru::parse diff --git a/include/cru/parse/RecursiveDescentAlgorithmContext.hpp b/include/cru/parse/RecursiveDescentAlgorithmContext.hpp deleted file mode 100644 index b29ee1a1..00000000 --- a/include/cru/parse/RecursiveDescentAlgorithmContext.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "ParsingAlgorithmContext.hpp" -#include "cru/parse/ParsingTreeNode.hpp" -#include "cru/parse/RecursiveDescentAlgorithm.hpp" -#include "cru/parse/Terminal.hpp" - -namespace cru::parse { -class CRU_PARSE_API RecursiveDescentAlgorithmContext : public ParsingAlgorithmContext { - public: - RecursiveDescentAlgorithmContext(Grammar* grammar, - const RecursiveDescentAlgorithm* algorithm); - - CRU_DELETE_COPY(RecursiveDescentAlgorithmContext) - CRU_DELETE_MOVE(RecursiveDescentAlgorithmContext) - - ~RecursiveDescentAlgorithmContext() override; - - public: - ParsingTreeNode* Parse(const std::vector& input) override; -}; -} // namespace cru::parse diff --git a/include/cru/parse/Symbol.h b/include/cru/parse/Symbol.h new file mode 100644 index 00000000..e7bd4808 --- /dev/null +++ b/include/cru/parse/Symbol.h @@ -0,0 +1,30 @@ +#pragma once +#include "Base.h" + +#include "cru/common/String.h" + +namespace cru::parse { +class Grammar; + +// Base class of Terminal and Nonterminal. +class CRU_PARSE_API Symbol : public Object { + public: + explicit Symbol(Grammar* grammar, String name); + + CRU_DELETE_COPY(Symbol) + CRU_DELETE_MOVE(Symbol) + + ~Symbol() override; + + public: + Grammar* GetGrammar() { return grammar_; } + + String GetName() const { return name_; } + void SetName(String name) { name_ = std::move(name); } + + private: + Grammar* grammar_; + + String name_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/Symbol.hpp b/include/cru/parse/Symbol.hpp deleted file mode 100644 index 7404a5e7..00000000 --- a/include/cru/parse/Symbol.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/String.hpp" - -namespace cru::parse { -class Grammar; - -// Base class of Terminal and Nonterminal. -class CRU_PARSE_API Symbol : public Object { - public: - explicit Symbol(Grammar* grammar, String name); - - CRU_DELETE_COPY(Symbol) - CRU_DELETE_MOVE(Symbol) - - ~Symbol() override; - - public: - Grammar* GetGrammar() { return grammar_; } - - String GetName() const { return name_; } - void SetName(String name) { name_ = std::move(name); } - - private: - Grammar* grammar_; - - String name_; -}; -} // namespace cru::parse diff --git a/include/cru/parse/Terminal.h b/include/cru/parse/Terminal.h new file mode 100644 index 00000000..d197ab29 --- /dev/null +++ b/include/cru/parse/Terminal.h @@ -0,0 +1,14 @@ +#pragma once +#include "Symbol.h" + +namespace cru::parse { +class CRU_PARSE_API Terminal : public Symbol { + public: + Terminal(Grammar* grammar, String name); + + CRU_DELETE_COPY(Terminal) + CRU_DELETE_MOVE(Terminal) + + ~Terminal() override; +}; +} // namespace cru::parse diff --git a/include/cru/parse/Terminal.hpp b/include/cru/parse/Terminal.hpp deleted file mode 100644 index 4ff8f898..00000000 --- a/include/cru/parse/Terminal.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "Symbol.hpp" - -namespace cru::parse { -class CRU_PARSE_API Terminal : public Symbol { - public: - Terminal(Grammar* grammar, String name); - - CRU_DELETE_COPY(Terminal) - CRU_DELETE_MOVE(Terminal) - - ~Terminal() override; -}; -} // namespace cru::parse diff --git a/include/cru/parse/Token.h b/include/cru/parse/Token.h new file mode 100644 index 00000000..e69de29b diff --git a/include/cru/parse/Token.hpp b/include/cru/parse/Token.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/include/cru/parse/TokenType.h b/include/cru/parse/TokenType.h new file mode 100644 index 00000000..cb6f6159 --- /dev/null +++ b/include/cru/parse/TokenType.h @@ -0,0 +1,24 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Base.h" +#include "cru/common/String.h" + +namespace cru::parse { +class CRU_PARSE_API TokenType : public Object { + public: + explicit TokenType(String name); + + CRU_DELETE_COPY(TokenType) + CRU_DELETE_MOVE(TokenType) + + ~TokenType() override; + + public: + String GetName() const { return name_; } + void SetName(String name) { name_ = std::move(name); } + + private: + String name_; +}; +} // namespace cru::parse diff --git a/include/cru/parse/TokenType.hpp b/include/cru/parse/TokenType.hpp deleted file mode 100644 index 49415d3b..00000000 --- a/include/cru/parse/TokenType.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Base.hpp" -#include "cru/common/String.hpp" - -namespace cru::parse { -class CRU_PARSE_API TokenType : public Object { - public: - explicit TokenType(String name); - - CRU_DELETE_COPY(TokenType) - CRU_DELETE_MOVE(TokenType) - - ~TokenType() override; - - public: - String GetName() const { return name_; } - void SetName(String name) { name_ = std::move(name); } - - private: - String name_; -}; -} // namespace cru::parse diff --git a/include/cru/platform/Base.h b/include/cru/platform/Base.h new file mode 100644 index 00000000..8589e6cb --- /dev/null +++ b/include/cru/platform/Base.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_EXPORT_API +#define CRU_PLATFORM_API __declspec(dllexport) +#else +#define CRU_PLATFORM_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_API +#endif diff --git a/include/cru/platform/Base.hpp b/include/cru/platform/Base.hpp deleted file mode 100644 index 8589e6cb..00000000 --- a/include/cru/platform/Base.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_PLATFORM_EXPORT_API -#define CRU_PLATFORM_API __declspec(dllexport) -#else -#define CRU_PLATFORM_API __declspec(dllimport) -#endif -#else -#define CRU_PLATFORM_API -#endif diff --git a/include/cru/platform/Check.h b/include/cru/platform/Check.h new file mode 100644 index 00000000..1750c7e8 --- /dev/null +++ b/include/cru/platform/Check.h @@ -0,0 +1,41 @@ +#pragma once +#include "Exception.h" +#include "Resource.h" + +#include "cru/common/String.h" +#include "cru/common/Format.h" + +#include +#include + +namespace cru::platform { +template +TTarget* CheckPlatform(IPlatformResource* resource, + const String& target_platform) { + Expects(resource); + const auto result = dynamic_cast(resource); + if (result == nullptr) { + throw UnsupportPlatformException(Format( + u"Try to convert resource to target platform failed. Platform id of " + "resource to convert: {} . Target platform id: {} .", + resource->GetPlatformId(), target_platform)); + } + return result; +} + +template +std::shared_ptr CheckPlatform(const std::shared_ptr& resource, + const String& target_platform) { + static_assert(std::is_base_of_v, + "TSource must be a subclass of INativeResource."); + Expects(resource); + const auto result = std::dynamic_pointer_cast(resource); + if (result == nullptr) { + throw UnsupportPlatformException(Format( + u"Try to convert resource to target platform failed. Platform id of " + "resource to convert: {} . Target platform id: {} .", + resource->GetPlatformId(), target_platform)); + } + return result; +} +} // namespace cru::platform diff --git a/include/cru/platform/Check.hpp b/include/cru/platform/Check.hpp deleted file mode 100644 index 121e3505..00000000 --- a/include/cru/platform/Check.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include "Exception.hpp" -#include "Resource.hpp" - -#include "cru/common/String.hpp" -#include "cru/common/Format.hpp" - -#include -#include - -namespace cru::platform { -template -TTarget* CheckPlatform(IPlatformResource* resource, - const String& target_platform) { - Expects(resource); - const auto result = dynamic_cast(resource); - if (result == nullptr) { - throw UnsupportPlatformException(Format( - u"Try to convert resource to target platform failed. Platform id of " - "resource to convert: {} . Target platform id: {} .", - resource->GetPlatformId(), target_platform)); - } - return result; -} - -template -std::shared_ptr CheckPlatform(const std::shared_ptr& resource, - const String& target_platform) { - static_assert(std::is_base_of_v, - "TSource must be a subclass of INativeResource."); - Expects(resource); - const auto result = std::dynamic_pointer_cast(resource); - if (result == nullptr) { - throw UnsupportPlatformException(Format( - u"Try to convert resource to target platform failed. Platform id of " - "resource to convert: {} . Target platform id: {} .", - resource->GetPlatformId(), target_platform)); - } - return result; -} -} // namespace cru::platform diff --git a/include/cru/platform/Color.h b/include/cru/platform/Color.h new file mode 100644 index 00000000..4e35ae63 --- /dev/null +++ b/include/cru/platform/Color.h @@ -0,0 +1,265 @@ +#pragma once +#include "cru/common/Base.h" +#include "cru/platform/Base.h" + +#include "cru/common/String.h" +#include "cru/common/Format.h" + +#include +#include +#include +#include + +namespace cru::platform { +struct CRU_PLATFORM_API Color { + constexpr Color() : Color(0, 0, 0, 255) {} + constexpr Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, + std::uint8_t alpha = 255) + : red(red), green(green), blue(blue), alpha(alpha) {} + + constexpr static Color FromHex(std::uint32_t hex) { + const std::uint32_t mask = 0b11111111; + return Color((hex >> 16) & mask, (hex >> 8) & mask, hex & mask, 255); + } + + constexpr static Color FromHexAlpha(std::uint32_t hex) { + const std::uint32_t mask = 0b11111111; + return Color((hex >> 24) & mask, (hex >> 16) & mask, (hex >> 8) & mask, + hex & mask); + } + + constexpr Color WithAlpha(std::uint8_t new_alpha) const { + auto result = *this; + result.alpha = new_alpha; + return result; + } + + float GetFloatRed() const { return static_cast(red) / 255.f; } + float GetFloatGreen() const { return static_cast(green) / 255.f; } + float GetFloatBlue() const { return static_cast(blue) / 255.f; } + float GetFloatAlpha() const { return static_cast(alpha) / 255.f; } + + String ToString() const; + + std::uint8_t red; + std::uint8_t green; + std::uint8_t blue; + std::uint8_t alpha; + + static std::optional Parse(StringView string, + bool parse_predefined_color = true); +}; + +constexpr int Compare(const Color& left, const Color& right) { + if (left.red < right.red) return -1; + if (left.red > right.red) return 1; + if (left.green < right.green) return -1; + if (left.green > right.green) return 1; + if (left.blue < right.blue) return -1; + if (left.blue > right.blue) return 1; + if (left.alpha < right.alpha) return -1; + if (left.alpha > right.alpha) return 1; + return 0; +} + +constexpr bool operator==(const Color& left, const Color& right) { + return Compare(left, right) == 0; +} + +constexpr bool operator!=(const Color& left, const Color& right) { + return Compare(left, right) != 0; +} + +constexpr bool operator<(const Color& left, const Color& right) { + return Compare(left, right) < 0; +} + +constexpr bool operator<=(const Color& left, const Color& right) { + return Compare(left, right) <= 0; +} + +constexpr bool operator>(const Color& left, const Color& right) { + return Compare(left, right) > 0; +} + +constexpr bool operator>=(const Color& left, const Color& right) { + return Compare(left, right) >= 0; +} + +namespace colors { +constexpr Color transparent = Color::FromHexAlpha(0x00000000); +constexpr Color black = Color::FromHex(0x000000); +constexpr Color silver = Color::FromHex(0xc0c0c0); +constexpr Color gray = Color::FromHex(0x808080); +constexpr Color white = Color::FromHex(0xffffff); +constexpr Color maroon = Color::FromHex(0x800000); +constexpr Color red = Color::FromHex(0xff0000); +constexpr Color purple = Color::FromHex(0x800080); +constexpr Color fuchsia = Color::FromHex(0xff00ff); +constexpr Color green = Color::FromHex(0x008000); +constexpr Color lime = Color::FromHex(0x00ff00); +constexpr Color olive = Color::FromHex(0x808000); +constexpr Color yellow = Color::FromHex(0xffff00); +constexpr Color navy = Color::FromHex(0x000080); +constexpr Color blue = Color::FromHex(0x0000ff); +constexpr Color teal = Color::FromHex(0x008080); +constexpr Color aqua = Color::FromHex(0x00ffff); +constexpr Color orange = Color::FromHex(0xffa500); +constexpr Color aliceblue = Color::FromHex(0xf0f8ff); +constexpr Color antiquewhite = Color::FromHex(0xfaebd7); +constexpr Color aquamarine = Color::FromHex(0x7fffd4); +constexpr Color azure = Color::FromHex(0xf0ffff); +constexpr Color beige = Color::FromHex(0xf5f5dc); +constexpr Color bisque = Color::FromHex(0xffe4c4); +constexpr Color blanchedalmond = Color::FromHex(0xffebcd); +constexpr Color blueviolet = Color::FromHex(0x8a2be2); +constexpr Color brown = Color::FromHex(0xa52a2a); +constexpr Color burlywood = Color::FromHex(0xdeb887); +constexpr Color cadetblue = Color::FromHex(0x5f9ea0); +constexpr Color chartreuse = Color::FromHex(0x7fff00); +constexpr Color chocolate = Color::FromHex(0xd2691e); +constexpr Color coral = Color::FromHex(0xff7f50); +constexpr Color cornflowerblue = Color::FromHex(0x6495ed); +constexpr Color cornsilk = Color::FromHex(0xfff8dc); +constexpr Color crimson = Color::FromHex(0xdc143c); +constexpr Color cyan = aqua; +constexpr Color darkblue = Color::FromHex(0x00008b); +constexpr Color darkcyan = Color::FromHex(0x008b8b); +constexpr Color darkgoldenrod = Color::FromHex(0xb8860b); +constexpr Color darkgray = Color::FromHex(0xa9a9a9); +constexpr Color darkgreen = Color::FromHex(0x006400); +constexpr Color darkgrey = Color::FromHex(0xa9a9a9); +constexpr Color darkkhaki = Color::FromHex(0xbdb76b); +constexpr Color darkmagenta = Color::FromHex(0x8b008b); +constexpr Color darkolivegreen = Color::FromHex(0x556b2f); +constexpr Color darkorange = Color::FromHex(0xff8c00); +constexpr Color darkorchid = Color::FromHex(0x9932cc); +constexpr Color darkred = Color::FromHex(0x8b0000); +constexpr Color darksalmon = Color::FromHex(0xe9967a); +constexpr Color darkseagreen = Color::FromHex(0x8fbc8f); +constexpr Color darkslateblue = Color::FromHex(0x483d8b); +constexpr Color darkslategray = Color::FromHex(0x2f4f4f); +constexpr Color darkslategrey = Color::FromHex(0x2f4f4f); +constexpr Color darkturquoise = Color::FromHex(0x00ced1); +constexpr Color darkviolet = Color::FromHex(0x9400d3); +constexpr Color deeppink = Color::FromHex(0xff1493); +constexpr Color deepskyblue = Color::FromHex(0x00bfff); +constexpr Color dimgray = Color::FromHex(0x696969); +constexpr Color dimgrey = Color::FromHex(0x696969); +constexpr Color dodgerblue = Color::FromHex(0x1e90ff); +constexpr Color firebrick = Color::FromHex(0xb22222); +constexpr Color floralwhite = Color::FromHex(0xfffaf0); +constexpr Color forestgreen = Color::FromHex(0x228b22); +constexpr Color gainsboro = Color::FromHex(0xdcdcdc); +constexpr Color ghostwhite = Color::FromHex(0xf8f8ff); +constexpr Color gold = Color::FromHex(0xffd700); +constexpr Color goldenrod = Color::FromHex(0xdaa520); +constexpr Color greenyellow = Color::FromHex(0xadff2f); +constexpr Color grey = Color::FromHex(0x808080); +constexpr Color honeydew = Color::FromHex(0xf0fff0); +constexpr Color hotpink = Color::FromHex(0xff69b4); +constexpr Color indianred = Color::FromHex(0xcd5c5c); +constexpr Color indigo = Color::FromHex(0x4b0082); +constexpr Color ivory = Color::FromHex(0xfffff0); +constexpr Color khaki = Color::FromHex(0xf0e68c); +constexpr Color lavender = Color::FromHex(0xe6e6fa); +constexpr Color lavenderblush = Color::FromHex(0xfff0f5); +constexpr Color lawngreen = Color::FromHex(0x7cfc00); +constexpr Color lemonchiffon = Color::FromHex(0xfffacd); +constexpr Color lightblue = Color::FromHex(0xadd8e6); +constexpr Color lightcoral = Color::FromHex(0xf08080); +constexpr Color lightcyan = Color::FromHex(0xe0ffff); +constexpr Color lightgoldenrodyellow = Color::FromHex(0xfafad2); +constexpr Color lightgray = Color::FromHex(0xd3d3d3); +constexpr Color lightgreen = Color::FromHex(0x90ee90); +constexpr Color lightgrey = Color::FromHex(0xd3d3d3); +constexpr Color lightpink = Color::FromHex(0xffb6c1); +constexpr Color lightsalmon = Color::FromHex(0xffa07a); +constexpr Color lightseagreen = Color::FromHex(0x20b2aa); +constexpr Color lightskyblue = Color::FromHex(0x87cefa); +constexpr Color lightslategray = Color::FromHex(0x778899); +constexpr Color lightslategrey = Color::FromHex(0x778899); +constexpr Color lightsteelblue = Color::FromHex(0xb0c4de); +constexpr Color lightyellow = Color::FromHex(0xffffe0); +constexpr Color limegreen = Color::FromHex(0x32cd32); +constexpr Color linen = Color::FromHex(0xfaf0e6); +constexpr Color magenta = fuchsia; +constexpr Color mediumaquamarine = Color::FromHex(0x66cdaa); +constexpr Color mediumblue = Color::FromHex(0x0000cd); +constexpr Color mediumorchid = Color::FromHex(0xba55d3); +constexpr Color mediumpurple = Color::FromHex(0x9370db); +constexpr Color mediumseagreen = Color::FromHex(0x3cb371); +constexpr Color mediumslateblue = Color::FromHex(0x7b68ee); +constexpr Color mediumspringgreen = Color::FromHex(0x00fa9a); +constexpr Color mediumturquoise = Color::FromHex(0x48d1cc); +constexpr Color mediumvioletred = Color::FromHex(0xc71585); +constexpr Color midnightblue = Color::FromHex(0x191970); +constexpr Color mintcream = Color::FromHex(0xf5fffa); +constexpr Color mistyrose = Color::FromHex(0xffe4e1); +constexpr Color moccasin = Color::FromHex(0xffe4b5); +constexpr Color navajowhite = Color::FromHex(0xffdead); +constexpr Color oldlace = Color::FromHex(0xfdf5e6); +constexpr Color olivedrab = Color::FromHex(0x6b8e23); +constexpr Color orangered = Color::FromHex(0xff4500); +constexpr Color orchid = Color::FromHex(0xda70d6); +constexpr Color palegoldenrod = Color::FromHex(0xeee8aa); +constexpr Color palegreen = Color::FromHex(0x98fb98); +constexpr Color paleturquoise = Color::FromHex(0xafeeee); +constexpr Color palevioletred = Color::FromHex(0xdb7093); +constexpr Color papayawhip = Color::FromHex(0xffefd5); +constexpr Color peachpuff = Color::FromHex(0xffdab9); +constexpr Color peru = Color::FromHex(0xcd853f); +constexpr Color pink = Color::FromHex(0xffc0cb); +constexpr Color plum = Color::FromHex(0xdda0dd); +constexpr Color powderblue = Color::FromHex(0xb0e0e6); +constexpr Color rosybrown = Color::FromHex(0xbc8f8f); +constexpr Color royalblue = Color::FromHex(0x4169e1); +constexpr Color saddlebrown = Color::FromHex(0x8b4513); +constexpr Color salmon = Color::FromHex(0xfa8072); +constexpr Color sandybrown = Color::FromHex(0xf4a460); +constexpr Color seagreen = Color::FromHex(0x2e8b57); +constexpr Color seashell = Color::FromHex(0xfff5ee); +constexpr Color sienna = Color::FromHex(0xa0522d); +constexpr Color skyblue = Color::FromHex(0x87ceeb); +constexpr Color slateblue = Color::FromHex(0x6a5acd); +constexpr Color slategray = Color::FromHex(0x708090); +constexpr Color slategrey = Color::FromHex(0x708090); +constexpr Color snow = Color::FromHex(0xfffafa); +constexpr Color springgreen = Color::FromHex(0x00ff7f); +constexpr Color steelblue = Color::FromHex(0x4682b4); +constexpr Color tan = Color::FromHex(0xd2b48c); +constexpr Color thistle = Color::FromHex(0xd8bfd8); +constexpr Color tomato = Color::FromHex(0xff6347); +constexpr Color turquoise = Color::FromHex(0x40e0d0); +constexpr Color violet = Color::FromHex(0xee82ee); +constexpr Color wheat = Color::FromHex(0xf5deb3); +constexpr Color whitesmoke = Color::FromHex(0xf5f5f5); +constexpr Color yellowgreen = Color::FromHex(0x9acd32); +constexpr Color rebeccapurple = Color::FromHex(0x663399); +} // namespace colors +} // namespace cru::platform + +template <> +struct std::hash { + std::size_t operator()(const cru::platform::Color& color) const { + std::size_t seed = 0; + cru::hash_combine(seed, color.red); + cru::hash_combine(seed, color.green); + cru::hash_combine(seed, color.blue); + cru::hash_combine(seed, color.alpha); + return seed; + } +}; + +namespace cru::platform { +namespace details { +extern const std::unordered_map predefined_name_color_map; +} // namespace details + +std::optional GetPredefinedColorByName(StringView name); + +inline String ToString(const Color& color) { + return cru::Format(u"rgba({}, {}, {}, {})", color.red, color.green, + color.blue, color.alpha); +} +} // namespace cru::platform diff --git a/include/cru/platform/Color.hpp b/include/cru/platform/Color.hpp deleted file mode 100644 index cdc6518b..00000000 --- a/include/cru/platform/Color.hpp +++ /dev/null @@ -1,265 +0,0 @@ -#pragma once -#include "cru/common/Base.hpp" -#include "cru/platform/Base.hpp" - -#include "cru/common/String.hpp" -#include "cru/common/Format.hpp" - -#include -#include -#include -#include - -namespace cru::platform { -struct CRU_PLATFORM_API Color { - constexpr Color() : Color(0, 0, 0, 255) {} - constexpr Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, - std::uint8_t alpha = 255) - : red(red), green(green), blue(blue), alpha(alpha) {} - - constexpr static Color FromHex(std::uint32_t hex) { - const std::uint32_t mask = 0b11111111; - return Color((hex >> 16) & mask, (hex >> 8) & mask, hex & mask, 255); - } - - constexpr static Color FromHexAlpha(std::uint32_t hex) { - const std::uint32_t mask = 0b11111111; - return Color((hex >> 24) & mask, (hex >> 16) & mask, (hex >> 8) & mask, - hex & mask); - } - - constexpr Color WithAlpha(std::uint8_t new_alpha) const { - auto result = *this; - result.alpha = new_alpha; - return result; - } - - float GetFloatRed() const { return static_cast(red) / 255.f; } - float GetFloatGreen() const { return static_cast(green) / 255.f; } - float GetFloatBlue() const { return static_cast(blue) / 255.f; } - float GetFloatAlpha() const { return static_cast(alpha) / 255.f; } - - String ToString() const; - - std::uint8_t red; - std::uint8_t green; - std::uint8_t blue; - std::uint8_t alpha; - - static std::optional Parse(StringView string, - bool parse_predefined_color = true); -}; - -constexpr int Compare(const Color& left, const Color& right) { - if (left.red < right.red) return -1; - if (left.red > right.red) return 1; - if (left.green < right.green) return -1; - if (left.green > right.green) return 1; - if (left.blue < right.blue) return -1; - if (left.blue > right.blue) return 1; - if (left.alpha < right.alpha) return -1; - if (left.alpha > right.alpha) return 1; - return 0; -} - -constexpr bool operator==(const Color& left, const Color& right) { - return Compare(left, right) == 0; -} - -constexpr bool operator!=(const Color& left, const Color& right) { - return Compare(left, right) != 0; -} - -constexpr bool operator<(const Color& left, const Color& right) { - return Compare(left, right) < 0; -} - -constexpr bool operator<=(const Color& left, const Color& right) { - return Compare(left, right) <= 0; -} - -constexpr bool operator>(const Color& left, const Color& right) { - return Compare(left, right) > 0; -} - -constexpr bool operator>=(const Color& left, const Color& right) { - return Compare(left, right) >= 0; -} - -namespace colors { -constexpr Color transparent = Color::FromHexAlpha(0x00000000); -constexpr Color black = Color::FromHex(0x000000); -constexpr Color silver = Color::FromHex(0xc0c0c0); -constexpr Color gray = Color::FromHex(0x808080); -constexpr Color white = Color::FromHex(0xffffff); -constexpr Color maroon = Color::FromHex(0x800000); -constexpr Color red = Color::FromHex(0xff0000); -constexpr Color purple = Color::FromHex(0x800080); -constexpr Color fuchsia = Color::FromHex(0xff00ff); -constexpr Color green = Color::FromHex(0x008000); -constexpr Color lime = Color::FromHex(0x00ff00); -constexpr Color olive = Color::FromHex(0x808000); -constexpr Color yellow = Color::FromHex(0xffff00); -constexpr Color navy = Color::FromHex(0x000080); -constexpr Color blue = Color::FromHex(0x0000ff); -constexpr Color teal = Color::FromHex(0x008080); -constexpr Color aqua = Color::FromHex(0x00ffff); -constexpr Color orange = Color::FromHex(0xffa500); -constexpr Color aliceblue = Color::FromHex(0xf0f8ff); -constexpr Color antiquewhite = Color::FromHex(0xfaebd7); -constexpr Color aquamarine = Color::FromHex(0x7fffd4); -constexpr Color azure = Color::FromHex(0xf0ffff); -constexpr Color beige = Color::FromHex(0xf5f5dc); -constexpr Color bisque = Color::FromHex(0xffe4c4); -constexpr Color blanchedalmond = Color::FromHex(0xffebcd); -constexpr Color blueviolet = Color::FromHex(0x8a2be2); -constexpr Color brown = Color::FromHex(0xa52a2a); -constexpr Color burlywood = Color::FromHex(0xdeb887); -constexpr Color cadetblue = Color::FromHex(0x5f9ea0); -constexpr Color chartreuse = Color::FromHex(0x7fff00); -constexpr Color chocolate = Color::FromHex(0xd2691e); -constexpr Color coral = Color::FromHex(0xff7f50); -constexpr Color cornflowerblue = Color::FromHex(0x6495ed); -constexpr Color cornsilk = Color::FromHex(0xfff8dc); -constexpr Color crimson = Color::FromHex(0xdc143c); -constexpr Color cyan = aqua; -constexpr Color darkblue = Color::FromHex(0x00008b); -constexpr Color darkcyan = Color::FromHex(0x008b8b); -constexpr Color darkgoldenrod = Color::FromHex(0xb8860b); -constexpr Color darkgray = Color::FromHex(0xa9a9a9); -constexpr Color darkgreen = Color::FromHex(0x006400); -constexpr Color darkgrey = Color::FromHex(0xa9a9a9); -constexpr Color darkkhaki = Color::FromHex(0xbdb76b); -constexpr Color darkmagenta = Color::FromHex(0x8b008b); -constexpr Color darkolivegreen = Color::FromHex(0x556b2f); -constexpr Color darkorange = Color::FromHex(0xff8c00); -constexpr Color darkorchid = Color::FromHex(0x9932cc); -constexpr Color darkred = Color::FromHex(0x8b0000); -constexpr Color darksalmon = Color::FromHex(0xe9967a); -constexpr Color darkseagreen = Color::FromHex(0x8fbc8f); -constexpr Color darkslateblue = Color::FromHex(0x483d8b); -constexpr Color darkslategray = Color::FromHex(0x2f4f4f); -constexpr Color darkslategrey = Color::FromHex(0x2f4f4f); -constexpr Color darkturquoise = Color::FromHex(0x00ced1); -constexpr Color darkviolet = Color::FromHex(0x9400d3); -constexpr Color deeppink = Color::FromHex(0xff1493); -constexpr Color deepskyblue = Color::FromHex(0x00bfff); -constexpr Color dimgray = Color::FromHex(0x696969); -constexpr Color dimgrey = Color::FromHex(0x696969); -constexpr Color dodgerblue = Color::FromHex(0x1e90ff); -constexpr Color firebrick = Color::FromHex(0xb22222); -constexpr Color floralwhite = Color::FromHex(0xfffaf0); -constexpr Color forestgreen = Color::FromHex(0x228b22); -constexpr Color gainsboro = Color::FromHex(0xdcdcdc); -constexpr Color ghostwhite = Color::FromHex(0xf8f8ff); -constexpr Color gold = Color::FromHex(0xffd700); -constexpr Color goldenrod = Color::FromHex(0xdaa520); -constexpr Color greenyellow = Color::FromHex(0xadff2f); -constexpr Color grey = Color::FromHex(0x808080); -constexpr Color honeydew = Color::FromHex(0xf0fff0); -constexpr Color hotpink = Color::FromHex(0xff69b4); -constexpr Color indianred = Color::FromHex(0xcd5c5c); -constexpr Color indigo = Color::FromHex(0x4b0082); -constexpr Color ivory = Color::FromHex(0xfffff0); -constexpr Color khaki = Color::FromHex(0xf0e68c); -constexpr Color lavender = Color::FromHex(0xe6e6fa); -constexpr Color lavenderblush = Color::FromHex(0xfff0f5); -constexpr Color lawngreen = Color::FromHex(0x7cfc00); -constexpr Color lemonchiffon = Color::FromHex(0xfffacd); -constexpr Color lightblue = Color::FromHex(0xadd8e6); -constexpr Color lightcoral = Color::FromHex(0xf08080); -constexpr Color lightcyan = Color::FromHex(0xe0ffff); -constexpr Color lightgoldenrodyellow = Color::FromHex(0xfafad2); -constexpr Color lightgray = Color::FromHex(0xd3d3d3); -constexpr Color lightgreen = Color::FromHex(0x90ee90); -constexpr Color lightgrey = Color::FromHex(0xd3d3d3); -constexpr Color lightpink = Color::FromHex(0xffb6c1); -constexpr Color lightsalmon = Color::FromHex(0xffa07a); -constexpr Color lightseagreen = Color::FromHex(0x20b2aa); -constexpr Color lightskyblue = Color::FromHex(0x87cefa); -constexpr Color lightslategray = Color::FromHex(0x778899); -constexpr Color lightslategrey = Color::FromHex(0x778899); -constexpr Color lightsteelblue = Color::FromHex(0xb0c4de); -constexpr Color lightyellow = Color::FromHex(0xffffe0); -constexpr Color limegreen = Color::FromHex(0x32cd32); -constexpr Color linen = Color::FromHex(0xfaf0e6); -constexpr Color magenta = fuchsia; -constexpr Color mediumaquamarine = Color::FromHex(0x66cdaa); -constexpr Color mediumblue = Color::FromHex(0x0000cd); -constexpr Color mediumorchid = Color::FromHex(0xba55d3); -constexpr Color mediumpurple = Color::FromHex(0x9370db); -constexpr Color mediumseagreen = Color::FromHex(0x3cb371); -constexpr Color mediumslateblue = Color::FromHex(0x7b68ee); -constexpr Color mediumspringgreen = Color::FromHex(0x00fa9a); -constexpr Color mediumturquoise = Color::FromHex(0x48d1cc); -constexpr Color mediumvioletred = Color::FromHex(0xc71585); -constexpr Color midnightblue = Color::FromHex(0x191970); -constexpr Color mintcream = Color::FromHex(0xf5fffa); -constexpr Color mistyrose = Color::FromHex(0xffe4e1); -constexpr Color moccasin = Color::FromHex(0xffe4b5); -constexpr Color navajowhite = Color::FromHex(0xffdead); -constexpr Color oldlace = Color::FromHex(0xfdf5e6); -constexpr Color olivedrab = Color::FromHex(0x6b8e23); -constexpr Color orangered = Color::FromHex(0xff4500); -constexpr Color orchid = Color::FromHex(0xda70d6); -constexpr Color palegoldenrod = Color::FromHex(0xeee8aa); -constexpr Color palegreen = Color::FromHex(0x98fb98); -constexpr Color paleturquoise = Color::FromHex(0xafeeee); -constexpr Color palevioletred = Color::FromHex(0xdb7093); -constexpr Color papayawhip = Color::FromHex(0xffefd5); -constexpr Color peachpuff = Color::FromHex(0xffdab9); -constexpr Color peru = Color::FromHex(0xcd853f); -constexpr Color pink = Color::FromHex(0xffc0cb); -constexpr Color plum = Color::FromHex(0xdda0dd); -constexpr Color powderblue = Color::FromHex(0xb0e0e6); -constexpr Color rosybrown = Color::FromHex(0xbc8f8f); -constexpr Color royalblue = Color::FromHex(0x4169e1); -constexpr Color saddlebrown = Color::FromHex(0x8b4513); -constexpr Color salmon = Color::FromHex(0xfa8072); -constexpr Color sandybrown = Color::FromHex(0xf4a460); -constexpr Color seagreen = Color::FromHex(0x2e8b57); -constexpr Color seashell = Color::FromHex(0xfff5ee); -constexpr Color sienna = Color::FromHex(0xa0522d); -constexpr Color skyblue = Color::FromHex(0x87ceeb); -constexpr Color slateblue = Color::FromHex(0x6a5acd); -constexpr Color slategray = Color::FromHex(0x708090); -constexpr Color slategrey = Color::FromHex(0x708090); -constexpr Color snow = Color::FromHex(0xfffafa); -constexpr Color springgreen = Color::FromHex(0x00ff7f); -constexpr Color steelblue = Color::FromHex(0x4682b4); -constexpr Color tan = Color::FromHex(0xd2b48c); -constexpr Color thistle = Color::FromHex(0xd8bfd8); -constexpr Color tomato = Color::FromHex(0xff6347); -constexpr Color turquoise = Color::FromHex(0x40e0d0); -constexpr Color violet = Color::FromHex(0xee82ee); -constexpr Color wheat = Color::FromHex(0xf5deb3); -constexpr Color whitesmoke = Color::FromHex(0xf5f5f5); -constexpr Color yellowgreen = Color::FromHex(0x9acd32); -constexpr Color rebeccapurple = Color::FromHex(0x663399); -} // namespace colors -} // namespace cru::platform - -template <> -struct std::hash { - std::size_t operator()(const cru::platform::Color& color) const { - std::size_t seed = 0; - cru::hash_combine(seed, color.red); - cru::hash_combine(seed, color.green); - cru::hash_combine(seed, color.blue); - cru::hash_combine(seed, color.alpha); - return seed; - } -}; - -namespace cru::platform { -namespace details { -extern const std::unordered_map predefined_name_color_map; -} // namespace details - -std::optional GetPredefinedColorByName(StringView name); - -inline String ToString(const Color& color) { - return cru::Format(u"rgba({}, {}, {}, {})", color.red, color.green, - color.blue, color.alpha); -} -} // namespace cru::platform diff --git a/include/cru/platform/Exception.h b/include/cru/platform/Exception.h new file mode 100644 index 00000000..7d194d41 --- /dev/null +++ b/include/cru/platform/Exception.h @@ -0,0 +1,34 @@ +#pragma once +#include "Base.h" +#include "cru/common/Base.h" +#include "cru/common/Exception.h" +#include "cru/common/platform/Exception.h" + +namespace cru::platform { +// This exception is thrown when a resource is used on another platform. +// Of course, you can't mix resources of two different platform. +// For example, Win32 Brush (may add in the future) with Direct Painter. +class CRU_PLATFORM_API UnsupportPlatformException : public Exception { + public: + using Exception::Exception; // inherit constructors + + CRU_DEFAULT_COPY(UnsupportPlatformException) + CRU_DEFAULT_MOVE(UnsupportPlatformException) + + CRU_DEFAULT_DESTRUCTOR(UnsupportPlatformException) +}; + +// This exception is thrown when a resource has been disposed and not usable +// again. +// For example, calling Build twice on a GeometryBuilder::Build will lead to +// this exception. +class CRU_PLATFORM_API ReuseException : public Exception { + public: + using Exception::Exception; // inherit constructors + + CRU_DEFAULT_COPY(ReuseException) + CRU_DEFAULT_MOVE(ReuseException) + + CRU_DEFAULT_DESTRUCTOR(ReuseException) +}; +} // namespace cru::platform diff --git a/include/cru/platform/Exception.hpp b/include/cru/platform/Exception.hpp deleted file mode 100644 index b50e8c67..00000000 --- a/include/cru/platform/Exception.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "Base.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/Exception.hpp" -#include "cru/common/platform/Exception.hpp" - -namespace cru::platform { -// This exception is thrown when a resource is used on another platform. -// Of course, you can't mix resources of two different platform. -// For example, Win32 Brush (may add in the future) with Direct Painter. -class CRU_PLATFORM_API UnsupportPlatformException : public Exception { - public: - using Exception::Exception; // inherit constructors - - CRU_DEFAULT_COPY(UnsupportPlatformException) - CRU_DEFAULT_MOVE(UnsupportPlatformException) - - CRU_DEFAULT_DESTRUCTOR(UnsupportPlatformException) -}; - -// This exception is thrown when a resource has been disposed and not usable -// again. -// For example, calling Build twice on a GeometryBuilder::Build will lead to -// this exception. -class CRU_PLATFORM_API ReuseException : public Exception { - public: - using Exception::Exception; // inherit constructors - - CRU_DEFAULT_COPY(ReuseException) - CRU_DEFAULT_MOVE(ReuseException) - - CRU_DEFAULT_DESTRUCTOR(ReuseException) -}; -} // namespace cru::platform diff --git a/include/cru/platform/GraphicsBase.h b/include/cru/platform/GraphicsBase.h new file mode 100644 index 00000000..8fb9a3af --- /dev/null +++ b/include/cru/platform/GraphicsBase.h @@ -0,0 +1,287 @@ +#pragma once +#include "cru/common/Base.h" + +#include "cru/common/Range.h" +#include "cru/common/String.h" +#include "cru/common/Format.h" + +#include +#include +#include +#include +#include + +namespace cru::platform { +struct Size; + +struct Point final { + constexpr Point() = default; + constexpr Point(const float x, const float y) : x(x), y(y) {} + explicit constexpr Point(const Size& size); + + constexpr Point& operator+=(const Point& other) { + this->x += other.x; + this->y += other.y; + return *this; + } + + float x = 0; + float y = 0; +}; + +constexpr Point operator+(const Point& left, const Point& right) { + return Point(left.x + right.x, left.y + right.y); +} + +constexpr Point operator-(const Point& left, const Point& right) { + return Point(left.x - right.x, left.y - right.y); +} + +constexpr bool operator==(const Point& left, const Point& right) { + return left.x == right.x && left.y == right.y; +} + +constexpr bool operator!=(const Point& left, const Point& right) { + return !(left == right); +} + +inline String ToString(const Point& point) { + return Format(u"(x: {}, y: {})", point.x, point.y); +} + +struct Size final { + constexpr Size() = default; + constexpr Size(const float width, const float height) + : width(width), height(height) {} + explicit constexpr Size(const Point& point) + : width(point.x), height(point.y) {} + + constexpr static Size Infinate() { + return Size{std::numeric_limits::max(), + std::numeric_limits::max()}; + } + + float width = 0; + float height = 0; +}; + +constexpr Point::Point(const Size& size) : x(size.width), y(size.height) {} + +constexpr Size operator+(const Size& left, const Size& right) { + return Size(left.width + right.width, left.height + right.height); +} + +constexpr Size operator-(const Size& left, const Size& right) { + return Size(left.width - right.width, left.height - right.height); +} + +constexpr bool operator==(const Size& left, const Size& right) { + return left.width == right.width && left.height == right.height; +} + +constexpr bool operator!=(const Size& left, const Size& right) { + return !(left == right); +} + +inline String ToString(const Size& size) { + return Format(u"(width: {}, height: {})", size.width, size.height); +} + +struct Thickness final { + constexpr Thickness() : Thickness(0) {} + + constexpr explicit Thickness(const float width) + : left(width), top(width), right(width), bottom(width) {} + + constexpr explicit Thickness(const float horizontal, const float vertical) + : left(horizontal), top(vertical), right(horizontal), bottom(vertical) {} + + constexpr Thickness(const float left, const float top, const float right, + const float bottom) + : left(left), top(top), right(right), bottom(bottom) {} + + constexpr float GetHorizontalTotal() const { return left + right; } + + constexpr float GetVerticalTotal() const { return top + bottom; } + + void SetLeftRight(const float value) { left = right = value; } + + void SetTopBottom(const float value) { top = bottom = value; } + + void SetAll(const float value) { left = top = right = bottom = value; } + + constexpr float Validate() const { + return left >= 0.0 && top >= 0.0 && right >= 0.0 && bottom >= 0.0; + } + + float left; + float top; + float right; + float bottom; +}; + +constexpr Size operator+(const Size& size, const Thickness& thickness) { + return {size.width + thickness.left + thickness.right, + size.height + thickness.top + thickness.bottom}; +} + +constexpr Size operator+(const Thickness& thickness, const Size& size) { + return operator+(size, thickness); +} + +constexpr Thickness operator+(const Thickness& left, const Thickness& right) { + return {left.left + right.left, left.top + right.top, + left.right + right.right, left.bottom + right.bottom}; +} + +constexpr bool operator==(const Thickness& left, const Thickness& right) { + return left.left == right.left && left.top == right.top && + left.right == right.right && left.bottom == right.bottom; +} + +constexpr bool operator!=(const Thickness& left, const Thickness& right) { + return !(left == right); +} + +struct Rect final { + constexpr Rect() = default; + constexpr Rect(const float left, const float top, const float width, + const float height) + : left(left), top(top), width(width), height(height) {} + constexpr Rect(const Point& lefttop, const Size& size) + : left(lefttop.x), + top(lefttop.y), + width(size.width), + height(size.height) {} + + constexpr static Rect FromVertices(const float left, const float top, + const float right, const float bottom) { + return Rect(left, top, right - left, bottom - top); + } + + constexpr static Rect FromCenter(const Point& center, const float width, + const float height) { + return Rect(center.x - width / 2.0f, center.y - height / 2.0f, width, + height); + } + + constexpr float GetRight() const { return left + width; } + + constexpr float GetBottom() const { return top + height; } + + constexpr Point GetLeftTop() const { return Point(left, top); } + + constexpr Point GetRightBottom() const { + return Point(left + width, top + height); + } + + constexpr Point GetLeftBottom() const { return Point(left, top + height); } + + constexpr Point GetRightTop() const { return Point(left + width, top); } + + constexpr Point GetCenter() const { + return Point(left + width / 2.0f, top + height / 2.0f); + } + + constexpr void SetSize(const Size& size) { + width = size.width; + height = size.height; + } + + constexpr Size GetSize() const { return Size(width, height); } + + constexpr Rect Expand(const Thickness& thickness) const { + return Rect(left - thickness.left, top - thickness.top, + width + thickness.GetHorizontalTotal(), + height + thickness.GetVerticalTotal()); + } + + constexpr Rect Shrink(const Thickness& thickness) const { + return Rect(left + thickness.left, top + thickness.top, + width - thickness.GetHorizontalTotal(), + height - thickness.GetVerticalTotal()); + } + + constexpr bool IsPointInside(const Point& point) const { + return point.x >= left && point.x < GetRight() && point.y >= top && + point.y < GetBottom(); + } + + constexpr Rect Normalize() const { + Rect result = *this; + if (result.width < 0) { + result.left += result.width; + result.width = -result.width; + } + if (result.height < 0) { + result.top += result.height; + result.height = -result.height; + } + return result; + } + + float left = 0.0f; + float top = 0.0f; + float width = 0.0f; + float height = 0.0f; +}; + +constexpr bool operator==(const Rect& left, const Rect& right) { + return left.left == right.left && left.top == right.top && + left.width == right.width && left.height == right.height; +} + +constexpr bool operator!=(const Rect& left, const Rect& right) { + return !(left == right); +} + +struct RoundedRect final { + constexpr RoundedRect() = default; + constexpr RoundedRect(const Rect& rect, const float radius_x, + const float radius_y) + : rect(rect), radius_x(radius_x), radius_y(radius_y) {} + + Rect rect{}; + float radius_x = 0.0f; + float radius_y = 0.0f; +}; + +constexpr bool operator==(const RoundedRect& left, const RoundedRect& right) { + return left.rect == right.rect && left.radius_x == right.radius_x && + left.radius_y == right.radius_y; +} + +constexpr bool operator!=(const RoundedRect& left, const RoundedRect& right) { + return !(left == right); +} + +struct Ellipse final { + constexpr Ellipse() = default; + constexpr Ellipse(const Point& center, const float radius_x, + const float radius_y) + : center(center), radius_x(radius_x), radius_y(radius_y) {} + + constexpr static Ellipse FromRect(const Rect& rect) { + return Ellipse(rect.GetCenter(), rect.width / 2.0f, rect.height / 2.0f); + } + + constexpr Rect GetBoundRect() const { + return Rect::FromCenter(center, radius_x * 2.0f, radius_y * 2.0f); + } + + Point center{}; + float radius_x = 0.0f; + float radius_y = 0.0f; +}; + +constexpr bool operator==(const Ellipse& left, const Ellipse& right) { + return left.center == right.center && left.radius_x == right.radius_x && + left.radius_y == right.radius_y; +} + +constexpr bool operator!=(const Ellipse& left, const Ellipse& right) { + return !(left == right); +} + +using TextRange = Range; +} // namespace cru::platform diff --git a/include/cru/platform/GraphicsBase.hpp b/include/cru/platform/GraphicsBase.hpp deleted file mode 100644 index 088086e9..00000000 --- a/include/cru/platform/GraphicsBase.hpp +++ /dev/null @@ -1,287 +0,0 @@ -#pragma once -#include "cru/common/Base.hpp" - -#include "cru/common/Range.hpp" -#include "cru/common/String.hpp" -#include "cru/common/Format.hpp" - -#include -#include -#include -#include -#include - -namespace cru::platform { -struct Size; - -struct Point final { - constexpr Point() = default; - constexpr Point(const float x, const float y) : x(x), y(y) {} - explicit constexpr Point(const Size& size); - - constexpr Point& operator+=(const Point& other) { - this->x += other.x; - this->y += other.y; - return *this; - } - - float x = 0; - float y = 0; -}; - -constexpr Point operator+(const Point& left, const Point& right) { - return Point(left.x + right.x, left.y + right.y); -} - -constexpr Point operator-(const Point& left, const Point& right) { - return Point(left.x - right.x, left.y - right.y); -} - -constexpr bool operator==(const Point& left, const Point& right) { - return left.x == right.x && left.y == right.y; -} - -constexpr bool operator!=(const Point& left, const Point& right) { - return !(left == right); -} - -inline String ToString(const Point& point) { - return Format(u"(x: {}, y: {})", point.x, point.y); -} - -struct Size final { - constexpr Size() = default; - constexpr Size(const float width, const float height) - : width(width), height(height) {} - explicit constexpr Size(const Point& point) - : width(point.x), height(point.y) {} - - constexpr static Size Infinate() { - return Size{std::numeric_limits::max(), - std::numeric_limits::max()}; - } - - float width = 0; - float height = 0; -}; - -constexpr Point::Point(const Size& size) : x(size.width), y(size.height) {} - -constexpr Size operator+(const Size& left, const Size& right) { - return Size(left.width + right.width, left.height + right.height); -} - -constexpr Size operator-(const Size& left, const Size& right) { - return Size(left.width - right.width, left.height - right.height); -} - -constexpr bool operator==(const Size& left, const Size& right) { - return left.width == right.width && left.height == right.height; -} - -constexpr bool operator!=(const Size& left, const Size& right) { - return !(left == right); -} - -inline String ToString(const Size& size) { - return Format(u"(width: {}, height: {})", size.width, size.height); -} - -struct Thickness final { - constexpr Thickness() : Thickness(0) {} - - constexpr explicit Thickness(const float width) - : left(width), top(width), right(width), bottom(width) {} - - constexpr explicit Thickness(const float horizontal, const float vertical) - : left(horizontal), top(vertical), right(horizontal), bottom(vertical) {} - - constexpr Thickness(const float left, const float top, const float right, - const float bottom) - : left(left), top(top), right(right), bottom(bottom) {} - - constexpr float GetHorizontalTotal() const { return left + right; } - - constexpr float GetVerticalTotal() const { return top + bottom; } - - void SetLeftRight(const float value) { left = right = value; } - - void SetTopBottom(const float value) { top = bottom = value; } - - void SetAll(const float value) { left = top = right = bottom = value; } - - constexpr float Validate() const { - return left >= 0.0 && top >= 0.0 && right >= 0.0 && bottom >= 0.0; - } - - float left; - float top; - float right; - float bottom; -}; - -constexpr Size operator+(const Size& size, const Thickness& thickness) { - return {size.width + thickness.left + thickness.right, - size.height + thickness.top + thickness.bottom}; -} - -constexpr Size operator+(const Thickness& thickness, const Size& size) { - return operator+(size, thickness); -} - -constexpr Thickness operator+(const Thickness& left, const Thickness& right) { - return {left.left + right.left, left.top + right.top, - left.right + right.right, left.bottom + right.bottom}; -} - -constexpr bool operator==(const Thickness& left, const Thickness& right) { - return left.left == right.left && left.top == right.top && - left.right == right.right && left.bottom == right.bottom; -} - -constexpr bool operator!=(const Thickness& left, const Thickness& right) { - return !(left == right); -} - -struct Rect final { - constexpr Rect() = default; - constexpr Rect(const float left, const float top, const float width, - const float height) - : left(left), top(top), width(width), height(height) {} - constexpr Rect(const Point& lefttop, const Size& size) - : left(lefttop.x), - top(lefttop.y), - width(size.width), - height(size.height) {} - - constexpr static Rect FromVertices(const float left, const float top, - const float right, const float bottom) { - return Rect(left, top, right - left, bottom - top); - } - - constexpr static Rect FromCenter(const Point& center, const float width, - const float height) { - return Rect(center.x - width / 2.0f, center.y - height / 2.0f, width, - height); - } - - constexpr float GetRight() const { return left + width; } - - constexpr float GetBottom() const { return top + height; } - - constexpr Point GetLeftTop() const { return Point(left, top); } - - constexpr Point GetRightBottom() const { - return Point(left + width, top + height); - } - - constexpr Point GetLeftBottom() const { return Point(left, top + height); } - - constexpr Point GetRightTop() const { return Point(left + width, top); } - - constexpr Point GetCenter() const { - return Point(left + width / 2.0f, top + height / 2.0f); - } - - constexpr void SetSize(const Size& size) { - width = size.width; - height = size.height; - } - - constexpr Size GetSize() const { return Size(width, height); } - - constexpr Rect Expand(const Thickness& thickness) const { - return Rect(left - thickness.left, top - thickness.top, - width + thickness.GetHorizontalTotal(), - height + thickness.GetVerticalTotal()); - } - - constexpr Rect Shrink(const Thickness& thickness) const { - return Rect(left + thickness.left, top + thickness.top, - width - thickness.GetHorizontalTotal(), - height - thickness.GetVerticalTotal()); - } - - constexpr bool IsPointInside(const Point& point) const { - return point.x >= left && point.x < GetRight() && point.y >= top && - point.y < GetBottom(); - } - - constexpr Rect Normalize() const { - Rect result = *this; - if (result.width < 0) { - result.left += result.width; - result.width = -result.width; - } - if (result.height < 0) { - result.top += result.height; - result.height = -result.height; - } - return result; - } - - float left = 0.0f; - float top = 0.0f; - float width = 0.0f; - float height = 0.0f; -}; - -constexpr bool operator==(const Rect& left, const Rect& right) { - return left.left == right.left && left.top == right.top && - left.width == right.width && left.height == right.height; -} - -constexpr bool operator!=(const Rect& left, const Rect& right) { - return !(left == right); -} - -struct RoundedRect final { - constexpr RoundedRect() = default; - constexpr RoundedRect(const Rect& rect, const float radius_x, - const float radius_y) - : rect(rect), radius_x(radius_x), radius_y(radius_y) {} - - Rect rect{}; - float radius_x = 0.0f; - float radius_y = 0.0f; -}; - -constexpr bool operator==(const RoundedRect& left, const RoundedRect& right) { - return left.rect == right.rect && left.radius_x == right.radius_x && - left.radius_y == right.radius_y; -} - -constexpr bool operator!=(const RoundedRect& left, const RoundedRect& right) { - return !(left == right); -} - -struct Ellipse final { - constexpr Ellipse() = default; - constexpr Ellipse(const Point& center, const float radius_x, - const float radius_y) - : center(center), radius_x(radius_x), radius_y(radius_y) {} - - constexpr static Ellipse FromRect(const Rect& rect) { - return Ellipse(rect.GetCenter(), rect.width / 2.0f, rect.height / 2.0f); - } - - constexpr Rect GetBoundRect() const { - return Rect::FromCenter(center, radius_x * 2.0f, radius_y * 2.0f); - } - - Point center{}; - float radius_x = 0.0f; - float radius_y = 0.0f; -}; - -constexpr bool operator==(const Ellipse& left, const Ellipse& right) { - return left.center == right.center && left.radius_x == right.radius_x && - left.radius_y == right.radius_y; -} - -constexpr bool operator!=(const Ellipse& left, const Ellipse& right) { - return !(left == right); -} - -using TextRange = Range; -} // namespace cru::platform diff --git a/include/cru/platform/Matrix.h b/include/cru/platform/Matrix.h new file mode 100644 index 00000000..c9a52158 --- /dev/null +++ b/include/cru/platform/Matrix.h @@ -0,0 +1,110 @@ +#pragma once +#include "GraphicsBase.h" + +#include +#include + +namespace cru::platform { +struct Matrix { + float m11; + float m12; + float m21; + float m22; + float m31; + float m32; + + Matrix() {} + + Matrix(float m11, float m12, float m21, float m22, float m31, float m32) { + this->m11 = m11; + this->m12 = m12; + this->m21 = m21; + this->m22 = m22; + this->m31 = m31; + this->m32 = m32; + } + + bool IsIdentity() const { + return m11 == 1.0f && m12 == 0.0f && m21 == 0.0f && m22 == 1.0f && + m31 == 0.0f && m32 == 0.0f; + } + + Matrix& operator*=(const Matrix& matrix) { + *this = Product(*this, matrix); + return *this; + } + + Matrix operator*(const Matrix& matrix) const { + return Product(*this, matrix); + } + + Point TransformPoint(const Point& point) const { + return Point{point.x * m11 + point.y * m21 + m31, + point.x * m12 + point.y * m22 + m32}; + } + + Rect TransformRect(const Rect& rect, bool normalize = true) const { + Point lefttop = TransformPoint(rect.GetLeftTop()), + rightbottom = TransformPoint(rect.GetRightBottom()); + auto result = + Rect::FromVertices(lefttop.x, lefttop.y, rightbottom.x, rightbottom.y); + if (normalize) result = result.Normalize(); + return result; + } + + static Matrix Identity() { + return Matrix{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; + } + + static Matrix Translation(float x, float y) { + return Matrix{1.0f, 0.0f, 0.0f, 1.0f, x, y}; + } + + static Matrix Translation(const Point& point) { + return Translation(point.x, point.y); + } + + static Matrix Scale(float sx, float sy) { + return Matrix{sx, 0.0f, 0.0f, sy, 0.0f, 0.0f}; + } + + // Clockwise. + static Matrix Rotation(float angle) { + float r = AngleToRadian(angle); + float s = std::sin(r); + float c = std::cos(r); + + return Matrix{c, s, -s, c, 0.0f, 0.0f}; + } + + static Matrix Skew(float sx, float sy) { + return Matrix{1.0f, sx, sy, 1.0f, 0.0f, 0.0f}; + } + + static Matrix Product(const Matrix& a, const Matrix& b) { + return Matrix{a.m11 * b.m11 + a.m12 * b.m21, + a.m11 * b.m12 + a.m12 * b.m22, + a.m21 * b.m11 + a.m22 * b.m21, + a.m21 * b.m12 + a.m22 * b.m22, + a.m31 * b.m11 + a.m32 * b.m21 + b.m31, + a.m31 * b.m12 + a.m32 * b.m22 + b.m32}; + } + + std::optional Inverted() const { + if (m11 * m22 == m12 * m21) return std::nullopt; + Matrix result; + result.m11 = m22 / (m11 * m22 - m12 * m21); + result.m12 = m12 / (m12 * m21 - m11 * m22); + result.m21 = m21 / (m12 * m21 - m11 * m22); + result.m22 = m11 / (m11 * m22 - m12 * m21); + result.m31 = (m21 * m32 - m22 * m31) / (m11 * m22 - m12 * m21); + result.m32 = (m31 * m12 - m11 * m32) / (m11 * m22 - m12 * m21); + return result; + } + + private: + static constexpr float PI = 3.1415926535f; + + static float AngleToRadian(float angle) { return angle / 180.f * PI; } +}; +} // namespace cru::platform diff --git a/include/cru/platform/Matrix.hpp b/include/cru/platform/Matrix.hpp deleted file mode 100644 index 47917d47..00000000 --- a/include/cru/platform/Matrix.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once -#include "GraphicsBase.hpp" - -#include -#include - -namespace cru::platform { -struct Matrix { - float m11; - float m12; - float m21; - float m22; - float m31; - float m32; - - Matrix() {} - - Matrix(float m11, float m12, float m21, float m22, float m31, float m32) { - this->m11 = m11; - this->m12 = m12; - this->m21 = m21; - this->m22 = m22; - this->m31 = m31; - this->m32 = m32; - } - - bool IsIdentity() const { - return m11 == 1.0f && m12 == 0.0f && m21 == 0.0f && m22 == 1.0f && - m31 == 0.0f && m32 == 0.0f; - } - - Matrix& operator*=(const Matrix& matrix) { - *this = Product(*this, matrix); - return *this; - } - - Matrix operator*(const Matrix& matrix) const { - return Product(*this, matrix); - } - - Point TransformPoint(const Point& point) const { - return Point{point.x * m11 + point.y * m21 + m31, - point.x * m12 + point.y * m22 + m32}; - } - - Rect TransformRect(const Rect& rect, bool normalize = true) const { - Point lefttop = TransformPoint(rect.GetLeftTop()), - rightbottom = TransformPoint(rect.GetRightBottom()); - auto result = - Rect::FromVertices(lefttop.x, lefttop.y, rightbottom.x, rightbottom.y); - if (normalize) result = result.Normalize(); - return result; - } - - static Matrix Identity() { - return Matrix{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; - } - - static Matrix Translation(float x, float y) { - return Matrix{1.0f, 0.0f, 0.0f, 1.0f, x, y}; - } - - static Matrix Translation(const Point& point) { - return Translation(point.x, point.y); - } - - static Matrix Scale(float sx, float sy) { - return Matrix{sx, 0.0f, 0.0f, sy, 0.0f, 0.0f}; - } - - // Clockwise. - static Matrix Rotation(float angle) { - float r = AngleToRadian(angle); - float s = std::sin(r); - float c = std::cos(r); - - return Matrix{c, s, -s, c, 0.0f, 0.0f}; - } - - static Matrix Skew(float sx, float sy) { - return Matrix{1.0f, sx, sy, 1.0f, 0.0f, 0.0f}; - } - - static Matrix Product(const Matrix& a, const Matrix& b) { - return Matrix{a.m11 * b.m11 + a.m12 * b.m21, - a.m11 * b.m12 + a.m12 * b.m22, - a.m21 * b.m11 + a.m22 * b.m21, - a.m21 * b.m12 + a.m22 * b.m22, - a.m31 * b.m11 + a.m32 * b.m21 + b.m31, - a.m31 * b.m12 + a.m32 * b.m22 + b.m32}; - } - - std::optional Inverted() const { - if (m11 * m22 == m12 * m21) return std::nullopt; - Matrix result; - result.m11 = m22 / (m11 * m22 - m12 * m21); - result.m12 = m12 / (m12 * m21 - m11 * m22); - result.m21 = m21 / (m12 * m21 - m11 * m22); - result.m22 = m11 / (m11 * m22 - m12 * m21); - result.m31 = (m21 * m32 - m22 * m31) / (m11 * m22 - m12 * m21); - result.m32 = (m31 * m12 - m11 * m32) / (m11 * m22 - m12 * m21); - return result; - } - - private: - static constexpr float PI = 3.1415926535f; - - static float AngleToRadian(float angle) { return angle / 180.f * PI; } -}; -} // namespace cru::platform diff --git a/include/cru/platform/Resource.h b/include/cru/platform/Resource.h new file mode 100644 index 00000000..fe95ebb3 --- /dev/null +++ b/include/cru/platform/Resource.h @@ -0,0 +1,17 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Base.h" +#include "cru/common/String.h" + +#include + +namespace cru::platform { +struct CRU_PLATFORM_API IPlatformResource : virtual Interface { + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(IPlatformResource) + + virtual String GetPlatformId() const = 0; + + virtual String GetDebugString() { return String(); } +}; +} // namespace cru::platform diff --git a/include/cru/platform/Resource.hpp b/include/cru/platform/Resource.hpp deleted file mode 100644 index c89068fa..00000000 --- a/include/cru/platform/Resource.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Base.hpp" -#include "cru/common/String.hpp" - -#include - -namespace cru::platform { -struct CRU_PLATFORM_API IPlatformResource : virtual Interface { - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(IPlatformResource) - - virtual String GetPlatformId() const = 0; - - virtual String GetDebugString() { return String(); } -}; -} // namespace cru::platform diff --git a/include/cru/platform/bootstrap/Bootstrap.h b/include/cru/platform/bootstrap/Bootstrap.h new file mode 100644 index 00000000..3ab89a91 --- /dev/null +++ b/include/cru/platform/bootstrap/Bootstrap.h @@ -0,0 +1,17 @@ +#pragma once +#include "cru/platform/gui/UiApplication.h" + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_BOOTSTRAP_EXPORT_API +#define CRU_PLATFORM_BOOTSTRAP_API __declspec(dllexport) +#else +#define CRU_PLATFORM_BOOTSTRAP_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_BOOTSTRAP_API +#endif + +namespace cru::platform::bootstrap { +CRU_PLATFORM_BOOTSTRAP_API cru::platform::gui::IUiApplication* +CreateUiApplication(); +} diff --git a/include/cru/platform/bootstrap/Bootstrap.hpp b/include/cru/platform/bootstrap/Bootstrap.hpp deleted file mode 100644 index 33fb5122..00000000 --- a/include/cru/platform/bootstrap/Bootstrap.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "cru/platform/gui/UiApplication.hpp" - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_PLATFORM_BOOTSTRAP_EXPORT_API -#define CRU_PLATFORM_BOOTSTRAP_API __declspec(dllexport) -#else -#define CRU_PLATFORM_BOOTSTRAP_API __declspec(dllimport) -#endif -#else -#define CRU_PLATFORM_BOOTSTRAP_API -#endif - -namespace cru::platform::bootstrap { -CRU_PLATFORM_BOOTSTRAP_API cru::platform::gui::IUiApplication* -CreateUiApplication(); -} diff --git a/include/cru/platform/graphics/Base.h b/include/cru/platform/graphics/Base.h new file mode 100644 index 00000000..a134fb33 --- /dev/null +++ b/include/cru/platform/graphics/Base.h @@ -0,0 +1,37 @@ +#pragma once +#include "../Color.h" +#include "../GraphicsBase.h" +#include "../Matrix.h" +#include "../Resource.h" + +#include + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_GRAPHICS_EXPORT_API +#define CRU_PLATFORM_GRAPHICS_API __declspec(dllexport) +#else +#define CRU_PLATFORM_GRAPHICS_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_GRAPHICS_API +#endif + +namespace cru::platform::graphics { +// forward declarations +struct IGraphicsFactory; +struct IBrush; +struct ISolidColorBrush; +struct IFont; +struct IGeometry; +struct IGeometryBuilder; +struct IImage; +struct IImageFactory; +struct IPainter; +struct ITextLayout; + +struct TextHitTestResult { + gsl::index position; + bool trailing; + bool inside_text; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Base.hpp b/include/cru/platform/graphics/Base.hpp deleted file mode 100644 index 416f0df4..00000000 --- a/include/cru/platform/graphics/Base.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "../Color.hpp" -#include "../GraphicsBase.hpp" -#include "../Matrix.hpp" -#include "../Resource.hpp" - -#include - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_PLATFORM_GRAPHICS_EXPORT_API -#define CRU_PLATFORM_GRAPHICS_API __declspec(dllexport) -#else -#define CRU_PLATFORM_GRAPHICS_API __declspec(dllimport) -#endif -#else -#define CRU_PLATFORM_GRAPHICS_API -#endif - -namespace cru::platform::graphics { -// forward declarations -struct IGraphicsFactory; -struct IBrush; -struct ISolidColorBrush; -struct IFont; -struct IGeometry; -struct IGeometryBuilder; -struct IImage; -struct IImageFactory; -struct IPainter; -struct ITextLayout; - -struct TextHitTestResult { - gsl::index position; - bool trailing; - bool inside_text; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Brush.h b/include/cru/platform/graphics/Brush.h new file mode 100644 index 00000000..6f4a6902 --- /dev/null +++ b/include/cru/platform/graphics/Brush.h @@ -0,0 +1,11 @@ +#pragma once +#include "Resource.h" + +namespace cru::platform::graphics { +struct CRU_PLATFORM_GRAPHICS_API IBrush : virtual IGraphicsResource {}; + +struct CRU_PLATFORM_GRAPHICS_API ISolidColorBrush : virtual IBrush { + virtual Color GetColor() = 0; + virtual void SetColor(const Color& color) = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Brush.hpp b/include/cru/platform/graphics/Brush.hpp deleted file mode 100644 index 772edd5c..00000000 --- a/include/cru/platform/graphics/Brush.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "Resource.hpp" - -namespace cru::platform::graphics { -struct CRU_PLATFORM_GRAPHICS_API IBrush : virtual IGraphicsResource {}; - -struct CRU_PLATFORM_GRAPHICS_API ISolidColorBrush : virtual IBrush { - virtual Color GetColor() = 0; - virtual void SetColor(const Color& color) = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Factory.h b/include/cru/platform/graphics/Factory.h new file mode 100644 index 00000000..d197d821 --- /dev/null +++ b/include/cru/platform/graphics/Factory.h @@ -0,0 +1,32 @@ +#pragma once +#include "Resource.h" + +#include "Brush.h" +#include "Font.h" +#include "Geometry.h" +#include "Image.h" +#include "ImageFactory.h" +#include "TextLayout.h" + +namespace cru::platform::graphics { +// Entry point of the graphics module. +struct CRU_PLATFORM_GRAPHICS_API IGraphicsFactory : virtual IPlatformResource { + virtual std::unique_ptr CreateSolidColorBrush() = 0; + + virtual std::unique_ptr CreateGeometryBuilder() = 0; + + virtual std::unique_ptr CreateFont(String font_family, + float font_size) = 0; + + virtual std::unique_ptr CreateTextLayout( + std::shared_ptr font, String text) = 0; + + std::unique_ptr CreateSolidColorBrush(const Color& color) { + std::unique_ptr brush = CreateSolidColorBrush(); + brush->SetColor(color); + return brush; + } + + virtual IImageFactory* GetImageFactory() = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Factory.hpp b/include/cru/platform/graphics/Factory.hpp deleted file mode 100644 index 7aa88ebd..00000000 --- a/include/cru/platform/graphics/Factory.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "Brush.hpp" -#include "Font.hpp" -#include "Geometry.hpp" -#include "Image.hpp" -#include "ImageFactory.hpp" -#include "TextLayout.hpp" - -namespace cru::platform::graphics { -// Entry point of the graphics module. -struct CRU_PLATFORM_GRAPHICS_API IGraphicsFactory : virtual IPlatformResource { - virtual std::unique_ptr CreateSolidColorBrush() = 0; - - virtual std::unique_ptr CreateGeometryBuilder() = 0; - - virtual std::unique_ptr CreateFont(String font_family, - float font_size) = 0; - - virtual std::unique_ptr CreateTextLayout( - std::shared_ptr font, String text) = 0; - - std::unique_ptr CreateSolidColorBrush(const Color& color) { - std::unique_ptr brush = CreateSolidColorBrush(); - brush->SetColor(color); - return brush; - } - - virtual IImageFactory* GetImageFactory() = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Font.h b/include/cru/platform/graphics/Font.h new file mode 100644 index 00000000..24c35f7c --- /dev/null +++ b/include/cru/platform/graphics/Font.h @@ -0,0 +1,8 @@ +#pragma once +#include "Resource.h" + +namespace cru::platform::graphics { +struct CRU_PLATFORM_GRAPHICS_API IFont : virtual IGraphicsResource { + virtual float GetFontSize() = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Font.hpp b/include/cru/platform/graphics/Font.hpp deleted file mode 100644 index 2d1bc9a6..00000000 --- a/include/cru/platform/graphics/Font.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "Resource.hpp" - -namespace cru::platform::graphics { -struct CRU_PLATFORM_GRAPHICS_API IFont : virtual IGraphicsResource { - virtual float GetFontSize() = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Geometry.h b/include/cru/platform/graphics/Geometry.h new file mode 100644 index 00000000..732fc547 --- /dev/null +++ b/include/cru/platform/graphics/Geometry.h @@ -0,0 +1,20 @@ +#pragma once +#include "Resource.h" + +namespace cru::platform::graphics { +struct CRU_PLATFORM_GRAPHICS_API IGeometry : virtual IGraphicsResource { + virtual bool FillContains(const Point& point) = 0; +}; + +// After called Build, calling every method will throw a + +struct CRU_PLATFORM_GRAPHICS_API IGeometryBuilder : virtual IGraphicsResource { + virtual void BeginFigure(const Point& point) = 0; + virtual void LineTo(const Point& point) = 0; + virtual void QuadraticBezierTo(const Point& control_point, + const Point& end_point) = 0; + virtual void CloseFigure(bool close) = 0; + + virtual std::unique_ptr Build() = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Geometry.hpp b/include/cru/platform/graphics/Geometry.hpp deleted file mode 100644 index e83d1c51..00000000 --- a/include/cru/platform/graphics/Geometry.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Resource.hpp" - -namespace cru::platform::graphics { -struct CRU_PLATFORM_GRAPHICS_API IGeometry : virtual IGraphicsResource { - virtual bool FillContains(const Point& point) = 0; -}; - -// After called Build, calling every method will throw a - -struct CRU_PLATFORM_GRAPHICS_API IGeometryBuilder : virtual IGraphicsResource { - virtual void BeginFigure(const Point& point) = 0; - virtual void LineTo(const Point& point) = 0; - virtual void QuadraticBezierTo(const Point& control_point, - const Point& end_point) = 0; - virtual void CloseFigure(bool close) = 0; - - virtual std::unique_ptr Build() = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Image.h b/include/cru/platform/graphics/Image.h new file mode 100644 index 00000000..51e27678 --- /dev/null +++ b/include/cru/platform/graphics/Image.h @@ -0,0 +1,10 @@ +#pragma once +#include "Resource.h" + +namespace cru::platform::graphics { +struct CRU_PLATFORM_GRAPHICS_API IImage : public virtual IGraphicsResource { + virtual float GetWidth() = 0; + virtual float GetHeight() = 0; + virtual std::unique_ptr CreateWithRect(const Rect& rect) = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Image.hpp b/include/cru/platform/graphics/Image.hpp deleted file mode 100644 index e8bf6671..00000000 --- a/include/cru/platform/graphics/Image.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "Resource.hpp" - -namespace cru::platform::graphics { -struct CRU_PLATFORM_GRAPHICS_API IImage : public virtual IGraphicsResource { - virtual float GetWidth() = 0; - virtual float GetHeight() = 0; - virtual std::unique_ptr CreateWithRect(const Rect& rect) = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/ImageFactory.h b/include/cru/platform/graphics/ImageFactory.h new file mode 100644 index 00000000..2a7902b2 --- /dev/null +++ b/include/cru/platform/graphics/ImageFactory.h @@ -0,0 +1,11 @@ +#pragma once +#include "Image.h" +#include "Resource.h" +#include "cru/common/io/Stream.h" + +namespace cru::platform::graphics { +struct CRU_PLATFORM_GRAPHICS_API IImageFactory + : public virtual IGraphicsResource { + virtual std::unique_ptr DecodeFromStream(io::Stream* stream) = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/ImageFactory.hpp b/include/cru/platform/graphics/ImageFactory.hpp deleted file mode 100644 index 3997f783..00000000 --- a/include/cru/platform/graphics/ImageFactory.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "Image.hpp" -#include "Resource.hpp" -#include "cru/common/io/Stream.hpp" - -namespace cru::platform::graphics { -struct CRU_PLATFORM_GRAPHICS_API IImageFactory - : public virtual IGraphicsResource { - virtual std::unique_ptr DecodeFromStream(io::Stream* stream) = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/NullPainter.h b/include/cru/platform/graphics/NullPainter.h new file mode 100644 index 00000000..2c6e6cb1 --- /dev/null +++ b/include/cru/platform/graphics/NullPainter.h @@ -0,0 +1,84 @@ +#pragma once +#include "Painter.h" +#include "cru/common/Base.h" + +namespace cru::platform::graphics { +class CRU_PLATFORM_GRAPHICS_API NullPainter : public Object, + public virtual IPainter { + public: + NullPainter() = default; + + CRU_DELETE_COPY(NullPainter) + CRU_DELETE_MOVE(NullPainter) + + ~NullPainter() override = default; + + public: + String GetPlatformId() const override { return u"NULL"; } + + String GetDebugString() override { return u"NullPainter"; } + + Matrix GetTransform() override { return Matrix(); } + void SetTransform(const Matrix& matrix) override { CRU_UNUSED(matrix) } + + void ConcatTransform(const Matrix& matrix) override { CRU_UNUSED(matrix) } + + void Clear(const Color& color) override { CRU_UNUSED(color) } + + void DrawLine(const Point& start, const Point& end, IBrush* brush, + float width) override { + CRU_UNUSED(start) CRU_UNUSED(end) CRU_UNUSED(brush) CRU_UNUSED(width) + } + void StrokeRectangle(const Rect& rectangle, IBrush* brush, + float width) override { + CRU_UNUSED(rectangle) CRU_UNUSED(brush) CRU_UNUSED(width) + } + void FillRectangle(const Rect& rectangle, IBrush* brush) override { + CRU_UNUSED(rectangle) + CRU_UNUSED(brush) + } + void StrokeEllipse(const Rect& outline_rect, IBrush* brush, + float width) override { + CRU_UNUSED(outline_rect) + CRU_UNUSED(brush) + CRU_UNUSED(width) + } + void FillEllipse(const Rect& outline_rect, IBrush* brush) override { + CRU_UNUSED(outline_rect) + CRU_UNUSED(brush) + } + + void StrokeGeometry(IGeometry* geometry, IBrush* brush, + float width) override { + CRU_UNUSED(geometry) + CRU_UNUSED(brush) + CRU_UNUSED(width) + } + void FillGeometry(IGeometry* geometry, IBrush* brush) override { + CRU_UNUSED(geometry) + CRU_UNUSED(brush) + } + + void DrawText(const Point& offset, ITextLayout* text_layout, + IBrush* brush) override { + CRU_UNUSED(offset) + CRU_UNUSED(text_layout) + CRU_UNUSED(brush) + } + + void DrawImage(const Point& offset, IImage* image) override { + CRU_UNUSED(offset) + CRU_UNUSED(image) + } + + void PushLayer(const Rect& bounds) override { CRU_UNUSED(bounds) } + + void PopLayer() override {} + + void PushState() override {} + + void PopState() override {} + + void EndDraw() override {} +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/NullPainter.hpp b/include/cru/platform/graphics/NullPainter.hpp deleted file mode 100644 index 54c610c1..00000000 --- a/include/cru/platform/graphics/NullPainter.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include "Painter.hpp" -#include "cru/common/Base.hpp" - -namespace cru::platform::graphics { -class CRU_PLATFORM_GRAPHICS_API NullPainter : public Object, - public virtual IPainter { - public: - NullPainter() = default; - - CRU_DELETE_COPY(NullPainter) - CRU_DELETE_MOVE(NullPainter) - - ~NullPainter() override = default; - - public: - String GetPlatformId() const override { return u"NULL"; } - - String GetDebugString() override { return u"NullPainter"; } - - Matrix GetTransform() override { return Matrix(); } - void SetTransform(const Matrix& matrix) override { CRU_UNUSED(matrix) } - - void ConcatTransform(const Matrix& matrix) override { CRU_UNUSED(matrix) } - - void Clear(const Color& color) override { CRU_UNUSED(color) } - - void DrawLine(const Point& start, const Point& end, IBrush* brush, - float width) override { - CRU_UNUSED(start) CRU_UNUSED(end) CRU_UNUSED(brush) CRU_UNUSED(width) - } - void StrokeRectangle(const Rect& rectangle, IBrush* brush, - float width) override { - CRU_UNUSED(rectangle) CRU_UNUSED(brush) CRU_UNUSED(width) - } - void FillRectangle(const Rect& rectangle, IBrush* brush) override { - CRU_UNUSED(rectangle) - CRU_UNUSED(brush) - } - void StrokeEllipse(const Rect& outline_rect, IBrush* brush, - float width) override { - CRU_UNUSED(outline_rect) - CRU_UNUSED(brush) - CRU_UNUSED(width) - } - void FillEllipse(const Rect& outline_rect, IBrush* brush) override { - CRU_UNUSED(outline_rect) - CRU_UNUSED(brush) - } - - void StrokeGeometry(IGeometry* geometry, IBrush* brush, - float width) override { - CRU_UNUSED(geometry) - CRU_UNUSED(brush) - CRU_UNUSED(width) - } - void FillGeometry(IGeometry* geometry, IBrush* brush) override { - CRU_UNUSED(geometry) - CRU_UNUSED(brush) - } - - void DrawText(const Point& offset, ITextLayout* text_layout, - IBrush* brush) override { - CRU_UNUSED(offset) - CRU_UNUSED(text_layout) - CRU_UNUSED(brush) - } - - void DrawImage(const Point& offset, IImage* image) override { - CRU_UNUSED(offset) - CRU_UNUSED(image) - } - - void PushLayer(const Rect& bounds) override { CRU_UNUSED(bounds) } - - void PopLayer() override {} - - void PushState() override {} - - void PopState() override {} - - void EndDraw() override {} -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Painter.h b/include/cru/platform/graphics/Painter.h new file mode 100644 index 00000000..38ff8849 --- /dev/null +++ b/include/cru/platform/graphics/Painter.h @@ -0,0 +1,42 @@ +#pragma once +#include "Resource.h" + +namespace cru::platform::graphics { + +struct CRU_PLATFORM_GRAPHICS_API IPainter : virtual IPlatformResource { + virtual Matrix GetTransform() = 0; + virtual void SetTransform(const Matrix& matrix) = 0; + + virtual void ConcatTransform(const Matrix& matrix) = 0; + + virtual void Clear(const Color& color) = 0; + + virtual void DrawLine(const Point& start, const Point& end, IBrush* brush, + float width) = 0; + virtual void StrokeRectangle(const Rect& rectangle, IBrush* brush, + float width) = 0; + virtual void FillRectangle(const Rect& rectangle, IBrush* brush) = 0; + virtual void StrokeEllipse(const Rect& outline_rect, IBrush* brush, + float width) = 0; + virtual void FillEllipse(const Rect& outline_rect, IBrush* brush) = 0; + + virtual void StrokeGeometry(IGeometry* geometry, IBrush* brush, + float width) = 0; + virtual void FillGeometry(IGeometry* geometry, IBrush* brush) = 0; + + virtual void DrawText(const Point& offset, ITextLayout* text_layout, + IBrush* brush) = 0; + + virtual void DrawImage(const Point& offset, IImage* image) = 0; + + virtual void PushLayer(const Rect& bounds) = 0; + + virtual void PopLayer() = 0; + + virtual void PushState() = 0; + + virtual void PopState() = 0; + + virtual void EndDraw() = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Painter.hpp b/include/cru/platform/graphics/Painter.hpp deleted file mode 100644 index 171e6260..00000000 --- a/include/cru/platform/graphics/Painter.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "Resource.hpp" - -namespace cru::platform::graphics { - -struct CRU_PLATFORM_GRAPHICS_API IPainter : virtual IPlatformResource { - virtual Matrix GetTransform() = 0; - virtual void SetTransform(const Matrix& matrix) = 0; - - virtual void ConcatTransform(const Matrix& matrix) = 0; - - virtual void Clear(const Color& color) = 0; - - virtual void DrawLine(const Point& start, const Point& end, IBrush* brush, - float width) = 0; - virtual void StrokeRectangle(const Rect& rectangle, IBrush* brush, - float width) = 0; - virtual void FillRectangle(const Rect& rectangle, IBrush* brush) = 0; - virtual void StrokeEllipse(const Rect& outline_rect, IBrush* brush, - float width) = 0; - virtual void FillEllipse(const Rect& outline_rect, IBrush* brush) = 0; - - virtual void StrokeGeometry(IGeometry* geometry, IBrush* brush, - float width) = 0; - virtual void FillGeometry(IGeometry* geometry, IBrush* brush) = 0; - - virtual void DrawText(const Point& offset, ITextLayout* text_layout, - IBrush* brush) = 0; - - virtual void DrawImage(const Point& offset, IImage* image) = 0; - - virtual void PushLayer(const Rect& bounds) = 0; - - virtual void PopLayer() = 0; - - virtual void PushState() = 0; - - virtual void PopState() = 0; - - virtual void EndDraw() = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Resource.h b/include/cru/platform/graphics/Resource.h new file mode 100644 index 00000000..ab1b8de6 --- /dev/null +++ b/include/cru/platform/graphics/Resource.h @@ -0,0 +1,10 @@ +#pragma once +#include "Base.h" + +namespace cru::platform::graphics { +struct IGraphicsFactory; + +struct CRU_PLATFORM_GRAPHICS_API IGraphicsResource : virtual IPlatformResource { + virtual IGraphicsFactory* GetGraphicsFactory() = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Resource.hpp b/include/cru/platform/graphics/Resource.hpp deleted file mode 100644 index e559b0e9..00000000 --- a/include/cru/platform/graphics/Resource.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru::platform::graphics { -struct IGraphicsFactory; - -struct CRU_PLATFORM_GRAPHICS_API IGraphicsResource : virtual IPlatformResource { - virtual IGraphicsFactory* GetGraphicsFactory() = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/TextLayout.h b/include/cru/platform/graphics/TextLayout.h new file mode 100644 index 00000000..e060186b --- /dev/null +++ b/include/cru/platform/graphics/TextLayout.h @@ -0,0 +1,33 @@ +#pragma once +#include "Resource.h" + +#include +#include + +namespace cru::platform::graphics { +// Requirement: +// All text must be left-top aligned. +struct CRU_PLATFORM_GRAPHICS_API ITextLayout : virtual IGraphicsResource { + virtual String GetText() = 0; + virtual void SetText(String new_text) = 0; + + virtual std::shared_ptr GetFont() = 0; + virtual void SetFont(std::shared_ptr font) = 0; + + virtual void SetMaxWidth(float max_width) = 0; + virtual void SetMaxHeight(float max_height) = 0; + + virtual bool IsEditMode() = 0; + virtual void SetEditMode(bool enable) = 0; + + virtual Index GetLineIndexFromCharIndex(Index char_index) = 0; + virtual Index GetLineCount() = 0; + virtual float GetLineHeight(Index line_index) = 0; + + virtual Rect GetTextBounds(bool includingTrailingSpace = false) = 0; + virtual std::vector TextRangeRect(const TextRange& text_range) = 0; + // Width is always 0, height is line height. + virtual Rect TextSinglePoint(Index position, bool trailing) = 0; + virtual TextHitTestResult HitTest(const Point& point) = 0; +}; +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/TextLayout.hpp b/include/cru/platform/graphics/TextLayout.hpp deleted file mode 100644 index f9ccc824..00000000 --- a/include/cru/platform/graphics/TextLayout.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include -#include - -namespace cru::platform::graphics { -// Requirement: -// All text must be left-top aligned. -struct CRU_PLATFORM_GRAPHICS_API ITextLayout : virtual IGraphicsResource { - virtual String GetText() = 0; - virtual void SetText(String new_text) = 0; - - virtual std::shared_ptr GetFont() = 0; - virtual void SetFont(std::shared_ptr font) = 0; - - virtual void SetMaxWidth(float max_width) = 0; - virtual void SetMaxHeight(float max_height) = 0; - - virtual bool IsEditMode() = 0; - virtual void SetEditMode(bool enable) = 0; - - virtual Index GetLineIndexFromCharIndex(Index char_index) = 0; - virtual Index GetLineCount() = 0; - virtual float GetLineHeight(Index line_index) = 0; - - virtual Rect GetTextBounds(bool includingTrailingSpace = false) = 0; - virtual std::vector TextRangeRect(const TextRange& text_range) = 0; - // Width is always 0, height is line height. - virtual Rect TextSinglePoint(Index position, bool trailing) = 0; - virtual TextHitTestResult HitTest(const Point& point) = 0; -}; -} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/util/Painter.h b/include/cru/platform/graphics/util/Painter.h new file mode 100644 index 00000000..e36d5c55 --- /dev/null +++ b/include/cru/platform/graphics/util/Painter.h @@ -0,0 +1,18 @@ +#pragma once +#include "../Painter.h" + +#include +#include + +namespace cru::platform::graphics::util { +template +void WithTransform(IPainter* painter, const Matrix& matrix, const Fn& action) { + static_assert(std::is_invocable_v, + "Action must can be be invoked with painter."); + const auto old = painter->GetTransform(); + painter->PushState(); + painter->ConcatTransform(matrix); + action(painter); + painter->PopState(); +} +} // namespace cru::platform::graphics::util diff --git a/include/cru/platform/graphics/util/Painter.hpp b/include/cru/platform/graphics/util/Painter.hpp deleted file mode 100644 index 2e0fbb51..00000000 --- a/include/cru/platform/graphics/util/Painter.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "../Painter.hpp" - -#include -#include - -namespace cru::platform::graphics::util { -template -void WithTransform(IPainter* painter, const Matrix& matrix, const Fn& action) { - static_assert(std::is_invocable_v, - "Action must can be be invoked with painter."); - const auto old = painter->GetTransform(); - painter->PushState(); - painter->ConcatTransform(matrix); - action(painter); - painter->PopState(); -} -} // namespace cru::platform::graphics::util diff --git a/include/cru/platform/gui/Base.h b/include/cru/platform/gui/Base.h new file mode 100644 index 00000000..789ab308 --- /dev/null +++ b/include/cru/platform/gui/Base.h @@ -0,0 +1,37 @@ +#pragma once +#include "cru/common/Base.h" +#include "cru/common/Bitmask.h" +#include "cru/platform/graphics/Base.h" + +#include "../Resource.h" + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_GUI_EXPORT_API +#define CRU_PLATFORM_GUI_API __declspec(dllexport) +#else +#define CRU_PLATFORM_GUI_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_GUI_API +#endif + +namespace cru::platform::gui { +struct ICursor; +struct ICursorManager; +struct IUiApplication; +struct INativeWindow; +struct IInputMethodContext; +struct IClipboard; + +namespace details { +struct TagMouseButton {}; +} // namespace details + +using MouseButton = Bitmask; + +namespace mouse_buttons { +constexpr MouseButton left{0b1}; +constexpr MouseButton middle{0b10}; +constexpr MouseButton right{0b100}; +} // namespace mouse_buttons +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Base.hpp b/include/cru/platform/gui/Base.hpp deleted file mode 100644 index b432a2e0..00000000 --- a/include/cru/platform/gui/Base.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "cru/common/Base.hpp" -#include "cru/common/Bitmask.hpp" -#include "cru/platform/graphics/Base.hpp" - -#include "../Resource.hpp" - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_PLATFORM_GUI_EXPORT_API -#define CRU_PLATFORM_GUI_API __declspec(dllexport) -#else -#define CRU_PLATFORM_GUI_API __declspec(dllimport) -#endif -#else -#define CRU_PLATFORM_GUI_API -#endif - -namespace cru::platform::gui { -struct ICursor; -struct ICursorManager; -struct IUiApplication; -struct INativeWindow; -struct IInputMethodContext; -struct IClipboard; - -namespace details { -struct TagMouseButton {}; -} // namespace details - -using MouseButton = Bitmask; - -namespace mouse_buttons { -constexpr MouseButton left{0b1}; -constexpr MouseButton middle{0b10}; -constexpr MouseButton right{0b100}; -} // namespace mouse_buttons -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Clipboard.h b/include/cru/platform/gui/Clipboard.h new file mode 100644 index 00000000..47267895 --- /dev/null +++ b/include/cru/platform/gui/Clipboard.h @@ -0,0 +1,9 @@ +#pragma once +#include "Base.h" + +namespace cru::platform::gui { +struct IClipboard : virtual IPlatformResource { + virtual String GetText() = 0; + virtual void SetText(String text) = 0; +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Clipboard.hpp b/include/cru/platform/gui/Clipboard.hpp deleted file mode 100644 index c3467de5..00000000 --- a/include/cru/platform/gui/Clipboard.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru::platform::gui { -struct IClipboard : virtual IPlatformResource { - virtual String GetText() = 0; - virtual void SetText(String text) = 0; -}; -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Cursor.h b/include/cru/platform/gui/Cursor.h new file mode 100644 index 00000000..99168656 --- /dev/null +++ b/include/cru/platform/gui/Cursor.h @@ -0,0 +1,16 @@ +#pragma once +#include "Base.h" + +#include + +namespace cru::platform::gui { +enum class SystemCursorType { Arrow, Hand, IBeam }; + +struct ICursor : virtual IPlatformResource {}; + +struct ICursorManager : virtual IPlatformResource { + virtual std::shared_ptr GetSystemCursor(SystemCursorType type) = 0; + + // TODO: Add method to create cursor. +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Cursor.hpp b/include/cru/platform/gui/Cursor.hpp deleted file mode 100644 index abc8b064..00000000 --- a/include/cru/platform/gui/Cursor.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include - -namespace cru::platform::gui { -enum class SystemCursorType { Arrow, Hand, IBeam }; - -struct ICursor : virtual IPlatformResource {}; - -struct ICursorManager : virtual IPlatformResource { - virtual std::shared_ptr GetSystemCursor(SystemCursorType type) = 0; - - // TODO: Add method to create cursor. -}; -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/DebugFlags.h b/include/cru/platform/gui/DebugFlags.h new file mode 100644 index 00000000..2b7c7c19 --- /dev/null +++ b/include/cru/platform/gui/DebugFlags.h @@ -0,0 +1,8 @@ +#pragma once + +namespace cru::platform::gui { +struct DebugFlags { + static constexpr int paint = 0; + static constexpr int input_method = 0; +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/DebugFlags.hpp b/include/cru/platform/gui/DebugFlags.hpp deleted file mode 100644 index 2b7c7c19..00000000 --- a/include/cru/platform/gui/DebugFlags.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace cru::platform::gui { -struct DebugFlags { - static constexpr int paint = 0; - static constexpr int input_method = 0; -}; -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/InputMethod.h b/include/cru/platform/gui/InputMethod.h new file mode 100644 index 00000000..45e11c06 --- /dev/null +++ b/include/cru/platform/gui/InputMethod.h @@ -0,0 +1,55 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Event.h" + +#include +#include + +namespace cru::platform::gui { +struct CompositionClause { + int start; + int end; + bool target; +}; + +using CompositionClauses = std::vector; + +struct CompositionText { + String text; + CompositionClauses clauses; + TextRange selection; +}; + +struct IInputMethodContext : virtual IPlatformResource { + // Return true if you should draw composition text manually. Return false if + // system will take care of that for you. + virtual bool ShouldManuallyDrawCompositionText() = 0; + + virtual void EnableIME() = 0; + + virtual void DisableIME() = 0; + + virtual void CompleteComposition() = 0; + + virtual void CancelComposition() = 0; + + virtual CompositionText GetCompositionText() = 0; + + // Set the candidate window lefttop. Relative to window lefttop. Use this + // method to prepare typing. + virtual void SetCandidateWindowPosition(const Point& point) = 0; + + // Triggered when user starts composition. + virtual IEvent* CompositionStartEvent() = 0; + + // Triggered when user stops composition. + virtual IEvent* CompositionEndEvent() = 0; + + // Triggered every time composition text changes. + virtual IEvent* CompositionEvent() = 0; + + virtual IEvent* TextEvent() = 0; +}; +} // namespace cru::platform::gui + diff --git a/include/cru/platform/gui/InputMethod.hpp b/include/cru/platform/gui/InputMethod.hpp deleted file mode 100644 index a34aba74..00000000 --- a/include/cru/platform/gui/InputMethod.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Event.hpp" - -#include -#include - -namespace cru::platform::gui { -struct CompositionClause { - int start; - int end; - bool target; -}; - -using CompositionClauses = std::vector; - -struct CompositionText { - String text; - CompositionClauses clauses; - TextRange selection; -}; - -struct IInputMethodContext : virtual IPlatformResource { - // Return true if you should draw composition text manually. Return false if - // system will take care of that for you. - virtual bool ShouldManuallyDrawCompositionText() = 0; - - virtual void EnableIME() = 0; - - virtual void DisableIME() = 0; - - virtual void CompleteComposition() = 0; - - virtual void CancelComposition() = 0; - - virtual CompositionText GetCompositionText() = 0; - - // Set the candidate window lefttop. Relative to window lefttop. Use this - // method to prepare typing. - virtual void SetCandidateWindowPosition(const Point& point) = 0; - - // Triggered when user starts composition. - virtual IEvent* CompositionStartEvent() = 0; - - // Triggered when user stops composition. - virtual IEvent* CompositionEndEvent() = 0; - - // Triggered every time composition text changes. - virtual IEvent* CompositionEvent() = 0; - - virtual IEvent* TextEvent() = 0; -}; -} // namespace cru::platform::gui - diff --git a/include/cru/platform/gui/Keyboard.h b/include/cru/platform/gui/Keyboard.h new file mode 100644 index 00000000..f25b25fa --- /dev/null +++ b/include/cru/platform/gui/Keyboard.h @@ -0,0 +1,140 @@ +#pragma once +#include "cru/common/Bitmask.h" +#include "cru/platform/gui/Base.h" + +#include +#include + +namespace cru::platform::gui { +// Because of the complexity of keyboard layout, I only add code in US keyboard +// layout, the most widely used layout in China. We should try to make it easy +// to add new keyboard layout. +enum class KeyCode { + Unknown, + LeftButton, + MiddleButton, + RightButton, + Escape, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + N0, + N1, + N2, + N3, + N4, + N5, + N6, + N7, + N8, + N9, + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + GraveAccent, + Tab, + CapsLock, + LeftShift, + LeftCtrl, + LeftSuper, + LeftAlt, + Minus, + Equal, + Backspace, + LeftSquareBracket, + RightSquareBracket, + BackSlash, + Semicolon, + Quote, + Comma, + Period, + Slash, + RightShift, + RightCtrl, + RightSuper, + RightAlt, + Insert, + Delete, + Home, + End, + PageUp, + PageDown, + Up, + Left, + Down, + Right, + PrintScreen, + ScrollLock, + Pause, + NumPad0, + NumPad1, + NumPad2, + NumPad3, + NumPad4, + NumPad5, + NumPad6, + NumPad7, + NumPad8, + NumPad9, + LeftCommand, + RightCommand, + Return, + Space +}; + +namespace details { +struct TagKeyModifier {}; +} // namespace details + +using KeyModifier = Bitmask; + +struct KeyModifiers { + static constexpr KeyModifier none{0}; + static constexpr KeyModifier shift{0b1}; + static constexpr KeyModifier ctrl{0b10}; + static constexpr KeyModifier alt{0b100}; + static constexpr KeyModifier command{0b1000}; +}; + +#ifdef CRU_PLATFORM_OSX +constexpr KeyModifier kKeyModifierCommand = KeyModifiers::command; +#else +constexpr KeyModifier kKeyModifierCommand = KeyModifiers::ctrl; +#endif + +CRU_PLATFORM_GUI_API String ToString(KeyCode key_code); +CRU_PLATFORM_GUI_API String ToString(KeyModifier key_modifier, + StringView separator = u"+"); +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Keyboard.hpp b/include/cru/platform/gui/Keyboard.hpp deleted file mode 100644 index 347b57bc..00000000 --- a/include/cru/platform/gui/Keyboard.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once -#include "cru/common/Bitmask.hpp" -#include "cru/platform/gui/Base.hpp" - -#include -#include - -namespace cru::platform::gui { -// Because of the complexity of keyboard layout, I only add code in US keyboard -// layout, the most widely used layout in China. We should try to make it easy -// to add new keyboard layout. -enum class KeyCode { - Unknown, - LeftButton, - MiddleButton, - RightButton, - Escape, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - N0, - N1, - N2, - N3, - N4, - N5, - N6, - N7, - N8, - N9, - A, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, - GraveAccent, - Tab, - CapsLock, - LeftShift, - LeftCtrl, - LeftSuper, - LeftAlt, - Minus, - Equal, - Backspace, - LeftSquareBracket, - RightSquareBracket, - BackSlash, - Semicolon, - Quote, - Comma, - Period, - Slash, - RightShift, - RightCtrl, - RightSuper, - RightAlt, - Insert, - Delete, - Home, - End, - PageUp, - PageDown, - Up, - Left, - Down, - Right, - PrintScreen, - ScrollLock, - Pause, - NumPad0, - NumPad1, - NumPad2, - NumPad3, - NumPad4, - NumPad5, - NumPad6, - NumPad7, - NumPad8, - NumPad9, - LeftCommand, - RightCommand, - Return, - Space -}; - -namespace details { -struct TagKeyModifier {}; -} // namespace details - -using KeyModifier = Bitmask; - -struct KeyModifiers { - static constexpr KeyModifier none{0}; - static constexpr KeyModifier shift{0b1}; - static constexpr KeyModifier ctrl{0b10}; - static constexpr KeyModifier alt{0b100}; - static constexpr KeyModifier command{0b1000}; -}; - -#ifdef CRU_PLATFORM_OSX -constexpr KeyModifier kKeyModifierCommand = KeyModifiers::command; -#else -constexpr KeyModifier kKeyModifierCommand = KeyModifiers::ctrl; -#endif - -CRU_PLATFORM_GUI_API String ToString(KeyCode key_code); -CRU_PLATFORM_GUI_API String ToString(KeyModifier key_modifier, - StringView separator = u"+"); -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Menu.h b/include/cru/platform/gui/Menu.h new file mode 100644 index 00000000..6e2a8902 --- /dev/null +++ b/include/cru/platform/gui/Menu.h @@ -0,0 +1,32 @@ +#pragma once +#include "Base.h" + +#include "Keyboard.h" + +#include + +namespace cru::platform::gui { +struct IMenu; + +struct CRU_PLATFORM_GUI_API IMenuItem : virtual IPlatformResource { + virtual String GetTitle() = 0; + virtual void SetTitle(String title) = 0; + virtual bool IsEnabled() = 0; + virtual void SetEnabled(bool enabled) = 0; + virtual IMenu* GetParentMenu() = 0; + virtual IMenu* GetSubmenu() = 0; + virtual void SetKeyboardShortcut(KeyCode key, KeyModifier modifiers) = 0; + virtual void DeleteKeyboardShortcut() = 0; + virtual void SetOnClickHandler(std::function handler) = 0; +}; + +struct CRU_PLATFORM_GUI_API IMenu : virtual IPlatformResource { + virtual IMenuItem* GetItemAt(int index) = 0; + virtual int GetItemCount() = 0; + virtual IMenuItem* CreateItemAt(int index) = 0; + virtual void RemoveItemAt(int index) = 0; + + virtual std::vector GetItems(); + bool Empty() { return GetItemCount() == 0; } +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Menu.hpp b/include/cru/platform/gui/Menu.hpp deleted file mode 100644 index fc2e844f..00000000 --- a/include/cru/platform/gui/Menu.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "Keyboard.hpp" - -#include - -namespace cru::platform::gui { -struct IMenu; - -struct CRU_PLATFORM_GUI_API IMenuItem : virtual IPlatformResource { - virtual String GetTitle() = 0; - virtual void SetTitle(String title) = 0; - virtual bool IsEnabled() = 0; - virtual void SetEnabled(bool enabled) = 0; - virtual IMenu* GetParentMenu() = 0; - virtual IMenu* GetSubmenu() = 0; - virtual void SetKeyboardShortcut(KeyCode key, KeyModifier modifiers) = 0; - virtual void DeleteKeyboardShortcut() = 0; - virtual void SetOnClickHandler(std::function handler) = 0; -}; - -struct CRU_PLATFORM_GUI_API IMenu : virtual IPlatformResource { - virtual IMenuItem* GetItemAt(int index) = 0; - virtual int GetItemCount() = 0; - virtual IMenuItem* CreateItemAt(int index) = 0; - virtual void RemoveItemAt(int index) = 0; - - virtual std::vector GetItems(); - bool Empty() { return GetItemCount() == 0; } -}; -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/SaveOpenDialogOptions.h b/include/cru/platform/gui/SaveOpenDialogOptions.h new file mode 100644 index 00000000..cff4a44f --- /dev/null +++ b/include/cru/platform/gui/SaveOpenDialogOptions.h @@ -0,0 +1,81 @@ +#pragma once +#include "Base.h" + +namespace cru::platform::gui { +struct CRU_PLATFORM_GUI_API SaveDialogOptions { + String title; + String prompt; + String message; + std::vector allowed_file_types; + bool allow_all_file_types = false; +}; + +struct CRU_PLATFORM_GUI_API OpenDialogOptions : SaveDialogOptions { + bool can_choose_files = true; + bool can_choose_directories = false; + bool allow_mulitple_selection = false; +}; + +template +struct CRU_PLATFORM_GUI_API SaveDialogOptionsBuilderTemplate { + T options; + + SaveDialogOptionsBuilderTemplate& SetTitle(String title) { + options.title = std::move(title); + return *this; + } + + SaveDialogOptionsBuilderTemplate& SetPrompt(String prompt) { + options.prompt = std::move(prompt); + return *this; + } + + SaveDialogOptionsBuilderTemplate& SetMessage(String message) { + options.message = std::move(message); + return *this; + } + + SaveDialogOptionsBuilderTemplate& SetAllowedFileTypes( + std::vector allowed_file_types) { + options.allowed_file_types = std::move(allowed_file_types); + return *this; + } + + SaveDialogOptionsBuilderTemplate& AddAllowedFileType( + String allowed_file_type) { + options.allowed_file_types.push_back(allowed_file_type); + return *this; + } + + SaveDialogOptionsBuilderTemplate& SetAllowAllFileTypes( + bool allow_all_file_types) { + options.allow_all_file_types = allow_all_file_types; + return *this; + } + + T Build() { return options; } +}; + +using SaveDialogOptionsBuilder = + SaveDialogOptionsBuilderTemplate; + +struct CRU_PLATFORM_GUI_API OpenDialogOptionsBuilder + : SaveDialogOptionsBuilderTemplate { + OpenDialogOptionsBuilder& SetCanChooseFiles(bool can_choose_files) { + options.can_choose_files = can_choose_files; + return *this; + } + + OpenDialogOptionsBuilder& SetCanChooseDirectories( + bool can_choose_directories) { + options.can_choose_directories = can_choose_directories; + return *this; + } + + OpenDialogOptionsBuilder& SetAllowMultipleSelection( + bool allow_mulitple_selection) { + options.allow_mulitple_selection = allow_mulitple_selection; + return *this; + } +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/SaveOpenDialogOptions.hpp b/include/cru/platform/gui/SaveOpenDialogOptions.hpp deleted file mode 100644 index 907ec808..00000000 --- a/include/cru/platform/gui/SaveOpenDialogOptions.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru::platform::gui { -struct CRU_PLATFORM_GUI_API SaveDialogOptions { - String title; - String prompt; - String message; - std::vector allowed_file_types; - bool allow_all_file_types = false; -}; - -struct CRU_PLATFORM_GUI_API OpenDialogOptions : SaveDialogOptions { - bool can_choose_files = true; - bool can_choose_directories = false; - bool allow_mulitple_selection = false; -}; - -template -struct CRU_PLATFORM_GUI_API SaveDialogOptionsBuilderTemplate { - T options; - - SaveDialogOptionsBuilderTemplate& SetTitle(String title) { - options.title = std::move(title); - return *this; - } - - SaveDialogOptionsBuilderTemplate& SetPrompt(String prompt) { - options.prompt = std::move(prompt); - return *this; - } - - SaveDialogOptionsBuilderTemplate& SetMessage(String message) { - options.message = std::move(message); - return *this; - } - - SaveDialogOptionsBuilderTemplate& SetAllowedFileTypes( - std::vector allowed_file_types) { - options.allowed_file_types = std::move(allowed_file_types); - return *this; - } - - SaveDialogOptionsBuilderTemplate& AddAllowedFileType( - String allowed_file_type) { - options.allowed_file_types.push_back(allowed_file_type); - return *this; - } - - SaveDialogOptionsBuilderTemplate& SetAllowAllFileTypes( - bool allow_all_file_types) { - options.allow_all_file_types = allow_all_file_types; - return *this; - } - - T Build() { return options; } -}; - -using SaveDialogOptionsBuilder = - SaveDialogOptionsBuilderTemplate; - -struct CRU_PLATFORM_GUI_API OpenDialogOptionsBuilder - : SaveDialogOptionsBuilderTemplate { - OpenDialogOptionsBuilder& SetCanChooseFiles(bool can_choose_files) { - options.can_choose_files = can_choose_files; - return *this; - } - - OpenDialogOptionsBuilder& SetCanChooseDirectories( - bool can_choose_directories) { - options.can_choose_directories = can_choose_directories; - return *this; - } - - OpenDialogOptionsBuilder& SetAllowMultipleSelection( - bool allow_mulitple_selection) { - options.allow_mulitple_selection = allow_mulitple_selection; - return *this; - } -}; -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/TimerHelper.h b/include/cru/platform/gui/TimerHelper.h new file mode 100644 index 00000000..91d436a4 --- /dev/null +++ b/include/cru/platform/gui/TimerHelper.h @@ -0,0 +1,69 @@ +#pragma once +#include "UiApplication.h" + +namespace cru::platform::gui { + +class TimerAutoCanceler { + public: + TimerAutoCanceler() : id_(0) {} + explicit TimerAutoCanceler(long long id) : id_(id) {} + + CRU_DELETE_COPY(TimerAutoCanceler) + + TimerAutoCanceler(TimerAutoCanceler&& other) : id_(other.id_) { + other.id_ = 0; + } + + TimerAutoCanceler& operator=(TimerAutoCanceler&& other) { + if (&other == this) { + return *this; + } + Reset(other.id_); + other.id_ = 0; + return *this; + } + + TimerAutoCanceler& operator=(long long other) { + return this->operator=(TimerAutoCanceler(other)); + } + + ~TimerAutoCanceler() { Reset(); } + + long long Release() { + auto temp = id_; + id_ = 0; + return temp; + } + + void Reset(long long id = 0) { + if (id_ > 0) IUiApplication::GetInstance()->CancelTimer(id_); + id_ = id; + } + + explicit operator bool() const { return id_; } + + private: + long long id_; +}; + +class TimerListAutoCanceler { + public: + TimerListAutoCanceler() = default; + CRU_DELETE_COPY(TimerListAutoCanceler) + CRU_DEFAULT_MOVE(TimerListAutoCanceler) + ~TimerListAutoCanceler() = default; + + TimerListAutoCanceler& operator+=(long long id) { + list_.push_back(TimerAutoCanceler(id)); + return *this; + } + + void Clear() { list_.clear(); } + + bool IsEmpty() const { return list_.empty(); } + + private: + std::vector list_; +}; + +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/TimerHelper.hpp b/include/cru/platform/gui/TimerHelper.hpp deleted file mode 100644 index a61d2f04..00000000 --- a/include/cru/platform/gui/TimerHelper.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include "UiApplication.hpp" - -namespace cru::platform::gui { - -class TimerAutoCanceler { - public: - TimerAutoCanceler() : id_(0) {} - explicit TimerAutoCanceler(long long id) : id_(id) {} - - CRU_DELETE_COPY(TimerAutoCanceler) - - TimerAutoCanceler(TimerAutoCanceler&& other) : id_(other.id_) { - other.id_ = 0; - } - - TimerAutoCanceler& operator=(TimerAutoCanceler&& other) { - if (&other == this) { - return *this; - } - Reset(other.id_); - other.id_ = 0; - return *this; - } - - TimerAutoCanceler& operator=(long long other) { - return this->operator=(TimerAutoCanceler(other)); - } - - ~TimerAutoCanceler() { Reset(); } - - long long Release() { - auto temp = id_; - id_ = 0; - return temp; - } - - void Reset(long long id = 0) { - if (id_ > 0) IUiApplication::GetInstance()->CancelTimer(id_); - id_ = id; - } - - explicit operator bool() const { return id_; } - - private: - long long id_; -}; - -class TimerListAutoCanceler { - public: - TimerListAutoCanceler() = default; - CRU_DELETE_COPY(TimerListAutoCanceler) - CRU_DEFAULT_MOVE(TimerListAutoCanceler) - ~TimerListAutoCanceler() = default; - - TimerListAutoCanceler& operator+=(long long id) { - list_.push_back(TimerAutoCanceler(id)); - return *this; - } - - void Clear() { list_.clear(); } - - bool IsEmpty() const { return list_.empty(); } - - private: - std::vector list_; -}; - -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/UiApplication.h b/include/cru/platform/gui/UiApplication.h new file mode 100644 index 00000000..b39e2d36 --- /dev/null +++ b/include/cru/platform/gui/UiApplication.h @@ -0,0 +1,70 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Bitmask.h" +#include "cru/platform/gui/Menu.h" + +#include "SaveOpenDialogOptions.h" + +#include +#include +#include +#include + +namespace cru::platform::gui { +// The entry point of a ui application. +struct CRU_PLATFORM_GUI_API IUiApplication : public virtual IPlatformResource { + public: + static IUiApplication* GetInstance() { return instance; } + + private: + static IUiApplication* instance; + + protected: + IUiApplication(); + + public: + ~IUiApplication() override; + + // Block current thread and run the message loop. Return the exit code when + // message loop gets a quit message (possibly posted by method RequestQuit). + virtual int Run() = 0; + + // Post a quit message with given quit code. + virtual void RequestQuit(int quit_code) = 0; + + virtual void AddOnQuitHandler(std::function handler) = 0; + + virtual bool IsQuitOnAllWindowClosed() = 0; + virtual void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) = 0; + + // Timer id should always be positive (not 0) and never the same. So it's ok + // to use negative value (or 0) to represent no timer. + virtual long long SetImmediate(std::function action) = 0; + virtual long long SetTimeout(std::chrono::milliseconds milliseconds, + std::function action) = 0; + virtual long long SetInterval(std::chrono::milliseconds milliseconds, + std::function action) = 0; + // Implementation should guarantee calls on timer id already canceled have no + // effects and do not crash. Also canceling negative id or 0 should always + // result in no-op. + virtual void CancelTimer(long long id) = 0; + + virtual std::vector GetAllWindow() = 0; + + virtual INativeWindow* CreateWindow() = 0; + + virtual cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() = 0; + + virtual ICursorManager* GetCursorManager() = 0; + + virtual IClipboard* GetClipboard() = 0; + + // If return nullptr, it means the menu is not supported. + virtual IMenu* GetApplicationMenu(); + + virtual std::optional ShowSaveDialog(SaveDialogOptions options); + virtual std::optional> ShowOpenDialog( + OpenDialogOptions options); +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/UiApplication.hpp b/include/cru/platform/gui/UiApplication.hpp deleted file mode 100644 index c917aa01..00000000 --- a/include/cru/platform/gui/UiApplication.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Bitmask.hpp" -#include "cru/platform/gui/Menu.hpp" - -#include "SaveOpenDialogOptions.hpp" - -#include -#include -#include -#include - -namespace cru::platform::gui { -// The entry point of a ui application. -struct CRU_PLATFORM_GUI_API IUiApplication : public virtual IPlatformResource { - public: - static IUiApplication* GetInstance() { return instance; } - - private: - static IUiApplication* instance; - - protected: - IUiApplication(); - - public: - ~IUiApplication() override; - - // Block current thread and run the message loop. Return the exit code when - // message loop gets a quit message (possibly posted by method RequestQuit). - virtual int Run() = 0; - - // Post a quit message with given quit code. - virtual void RequestQuit(int quit_code) = 0; - - virtual void AddOnQuitHandler(std::function handler) = 0; - - virtual bool IsQuitOnAllWindowClosed() = 0; - virtual void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) = 0; - - // Timer id should always be positive (not 0) and never the same. So it's ok - // to use negative value (or 0) to represent no timer. - virtual long long SetImmediate(std::function action) = 0; - virtual long long SetTimeout(std::chrono::milliseconds milliseconds, - std::function action) = 0; - virtual long long SetInterval(std::chrono::milliseconds milliseconds, - std::function action) = 0; - // Implementation should guarantee calls on timer id already canceled have no - // effects and do not crash. Also canceling negative id or 0 should always - // result in no-op. - virtual void CancelTimer(long long id) = 0; - - virtual std::vector GetAllWindow() = 0; - - virtual INativeWindow* CreateWindow() = 0; - - virtual cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() = 0; - - virtual ICursorManager* GetCursorManager() = 0; - - virtual IClipboard* GetClipboard() = 0; - - // If return nullptr, it means the menu is not supported. - virtual IMenu* GetApplicationMenu(); - - virtual std::optional ShowSaveDialog(SaveDialogOptions options); - virtual std::optional> ShowOpenDialog( - OpenDialogOptions options); -}; -} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Window.h b/include/cru/platform/gui/Window.h new file mode 100644 index 00000000..d3f0daad --- /dev/null +++ b/include/cru/platform/gui/Window.h @@ -0,0 +1,112 @@ +#pragma once +#include "Base.h" + +#include "Keyboard.h" + +#include "cru/common/Event.h" + +#include + +namespace cru::platform::gui { +namespace details { +struct WindowStyleFlagTag; +} + +using WindowStyleFlag = Bitmask; + +struct WindowStyleFlags { + static constexpr WindowStyleFlag NoCaptionAndBorder{0b1}; +}; + +enum class WindowVisibilityType { Show, Hide, Minimize }; + +enum class FocusChangeType { Gain, Lose }; + +enum class MouseEnterLeaveType { Enter, Leave }; + +struct NativeMouseButtonEventArgs { + MouseButton button; + Point point; + KeyModifier modifier; +}; + +struct NativeMouseWheelEventArgs { + // Positive means down. Negative means up. + float delta; + Point point; + KeyModifier modifier; + bool horizontal; // true if horizontal wheel. +}; + +struct NativeKeyEventArgs { + KeyCode key; + KeyModifier modifier; +}; + +// Represents a native window, which exposes some low-level events and +// operations. +struct INativeWindow : virtual IPlatformResource { + virtual void Close() = 0; + + virtual INativeWindow* GetParent() = 0; + virtual void SetParent(INativeWindow* parent) = 0; + + virtual WindowStyleFlag GetStyleFlag() = 0; + virtual void SetStyleFlag(WindowStyleFlag flag) = 0; + + virtual String GetTitle() = 0; + virtual void SetTitle(String title) = 0; + + virtual WindowVisibilityType GetVisibility() = 0; + virtual void SetVisibility(WindowVisibilityType visibility) = 0; + + virtual Size GetClientSize() = 0; + virtual void SetClientSize(const Size& size) = 0; + + virtual Rect GetClientRect() = 0; + virtual void SetClientRect(const Rect& rect) = 0; + + // Get the rect of the window containing frame. + // The lefttop of the rect is relative to screen lefttop. + virtual Rect GetWindowRect() = 0; + + // Set the rect of the window containing frame. + // The lefttop of the rect is relative to screen lefttop. + virtual void SetWindowRect(const Rect& rect) = 0; + + virtual bool RequestFocus() = 0; + + // Relative to client lefttop. + virtual Point GetMousePosition() = 0; + + virtual bool CaptureMouse() = 0; + virtual bool ReleaseMouse() = 0; + + virtual void SetCursor(std::shared_ptr cursor) = 0; + + virtual void SetToForeground() = 0; + + virtual void RequestRepaint() = 0; + + // Remember to call EndDraw on return value and destroy it. + virtual std::unique_ptr BeginPaint() = 0; + + virtual IEvent* CreateEvent() = 0; + virtual IEvent* DestroyEvent() = 0; + virtual IEvent* PaintEvent() = 0; + + virtual IEvent* VisibilityChangeEvent() = 0; + virtual IEvent* ResizeEvent() = 0; + virtual IEvent* FocusEvent() = 0; + + virtual IEvent* MouseEnterLeaveEvent() = 0; + virtual IEvent* MouseMoveEvent() = 0; + virtual IEvent* MouseDownEvent() = 0; + virtual IEvent* MouseUpEvent() = 0; + virtual IEvent* MouseWheelEvent() = 0; + virtual IEvent* KeyDownEvent() = 0; + virtual IEvent* KeyUpEvent() = 0; + + virtual IInputMethodContext* GetInputMethodContext() = 0; +}; +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Window.hpp b/include/cru/platform/gui/Window.hpp deleted file mode 100644 index a8fe3ca6..00000000 --- a/include/cru/platform/gui/Window.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "Keyboard.hpp" - -#include "cru/common/Event.hpp" - -#include - -namespace cru::platform::gui { -namespace details { -struct WindowStyleFlagTag; -} - -using WindowStyleFlag = Bitmask; - -struct WindowStyleFlags { - static constexpr WindowStyleFlag NoCaptionAndBorder{0b1}; -}; - -enum class WindowVisibilityType { Show, Hide, Minimize }; - -enum class FocusChangeType { Gain, Lose }; - -enum class MouseEnterLeaveType { Enter, Leave }; - -struct NativeMouseButtonEventArgs { - MouseButton button; - Point point; - KeyModifier modifier; -}; - -struct NativeMouseWheelEventArgs { - // Positive means down. Negative means up. - float delta; - Point point; - KeyModifier modifier; - bool horizontal; // true if horizontal wheel. -}; - -struct NativeKeyEventArgs { - KeyCode key; - KeyModifier modifier; -}; - -// Represents a native window, which exposes some low-level events and -// operations. -struct INativeWindow : virtual IPlatformResource { - virtual void Close() = 0; - - virtual INativeWindow* GetParent() = 0; - virtual void SetParent(INativeWindow* parent) = 0; - - virtual WindowStyleFlag GetStyleFlag() = 0; - virtual void SetStyleFlag(WindowStyleFlag flag) = 0; - - virtual String GetTitle() = 0; - virtual void SetTitle(String title) = 0; - - virtual WindowVisibilityType GetVisibility() = 0; - virtual void SetVisibility(WindowVisibilityType visibility) = 0; - - virtual Size GetClientSize() = 0; - virtual void SetClientSize(const Size& size) = 0; - - virtual Rect GetClientRect() = 0; - virtual void SetClientRect(const Rect& rect) = 0; - - // Get the rect of the window containing frame. - // The lefttop of the rect is relative to screen lefttop. - virtual Rect GetWindowRect() = 0; - - // Set the rect of the window containing frame. - // The lefttop of the rect is relative to screen lefttop. - virtual void SetWindowRect(const Rect& rect) = 0; - - virtual bool RequestFocus() = 0; - - // Relative to client lefttop. - virtual Point GetMousePosition() = 0; - - virtual bool CaptureMouse() = 0; - virtual bool ReleaseMouse() = 0; - - virtual void SetCursor(std::shared_ptr cursor) = 0; - - virtual void SetToForeground() = 0; - - virtual void RequestRepaint() = 0; - - // Remember to call EndDraw on return value and destroy it. - virtual std::unique_ptr BeginPaint() = 0; - - virtual IEvent* CreateEvent() = 0; - virtual IEvent* DestroyEvent() = 0; - virtual IEvent* PaintEvent() = 0; - - virtual IEvent* VisibilityChangeEvent() = 0; - virtual IEvent* ResizeEvent() = 0; - virtual IEvent* FocusEvent() = 0; - - virtual IEvent* MouseEnterLeaveEvent() = 0; - virtual IEvent* MouseMoveEvent() = 0; - virtual IEvent* MouseDownEvent() = 0; - virtual IEvent* MouseUpEvent() = 0; - virtual IEvent* MouseWheelEvent() = 0; - virtual IEvent* KeyDownEvent() = 0; - virtual IEvent* KeyUpEvent() = 0; - - virtual IInputMethodContext* GetInputMethodContext() = 0; -}; -} // namespace cru::platform::gui diff --git a/include/cru/toml/Base.h b/include/cru/toml/Base.h new file mode 100644 index 00000000..de1d558c --- /dev/null +++ b/include/cru/toml/Base.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_TOML_EXPORT_API +#define CRU_TOML_API __declspec(dllexport) +#else +#define CRU_TOML_API __declspec(dllimport) +#endif +#else +#define CRU_TOML_API +#endif diff --git a/include/cru/toml/Base.hpp b/include/cru/toml/Base.hpp deleted file mode 100644 index de1d558c..00000000 --- a/include/cru/toml/Base.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_TOML_EXPORT_API -#define CRU_TOML_API __declspec(dllexport) -#else -#define CRU_TOML_API __declspec(dllimport) -#endif -#else -#define CRU_TOML_API -#endif diff --git a/include/cru/toml/TomlDocument.h b/include/cru/toml/TomlDocument.h new file mode 100644 index 00000000..6da5ad74 --- /dev/null +++ b/include/cru/toml/TomlDocument.h @@ -0,0 +1,57 @@ +#pragma once + +#include "Base.h" + +#include "cru/common/Base.h" +#include "cru/common/String.h" + +#include +#include + +namespace cru::toml { +class CRU_TOML_API TomlSection { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(TomlSection) + CRU_DEFAULT_COPY(TomlSection) + CRU_DEFAULT_MOVE(TomlSection) + + public: + std::optional GetValue(const String& key) const; + void SetValue(const String& key, String value); + void DeleteValue(const String& key); + + auto begin() { return values_.begin(); } + auto end() { return values_.end(); } + auto begin() const { return values_.begin(); } + auto end() const { return values_.end(); } + auto cbegin() const { return values_.cbegin(); } + auto cend() const { return values_.cend(); } + + private: + std::unordered_map values_; +}; + +class CRU_TOML_API TomlDocument { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(TomlDocument) + CRU_DEFAULT_COPY(TomlDocument) + CRU_DEFAULT_MOVE(TomlDocument) + + public: + TomlSection* GetSection(const String& name); + TomlSection* GetSectionOrCreate(const String& name); + const TomlSection* GetSection(const String& name) const; + void SetSection(const String& name, TomlSection section); + void DeleteSection(const String& name); + + auto begin() { return sections_.begin(); } + auto end() { return sections_.end(); } + auto begin() const { return sections_.begin(); } + auto end() const { return sections_.end(); } + auto cbegin() const { return sections_.cbegin(); } + auto cend() const { return sections_.cend(); } + + private: + std::unordered_map sections_; +}; +} // namespace cru::toml diff --git a/include/cru/toml/TomlDocument.hpp b/include/cru/toml/TomlDocument.hpp deleted file mode 100644 index 1e5caf71..00000000 --- a/include/cru/toml/TomlDocument.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "Base.hpp" - -#include "cru/common/Base.hpp" -#include "cru/common/String.hpp" - -#include -#include - -namespace cru::toml { -class CRU_TOML_API TomlSection { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(TomlSection) - CRU_DEFAULT_COPY(TomlSection) - CRU_DEFAULT_MOVE(TomlSection) - - public: - std::optional GetValue(const String& key) const; - void SetValue(const String& key, String value); - void DeleteValue(const String& key); - - auto begin() { return values_.begin(); } - auto end() { return values_.end(); } - auto begin() const { return values_.begin(); } - auto end() const { return values_.end(); } - auto cbegin() const { return values_.cbegin(); } - auto cend() const { return values_.cend(); } - - private: - std::unordered_map values_; -}; - -class CRU_TOML_API TomlDocument { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(TomlDocument) - CRU_DEFAULT_COPY(TomlDocument) - CRU_DEFAULT_MOVE(TomlDocument) - - public: - TomlSection* GetSection(const String& name); - TomlSection* GetSectionOrCreate(const String& name); - const TomlSection* GetSection(const String& name) const; - void SetSection(const String& name, TomlSection section); - void DeleteSection(const String& name); - - auto begin() { return sections_.begin(); } - auto end() { return sections_.end(); } - auto begin() const { return sections_.begin(); } - auto end() const { return sections_.end(); } - auto cbegin() const { return sections_.cbegin(); } - auto cend() const { return sections_.cend(); } - - private: - std::unordered_map sections_; -}; -} // namespace cru::toml diff --git a/include/cru/toml/TomlParser.h b/include/cru/toml/TomlParser.h new file mode 100644 index 00000000..dcef2920 --- /dev/null +++ b/include/cru/toml/TomlParser.h @@ -0,0 +1,36 @@ +#pragma once + +#include "cru/common/Exception.h" +#include "cru/toml/TomlDocument.h" + +#include + +namespace cru::toml { +// A very simple and tolerant TOML parser. +class CRU_TOML_API TomlParsingException : public Exception { + public: + using Exception::Exception; +}; + +class CRU_TOML_API TomlParser { + public: + explicit TomlParser(String input); + + CRU_DELETE_COPY(TomlParser) + CRU_DELETE_MOVE(TomlParser) + + ~TomlParser(); + + public: + TomlDocument Parse(); + + private: + // The document is empty to begin with. + void DoParse(TomlDocument& document); + + private: + String input_; + + std::optional cache_; +}; +} // namespace cru::toml diff --git a/include/cru/toml/TomlParser.hpp b/include/cru/toml/TomlParser.hpp deleted file mode 100644 index c3091bad..00000000 --- a/include/cru/toml/TomlParser.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "cru/common/Exception.hpp" -#include "cru/toml/TomlDocument.hpp" - -#include - -namespace cru::toml { -// A very simple and tolerant TOML parser. -class CRU_TOML_API TomlParsingException : public Exception { - public: - using Exception::Exception; -}; - -class CRU_TOML_API TomlParser { - public: - explicit TomlParser(String input); - - CRU_DELETE_COPY(TomlParser) - CRU_DELETE_MOVE(TomlParser) - - ~TomlParser(); - - public: - TomlDocument Parse(); - - private: - // The document is empty to begin with. - void DoParse(TomlDocument& document); - - private: - String input_; - - std::optional cache_; -}; -} // namespace cru::toml diff --git a/include/cru/ui/Base.h b/include/cru/ui/Base.h new file mode 100644 index 00000000..44f76907 --- /dev/null +++ b/include/cru/ui/Base.h @@ -0,0 +1,152 @@ +#pragma once +#include "cru/common/Base.h" +#include "cru/platform/graphics/Base.h" +#include "cru/platform/gui/Base.h" + +#include +#include +#include +#include + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_UI_EXPORT_API +#define CRU_UI_API __declspec(dllexport) +#else +#define CRU_UI_API __declspec(dllimport) +#endif +#else +#define CRU_UI_API +#endif + +namespace cru::ui { +//-------------------- region: import -------------------- +using cru::platform::Color; +using cru::platform::Ellipse; +using cru::platform::Matrix; +using cru::platform::Point; +using cru::platform::Rect; +using cru::platform::RoundedRect; +using cru::platform::Size; +using cru::platform::TextRange; +using cru::platform::Thickness; +using cru::platform::gui::MouseButton; + +namespace mouse_buttons = cru::platform::gui::mouse_buttons; + +namespace colors = cru::platform::colors; + +//-------------------- region: forward declaration -------------------- + +namespace controls { +class Window; +class Control; +} // namespace controls + +namespace host { +class WindowHost; +} + +namespace render { +class RenderObject; +} + +namespace style { +class StyleRuleSet; +class StyleRuleSetBind; +} // namespace style + +//-------------------- region: basic types -------------------- +enum class Direction { Horizontal, Vertical }; + +namespace internal { +constexpr int align_start = 0; +constexpr int align_end = align_start + 1; +constexpr int align_center = align_end + 1; +constexpr int align_stretch = align_center + 1; +} // namespace internal + +enum class Alignment { + Start = internal::align_start, + End = internal::align_end, + Center = internal::align_center, + Stretch = internal::align_stretch +}; + +struct CornerRadius { + constexpr CornerRadius() + : left_top(), right_top(), left_bottom(), right_bottom() {} + constexpr CornerRadius(const float& value) + : CornerRadius(Point{value, value}) {} + constexpr CornerRadius(const Point& value) + : left_top(value), + right_top(value), + left_bottom(value), + right_bottom(value) {} + constexpr CornerRadius(Point left_top, Point right_top, Point left_bottom, + Point right_bottom) + : left_top(left_top), + right_top(right_top), + left_bottom(left_bottom), + right_bottom(right_bottom) {} + + CornerRadius& SetAll(const Point& point) { + left_top = right_top = left_bottom = right_bottom = point; + return *this; + } + + Point left_top; + Point right_top; + Point left_bottom; + Point right_bottom; +}; + +inline bool operator==(const CornerRadius& left, const CornerRadius& right) { + return left.left_top == right.left_top && + left.left_bottom == right.left_bottom && + left.right_top == right.right_top && + left.right_bottom == right.right_bottom; +} + +inline bool operator!=(const CornerRadius& left, const CornerRadius& right) { + return !(left == right); +} + +class CanvasPaintEventArgs { + public: + CanvasPaintEventArgs(platform::graphics::IPainter* painter, + const Size& paint_size) + : painter_(painter), paint_size_(paint_size) {} + CRU_DEFAULT_COPY(CanvasPaintEventArgs) + CRU_DEFAULT_MOVE(CanvasPaintEventArgs) + ~CanvasPaintEventArgs() = default; + + platform::graphics::IPainter* GetPainter() const { return painter_; } + Size GetPaintSize() const { return paint_size_; } + + private: + platform::graphics::IPainter* painter_; + Size paint_size_; +}; + +enum class FlexDirection { + Horizontal, + HorizontalReverse, + Vertical, + VertivalReverse +}; + +using FlexMainAlignment = Alignment; +using FlexCrossAlignment = Alignment; + +struct FlexChildLayoutData { + float expand_factor = 0; + float shrink_factor = 1; + // nullopt stands for looking at parent's setting + std::optional cross_alignment = std::nullopt; +}; + +struct StackChildLayoutData { + std::optional horizontal; + std::optional vertical; +}; +} // namespace cru::ui diff --git a/include/cru/ui/Base.hpp b/include/cru/ui/Base.hpp deleted file mode 100644 index e99c956f..00000000 --- a/include/cru/ui/Base.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/Base.hpp" -#include "cru/platform/gui/Base.hpp" - -#include -#include -#include -#include - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_UI_EXPORT_API -#define CRU_UI_API __declspec(dllexport) -#else -#define CRU_UI_API __declspec(dllimport) -#endif -#else -#define CRU_UI_API -#endif - -namespace cru::ui { -//-------------------- region: import -------------------- -using cru::platform::Color; -using cru::platform::Ellipse; -using cru::platform::Matrix; -using cru::platform::Point; -using cru::platform::Rect; -using cru::platform::RoundedRect; -using cru::platform::Size; -using cru::platform::TextRange; -using cru::platform::Thickness; -using cru::platform::gui::MouseButton; - -namespace mouse_buttons = cru::platform::gui::mouse_buttons; - -namespace colors = cru::platform::colors; - -//-------------------- region: forward declaration -------------------- - -namespace controls { -class Window; -class Control; -} // namespace controls - -namespace host { -class WindowHost; -} - -namespace render { -class RenderObject; -} - -namespace style { -class StyleRuleSet; -class StyleRuleSetBind; -} // namespace style - -//-------------------- region: basic types -------------------- -enum class Direction { Horizontal, Vertical }; - -namespace internal { -constexpr int align_start = 0; -constexpr int align_end = align_start + 1; -constexpr int align_center = align_end + 1; -constexpr int align_stretch = align_center + 1; -} // namespace internal - -enum class Alignment { - Start = internal::align_start, - End = internal::align_end, - Center = internal::align_center, - Stretch = internal::align_stretch -}; - -struct CornerRadius { - constexpr CornerRadius() - : left_top(), right_top(), left_bottom(), right_bottom() {} - constexpr CornerRadius(const float& value) - : CornerRadius(Point{value, value}) {} - constexpr CornerRadius(const Point& value) - : left_top(value), - right_top(value), - left_bottom(value), - right_bottom(value) {} - constexpr CornerRadius(Point left_top, Point right_top, Point left_bottom, - Point right_bottom) - : left_top(left_top), - right_top(right_top), - left_bottom(left_bottom), - right_bottom(right_bottom) {} - - CornerRadius& SetAll(const Point& point) { - left_top = right_top = left_bottom = right_bottom = point; - return *this; - } - - Point left_top; - Point right_top; - Point left_bottom; - Point right_bottom; -}; - -inline bool operator==(const CornerRadius& left, const CornerRadius& right) { - return left.left_top == right.left_top && - left.left_bottom == right.left_bottom && - left.right_top == right.right_top && - left.right_bottom == right.right_bottom; -} - -inline bool operator!=(const CornerRadius& left, const CornerRadius& right) { - return !(left == right); -} - -class CanvasPaintEventArgs { - public: - CanvasPaintEventArgs(platform::graphics::IPainter* painter, - const Size& paint_size) - : painter_(painter), paint_size_(paint_size) {} - CRU_DEFAULT_COPY(CanvasPaintEventArgs) - CRU_DEFAULT_MOVE(CanvasPaintEventArgs) - ~CanvasPaintEventArgs() = default; - - platform::graphics::IPainter* GetPainter() const { return painter_; } - Size GetPaintSize() const { return paint_size_; } - - private: - platform::graphics::IPainter* painter_; - Size paint_size_; -}; - -enum class FlexDirection { - Horizontal, - HorizontalReverse, - Vertical, - VertivalReverse -}; - -using FlexMainAlignment = Alignment; -using FlexCrossAlignment = Alignment; - -struct FlexChildLayoutData { - float expand_factor = 0; - float shrink_factor = 1; - // nullopt stands for looking at parent's setting - std::optional cross_alignment = std::nullopt; -}; - -struct StackChildLayoutData { - std::optional horizontal; - std::optional vertical; -}; -} // namespace cru::ui diff --git a/include/cru/ui/DebugFlags.h b/include/cru/ui/DebugFlags.h new file mode 100644 index 00000000..71d2c03e --- /dev/null +++ b/include/cru/ui/DebugFlags.h @@ -0,0 +1,10 @@ +#pragma once + +namespace cru::ui::debug_flags { +constexpr bool routed_event = false; +constexpr bool layout = false; +constexpr bool shortcut = false; +constexpr bool text_service = false; +constexpr int click_detector = 0; +constexpr int draw = 0; +} // namespace cru::ui::debug_flags diff --git a/include/cru/ui/DebugFlags.hpp b/include/cru/ui/DebugFlags.hpp deleted file mode 100644 index 71d2c03e..00000000 --- a/include/cru/ui/DebugFlags.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace cru::ui::debug_flags { -constexpr bool routed_event = false; -constexpr bool layout = false; -constexpr bool shortcut = false; -constexpr bool text_service = false; -constexpr int click_detector = 0; -constexpr int draw = 0; -} // namespace cru::ui::debug_flags diff --git a/include/cru/ui/ThemeManager.h b/include/cru/ui/ThemeManager.h new file mode 100644 index 00000000..9176d85e --- /dev/null +++ b/include/cru/ui/ThemeManager.h @@ -0,0 +1,92 @@ +#pragma once +#include "Base.h" +#include "cru/common/Base.h" +#include "cru/common/Event.h" +#include "cru/common/Exception.h" +#include "cru/platform/graphics/Brush.h" +#include "cru/ui/mapper/MapperRegistry.h" +#include "cru/ui/style/StyleRuleSet.h" +#include "cru/xml/XmlNode.h" + +#include +#include +#include +#include + +namespace cru::ui { +class CRU_UI_API ThemeResourceKeyNotExistException : public Exception { + public: + using Exception::Exception; +}; + +class CRU_UI_API BadThemeResourceException : public Exception { + public: + using Exception::Exception; +}; + +class CRU_UI_API ThemeManager : public Object { + public: + static ThemeManager* GetInstance(); + + private: + ThemeManager(); + + public: + CRU_DELETE_COPY(ThemeManager) + CRU_DELETE_MOVE(ThemeManager) + + ~ThemeManager() override; + + IEvent* ThemeResourceChangeEvent() { + return &theme_resource_change_event_; + } + + void ReadResourcesFile(const String& file_path); + + void SetThemeXml(xml::XmlElementNode* root); + + template + T GetResource(const String& key) { + auto find_result = theme_resource_map_.find(key); + if (find_result == theme_resource_map_.cend()) { + throw ThemeResourceKeyNotExistException( + Format(u"Theme resource key \"%s\" not exist.", key)); + } + + auto& cache = find_result->second.cache; + auto cache_find_result = cache.find(typeid(T)); + if (cache_find_result != cache.cend()) { + return std::any_cast(cache_find_result->second); + } + + auto mapper_registry = mapper::MapperRegistry::GetInstance(); + auto mapper = mapper_registry->GetMapper(); + auto resource = mapper->MapFromXml(find_result->second.xml_node); + cache[typeid(T)] = resource; + return resource; + } + + std::shared_ptr GetResourceBrush( + const String& key); + + std::shared_ptr GetResourceFont(const String& key); + + std::shared_ptr GetResourceStyleRuleSet( + const String& key); + + private: + struct ResourceEntry { + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ResourceEntry) + CRU_DEFAULT_COPY(ResourceEntry) + CRU_DEFAULT_MOVE(ResourceEntry) + + String name; + xml::XmlElementNode* xml_node; + std::unordered_map cache; + }; + + Event theme_resource_change_event_; + std::unique_ptr theme_resource_xml_root_; + std::unordered_map theme_resource_map_; +}; +} // namespace cru::ui diff --git a/include/cru/ui/ThemeManager.hpp b/include/cru/ui/ThemeManager.hpp deleted file mode 100644 index 68c2b121..00000000 --- a/include/cru/ui/ThemeManager.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include "Base.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/Event.hpp" -#include "cru/common/Exception.hpp" -#include "cru/platform/graphics/Brush.hpp" -#include "cru/ui/mapper/MapperRegistry.hpp" -#include "cru/ui/style/StyleRuleSet.hpp" -#include "cru/xml/XmlNode.hpp" - -#include -#include -#include -#include - -namespace cru::ui { -class CRU_UI_API ThemeResourceKeyNotExistException : public Exception { - public: - using Exception::Exception; -}; - -class CRU_UI_API BadThemeResourceException : public Exception { - public: - using Exception::Exception; -}; - -class CRU_UI_API ThemeManager : public Object { - public: - static ThemeManager* GetInstance(); - - private: - ThemeManager(); - - public: - CRU_DELETE_COPY(ThemeManager) - CRU_DELETE_MOVE(ThemeManager) - - ~ThemeManager() override; - - IEvent* ThemeResourceChangeEvent() { - return &theme_resource_change_event_; - } - - void ReadResourcesFile(const String& file_path); - - void SetThemeXml(xml::XmlElementNode* root); - - template - T GetResource(const String& key) { - auto find_result = theme_resource_map_.find(key); - if (find_result == theme_resource_map_.cend()) { - throw ThemeResourceKeyNotExistException( - Format(u"Theme resource key \"%s\" not exist.", key)); - } - - auto& cache = find_result->second.cache; - auto cache_find_result = cache.find(typeid(T)); - if (cache_find_result != cache.cend()) { - return std::any_cast(cache_find_result->second); - } - - auto mapper_registry = mapper::MapperRegistry::GetInstance(); - auto mapper = mapper_registry->GetMapper(); - auto resource = mapper->MapFromXml(find_result->second.xml_node); - cache[typeid(T)] = resource; - return resource; - } - - std::shared_ptr GetResourceBrush( - const String& key); - - std::shared_ptr GetResourceFont(const String& key); - - std::shared_ptr GetResourceStyleRuleSet( - const String& key); - - private: - struct ResourceEntry { - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ResourceEntry) - CRU_DEFAULT_COPY(ResourceEntry) - CRU_DEFAULT_MOVE(ResourceEntry) - - String name; - xml::XmlElementNode* xml_node; - std::unordered_map cache; - }; - - Event theme_resource_change_event_; - std::unique_ptr theme_resource_xml_root_; - std::unordered_map theme_resource_map_; -}; -} // namespace cru::ui diff --git a/include/cru/ui/components/Component.h b/include/cru/ui/components/Component.h new file mode 100644 index 00000000..0b871dc4 --- /dev/null +++ b/include/cru/ui/components/Component.h @@ -0,0 +1,19 @@ +#pragma once +#include "../Base.h" + +namespace cru::ui::components { +// In destructor, component should check all owned controls whether it is +// attached to window, if not, destroy them, otherwise it is host's duty to +// destroy them. +class CRU_UI_API Component : public Object { + public: + Component() = default; + + CRU_DELETE_COPY(Component) + CRU_DELETE_MOVE(Component) + + ~Component() = default; + + virtual controls::Control* GetRootControl() = 0; +}; +} // namespace cru::ui::components diff --git a/include/cru/ui/components/Component.hpp b/include/cru/ui/components/Component.hpp deleted file mode 100644 index 4cbc3791..00000000 --- a/include/cru/ui/components/Component.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::components { -// In destructor, component should check all owned controls whether it is -// attached to window, if not, destroy them, otherwise it is host's duty to -// destroy them. -class CRU_UI_API Component : public Object { - public: - Component() = default; - - CRU_DELETE_COPY(Component) - CRU_DELETE_MOVE(Component) - - ~Component() = default; - - virtual controls::Control* GetRootControl() = 0; -}; -} // namespace cru::ui::components diff --git a/include/cru/ui/components/Menu.h b/include/cru/ui/components/Menu.h new file mode 100644 index 00000000..32936f84 --- /dev/null +++ b/include/cru/ui/components/Menu.h @@ -0,0 +1,107 @@ +#pragma once +#include "Component.h" +#include "cru/common/Base.h" +#include "cru/ui/controls/Button.h" +#include "cru/ui/controls/Control.h" +#include "cru/ui/controls/FlexLayout.h" +#include "cru/ui/controls/Popup.h" +#include "cru/ui/controls/TextBlock.h" + +#include +#include + +namespace cru::ui::components { +class CRU_UI_API MenuItem : public Component { + public: + MenuItem(); + explicit MenuItem(String text); + + CRU_DELETE_COPY(MenuItem) + CRU_DELETE_MOVE(MenuItem) + + ~MenuItem(); + + public: + controls::Control* GetRootControl() override { return container_; } + + void SetText(String text); + + void SetOnClick(std::function on_click) { + on_click_ = std::move(on_click); + } + + private: + controls::Button* container_; + controls::TextBlock* text_; + std::function on_click_; +}; + +class CRU_UI_API Menu : public Component { + public: + Menu(); + + CRU_DELETE_COPY(Menu) + CRU_DELETE_MOVE(Menu) + + ~Menu(); + + public: + controls::Control* GetRootControl() override { return container_; } + + gsl::index GetItemCount() const { + return static_cast(items_.size()); + } + + void AddItem(Component* component) { AddItem(component, GetItemCount()); } + void AddItem(Component* component, gsl::index index); + Component* RemoveItem(gsl::index index); + void ClearItems(); + + void AddTextItem(String text, std::function on_click) { + AddTextItem(std::move(text), GetItemCount(), std::move(on_click)); + } + void AddTextItem(String text, Index index, std::function on_click); + + void SetOnItemClick(std::function on_item_click) { + on_item_click_ = std::move(on_item_click); + } + + private: + controls::FlexLayout* container_; + std::vector items_; + + std::function on_item_click_; +}; + +class CRU_UI_API PopupMenu : public Component { + public: + explicit PopupMenu(controls::Control* attached_control = nullptr); + + CRU_DELETE_COPY(PopupMenu) + CRU_DELETE_MOVE(PopupMenu) + + ~PopupMenu(); + + public: + controls::Control* GetRootControl() override; + + controls::Popup* GetPopup() { return popup_; } + Menu* GetMenu() { return menu_; } + + // position relative to screen left top. + void SetPosition(const Point& position); + void Show(); + // position relative to screen left top. + void Show(const Point& position) { + SetPosition(position); + Show(); + } + void Close(); + + private: + controls::Control* attached_control_; + + controls::Popup* popup_; + Menu* menu_; +}; +} // namespace cru::ui::components diff --git a/include/cru/ui/components/Menu.hpp b/include/cru/ui/components/Menu.hpp deleted file mode 100644 index 9b60eb02..00000000 --- a/include/cru/ui/components/Menu.hpp +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once -#include "Component.hpp" -#include "cru/common/Base.hpp" -#include "cru/ui/controls/Button.hpp" -#include "cru/ui/controls/Control.hpp" -#include "cru/ui/controls/FlexLayout.hpp" -#include "cru/ui/controls/Popup.hpp" -#include "cru/ui/controls/TextBlock.hpp" - -#include -#include - -namespace cru::ui::components { -class CRU_UI_API MenuItem : public Component { - public: - MenuItem(); - explicit MenuItem(String text); - - CRU_DELETE_COPY(MenuItem) - CRU_DELETE_MOVE(MenuItem) - - ~MenuItem(); - - public: - controls::Control* GetRootControl() override { return container_; } - - void SetText(String text); - - void SetOnClick(std::function on_click) { - on_click_ = std::move(on_click); - } - - private: - controls::Button* container_; - controls::TextBlock* text_; - std::function on_click_; -}; - -class CRU_UI_API Menu : public Component { - public: - Menu(); - - CRU_DELETE_COPY(Menu) - CRU_DELETE_MOVE(Menu) - - ~Menu(); - - public: - controls::Control* GetRootControl() override { return container_; } - - gsl::index GetItemCount() const { - return static_cast(items_.size()); - } - - void AddItem(Component* component) { AddItem(component, GetItemCount()); } - void AddItem(Component* component, gsl::index index); - Component* RemoveItem(gsl::index index); - void ClearItems(); - - void AddTextItem(String text, std::function on_click) { - AddTextItem(std::move(text), GetItemCount(), std::move(on_click)); - } - void AddTextItem(String text, Index index, std::function on_click); - - void SetOnItemClick(std::function on_item_click) { - on_item_click_ = std::move(on_item_click); - } - - private: - controls::FlexLayout* container_; - std::vector items_; - - std::function on_item_click_; -}; - -class CRU_UI_API PopupMenu : public Component { - public: - explicit PopupMenu(controls::Control* attached_control = nullptr); - - CRU_DELETE_COPY(PopupMenu) - CRU_DELETE_MOVE(PopupMenu) - - ~PopupMenu(); - - public: - controls::Control* GetRootControl() override; - - controls::Popup* GetPopup() { return popup_; } - Menu* GetMenu() { return menu_; } - - // position relative to screen left top. - void SetPosition(const Point& position); - void Show(); - // position relative to screen left top. - void Show(const Point& position) { - SetPosition(position); - Show(); - } - void Close(); - - private: - controls::Control* attached_control_; - - controls::Popup* popup_; - Menu* menu_; -}; -} // namespace cru::ui::components diff --git a/include/cru/ui/controls/Base.h b/include/cru/ui/controls/Base.h new file mode 100644 index 00000000..21f1c563 --- /dev/null +++ b/include/cru/ui/controls/Base.h @@ -0,0 +1,4 @@ +#pragma once +#include "../Base.h" + +namespace cru::ui::controls {} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Base.hpp b/include/cru/ui/controls/Base.hpp deleted file mode 100644 index 7c85cdb2..00000000 --- a/include/cru/ui/controls/Base.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::controls {} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Button.h b/include/cru/ui/controls/Button.h new file mode 100644 index 00000000..ab1ef8eb --- /dev/null +++ b/include/cru/ui/controls/Button.h @@ -0,0 +1,53 @@ +#pragma once +#include "ContentControl.h" + +#include "../helper/ClickDetector.h" +#include "IBorderControl.h" +#include "IClickableControl.h" +#include "cru/common/Event.h" +#include "cru/ui/style/ApplyBorderStyleInfo.h" + +namespace cru::ui::controls { +class CRU_UI_API Button : public ContentControl, + public virtual IClickableControl, + public virtual IBorderControl { + public: + static constexpr StringView control_type = u"Button"; + + static Button* Create() { return new Button(); } + + protected: + Button(); + + public: + Button(const Button& other) = delete; + Button(Button&& other) = delete; + Button& operator=(const Button& other) = delete; + Button& operator=(Button&& other) = delete; + ~Button() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + public: + helper::ClickState GetClickState() override { + return click_detector_.GetState(); + } + + IEvent* ClickStateChangeEvent() override { + return click_detector_.StateChangeEvent(); + } + + IEvent* ClickEvent() { + return click_detector_.ClickEvent(); + } + + void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; + + private: + std::unique_ptr render_object_{}; + + helper::ClickDetector click_detector_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Button.hpp b/include/cru/ui/controls/Button.hpp deleted file mode 100644 index 77e0989c..00000000 --- a/include/cru/ui/controls/Button.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "ContentControl.hpp" - -#include "../helper/ClickDetector.hpp" -#include "IBorderControl.hpp" -#include "IClickableControl.hpp" -#include "cru/common/Event.hpp" -#include "cru/ui/style/ApplyBorderStyleInfo.hpp" - -namespace cru::ui::controls { -class CRU_UI_API Button : public ContentControl, - public virtual IClickableControl, - public virtual IBorderControl { - public: - static constexpr StringView control_type = u"Button"; - - static Button* Create() { return new Button(); } - - protected: - Button(); - - public: - Button(const Button& other) = delete; - Button(Button&& other) = delete; - Button& operator=(const Button& other) = delete; - Button& operator=(Button&& other) = delete; - ~Button() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - public: - helper::ClickState GetClickState() override { - return click_detector_.GetState(); - } - - IEvent* ClickStateChangeEvent() override { - return click_detector_.StateChangeEvent(); - } - - IEvent* ClickEvent() { - return click_detector_.ClickEvent(); - } - - void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; - - private: - std::unique_ptr render_object_{}; - - helper::ClickDetector click_detector_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Container.h b/include/cru/ui/controls/Container.h new file mode 100644 index 00000000..f250807d --- /dev/null +++ b/include/cru/ui/controls/Container.h @@ -0,0 +1,25 @@ +#pragma once +#include "ContentControl.h" + +namespace cru::ui::controls { +class CRU_UI_API Container : public ContentControl { + static constexpr StringView control_type = u"Container"; + + protected: + Container(); + + public: + CRU_DELETE_COPY(Container) + CRU_DELETE_MOVE(Container) + + ~Container() override; + + public: + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + private: + std::unique_ptr render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Container.hpp b/include/cru/ui/controls/Container.hpp deleted file mode 100644 index 4385c23f..00000000 --- a/include/cru/ui/controls/Container.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "ContentControl.hpp" - -namespace cru::ui::controls { -class CRU_UI_API Container : public ContentControl { - static constexpr StringView control_type = u"Container"; - - protected: - Container(); - - public: - CRU_DELETE_COPY(Container) - CRU_DELETE_MOVE(Container) - - ~Container() override; - - public: - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - private: - std::unique_ptr render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ContentControl.h b/include/cru/ui/controls/ContentControl.h new file mode 100644 index 00000000..86e90dae --- /dev/null +++ b/include/cru/ui/controls/ContentControl.h @@ -0,0 +1,38 @@ +#pragma once +#include "Control.h" + +#include "cru/ui/render/RenderObject.h" + +namespace cru::ui::controls { +class CRU_UI_API ContentControl : public Control { + protected: + ContentControl() = default; + + public: + ContentControl(const ContentControl& other) = delete; + ContentControl(ContentControl&& other) = delete; + ContentControl& operator=(const ContentControl& other) = delete; + ContentControl& operator=(ContentControl&& other) = delete; + ~ContentControl() override = default; + + Control* GetChild() const; + void SetChild(Control* child); + + protected: + virtual void OnChildChanged(Control* old_child, Control* new_child); + + render::RenderObject* GetContainerRenderObject() const { + return container_render_object_; + } + void SetContainerRenderObject(render::RenderObject* ro) { + container_render_object_ = ro; + } + + private: + using Control::AddChild; + using Control::RemoveChild; + + private: + render::RenderObject* container_render_object_ = nullptr; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ContentControl.hpp b/include/cru/ui/controls/ContentControl.hpp deleted file mode 100644 index 7b40de64..00000000 --- a/include/cru/ui/controls/ContentControl.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "Control.hpp" - -#include "cru/ui/render/RenderObject.hpp" - -namespace cru::ui::controls { -class CRU_UI_API ContentControl : public Control { - protected: - ContentControl() = default; - - public: - ContentControl(const ContentControl& other) = delete; - ContentControl(ContentControl&& other) = delete; - ContentControl& operator=(const ContentControl& other) = delete; - ContentControl& operator=(ContentControl&& other) = delete; - ~ContentControl() override = default; - - Control* GetChild() const; - void SetChild(Control* child); - - protected: - virtual void OnChildChanged(Control* old_child, Control* new_child); - - render::RenderObject* GetContainerRenderObject() const { - return container_render_object_; - } - void SetContainerRenderObject(render::RenderObject* ro) { - container_render_object_ = ro; - } - - private: - using Control::AddChild; - using Control::RemoveChild; - - private: - render::RenderObject* container_render_object_ = nullptr; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Control.h b/include/cru/ui/controls/Control.h new file mode 100644 index 00000000..c00e3a65 --- /dev/null +++ b/include/cru/ui/controls/Control.h @@ -0,0 +1,157 @@ +#pragma once +#include "Base.h" + +#include "../events/UiEvents.h" +#include "../render/Base.h" +#include "cru/common/Event.h" + +#include + +namespace cru::ui::controls { +class CRU_UI_API Control : public Object { + friend host::WindowHost; + + protected: + Control(); + + public: + Control(const Control& other) = delete; + Control(Control&& other) = delete; + Control& operator=(const Control& other) = delete; + Control& operator=(Control&& other) = delete; + ~Control() override; + + public: + virtual String GetControlType() const = 0; + + //*************** region: tree *************** + public: + host::WindowHost* GetWindowHost() const; + + Control* GetParent() const { return parent_; } + + const std::vector& GetChildren() const { return children_; } + + // Traverse the tree rooted the control including itself. + void TraverseDescendants(const std::function& predicate); + + public: + virtual render::RenderObject* GetRenderObject() const = 0; + + //*************** region: focus *************** + public: + bool HasFocus(); + + void SetFocus(); + + //*************** region: mouse *************** + public: + bool IsMouseOver() const { return is_mouse_over_; } + + bool CaptureMouse(); + + bool ReleaseMouse(); + + bool IsMouseCaptured(); + + //*************** region: cursor *************** + // Cursor is inherited from parent recursively if not set. + public: + // null for not set + std::shared_ptr GetCursor(); + + // will not return nullptr + std::shared_ptr GetInheritedCursor(); + + // null to unset + void SetCursor(std::shared_ptr cursor); + + public: + std::shared_ptr GetStyleRuleSet(); + + //*************** region: events *************** + public: + // Raised when mouse enter the control. Even when the control itself captures + // the mouse, this event is raised as regular. But if mouse is captured by + // another control, the control will not receive any mouse enter event. You + // can use `IsMouseCaptured` to get more info. + events::RoutedEvent* MouseEnterEvent() { + return &mouse_enter_event_; + } + // Raised when mouse is leave the control. Even when the control itself + // captures the mouse, this event is raised as regular. But if mouse is + // captured by another control, the control will not receive any mouse leave + // event. You can use `IsMouseCaptured` to get more info. + events::RoutedEvent* MouseLeaveEvent() { + return &mouse_leave_event_; + } + // Raised when mouse is move in the control. + events::RoutedEvent* MouseMoveEvent() { + return &mouse_move_event_; + } + // Raised when a mouse button is pressed in the control. + events::RoutedEvent* MouseDownEvent() { + return &mouse_down_event_; + } + // Raised when a mouse button is released in the control. + events::RoutedEvent* MouseUpEvent() { + return &mouse_up_event_; + } + events::RoutedEvent* MouseWheelEvent() { + return &mouse_wheel_event_; + } + events::RoutedEvent* KeyDownEvent() { + return &key_down_event_; + } + events::RoutedEvent* KeyUpEvent() { + return &key_up_event_; + } + events::RoutedEvent* GainFocusEvent() { + return &gain_focus_event_; + } + events::RoutedEvent* LoseFocusEvent() { + return &lose_focus_event_; + } + + private: + events::RoutedEvent mouse_enter_event_; + events::RoutedEvent mouse_leave_event_; + events::RoutedEvent mouse_move_event_; + events::RoutedEvent mouse_down_event_; + events::RoutedEvent mouse_up_event_; + events::RoutedEvent mouse_wheel_event_; + + events::RoutedEvent key_down_event_; + events::RoutedEvent key_up_event_; + + events::RoutedEvent gain_focus_event_; + events::RoutedEvent lose_focus_event_; + + //*************** region: tree *************** + protected: + void AddChild(Control* control, Index position); + void RemoveChild(Index position); + virtual void OnAddChild(Control* child, Index position); + virtual void OnRemoveChild(Control* child, Index position); + virtual void OnParentChanged(Control* old_parent, Control* new_parent); + virtual void OnAttachToHost(host::WindowHost* host); + virtual void OnDetachFromHost(host::WindowHost* host); + + protected: + virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) } + + private: + Control* parent_ = nullptr; + std::vector children_; + + host::WindowHost* window_host_ = nullptr; + + private: + bool is_mouse_over_ = false; + + std::shared_ptr cursor_ = nullptr; + + std::shared_ptr style_rule_set_; + std::unique_ptr style_rule_set_bind_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Control.hpp b/include/cru/ui/controls/Control.hpp deleted file mode 100644 index c51643be..00000000 --- a/include/cru/ui/controls/Control.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "../events/UiEvents.hpp" -#include "../render/Base.hpp" -#include "cru/common/Event.hpp" - -#include - -namespace cru::ui::controls { -class CRU_UI_API Control : public Object { - friend host::WindowHost; - - protected: - Control(); - - public: - Control(const Control& other) = delete; - Control(Control&& other) = delete; - Control& operator=(const Control& other) = delete; - Control& operator=(Control&& other) = delete; - ~Control() override; - - public: - virtual String GetControlType() const = 0; - - //*************** region: tree *************** - public: - host::WindowHost* GetWindowHost() const; - - Control* GetParent() const { return parent_; } - - const std::vector& GetChildren() const { return children_; } - - // Traverse the tree rooted the control including itself. - void TraverseDescendants(const std::function& predicate); - - public: - virtual render::RenderObject* GetRenderObject() const = 0; - - //*************** region: focus *************** - public: - bool HasFocus(); - - void SetFocus(); - - //*************** region: mouse *************** - public: - bool IsMouseOver() const { return is_mouse_over_; } - - bool CaptureMouse(); - - bool ReleaseMouse(); - - bool IsMouseCaptured(); - - //*************** region: cursor *************** - // Cursor is inherited from parent recursively if not set. - public: - // null for not set - std::shared_ptr GetCursor(); - - // will not return nullptr - std::shared_ptr GetInheritedCursor(); - - // null to unset - void SetCursor(std::shared_ptr cursor); - - public: - std::shared_ptr GetStyleRuleSet(); - - //*************** region: events *************** - public: - // Raised when mouse enter the control. Even when the control itself captures - // the mouse, this event is raised as regular. But if mouse is captured by - // another control, the control will not receive any mouse enter event. You - // can use `IsMouseCaptured` to get more info. - events::RoutedEvent* MouseEnterEvent() { - return &mouse_enter_event_; - } - // Raised when mouse is leave the control. Even when the control itself - // captures the mouse, this event is raised as regular. But if mouse is - // captured by another control, the control will not receive any mouse leave - // event. You can use `IsMouseCaptured` to get more info. - events::RoutedEvent* MouseLeaveEvent() { - return &mouse_leave_event_; - } - // Raised when mouse is move in the control. - events::RoutedEvent* MouseMoveEvent() { - return &mouse_move_event_; - } - // Raised when a mouse button is pressed in the control. - events::RoutedEvent* MouseDownEvent() { - return &mouse_down_event_; - } - // Raised when a mouse button is released in the control. - events::RoutedEvent* MouseUpEvent() { - return &mouse_up_event_; - } - events::RoutedEvent* MouseWheelEvent() { - return &mouse_wheel_event_; - } - events::RoutedEvent* KeyDownEvent() { - return &key_down_event_; - } - events::RoutedEvent* KeyUpEvent() { - return &key_up_event_; - } - events::RoutedEvent* GainFocusEvent() { - return &gain_focus_event_; - } - events::RoutedEvent* LoseFocusEvent() { - return &lose_focus_event_; - } - - private: - events::RoutedEvent mouse_enter_event_; - events::RoutedEvent mouse_leave_event_; - events::RoutedEvent mouse_move_event_; - events::RoutedEvent mouse_down_event_; - events::RoutedEvent mouse_up_event_; - events::RoutedEvent mouse_wheel_event_; - - events::RoutedEvent key_down_event_; - events::RoutedEvent key_up_event_; - - events::RoutedEvent gain_focus_event_; - events::RoutedEvent lose_focus_event_; - - //*************** region: tree *************** - protected: - void AddChild(Control* control, Index position); - void RemoveChild(Index position); - virtual void OnAddChild(Control* child, Index position); - virtual void OnRemoveChild(Control* child, Index position); - virtual void OnParentChanged(Control* old_parent, Control* new_parent); - virtual void OnAttachToHost(host::WindowHost* host); - virtual void OnDetachFromHost(host::WindowHost* host); - - protected: - virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) } - - private: - Control* parent_ = nullptr; - std::vector children_; - - host::WindowHost* window_host_ = nullptr; - - private: - bool is_mouse_over_ = false; - - std::shared_ptr cursor_ = nullptr; - - std::shared_ptr style_rule_set_; - std::unique_ptr style_rule_set_bind_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/FlexLayout.h b/include/cru/ui/controls/FlexLayout.h new file mode 100644 index 00000000..1255b119 --- /dev/null +++ b/include/cru/ui/controls/FlexLayout.h @@ -0,0 +1,40 @@ +#pragma once +#include "LayoutControl.h" + +namespace cru::ui::controls { +class CRU_UI_API FlexLayout : public LayoutControl { + public: + static constexpr StringView control_type = u"FlexLayout"; + + static FlexLayout* Create() { return new FlexLayout(); } + + protected: + FlexLayout(); + + public: + FlexLayout(const FlexLayout& other) = delete; + FlexLayout(FlexLayout&& other) = delete; + FlexLayout& operator=(const FlexLayout& other) = delete; + FlexLayout& operator=(FlexLayout&& other) = delete; + ~FlexLayout() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + FlexMainAlignment GetContentMainAlign() const; + void SetContentMainAlign(FlexMainAlignment value); + + FlexDirection GetFlexDirection() const; + void SetFlexDirection(FlexDirection direction); + + FlexCrossAlignment GetItemCrossAlign() const; + void SetItemCrossAlign(FlexCrossAlignment alignment); + + FlexChildLayoutData GetChildLayoutData(Control* control); + void SetChildLayoutData(Control* control, FlexChildLayoutData data); + + private: + std::shared_ptr render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/FlexLayout.hpp b/include/cru/ui/controls/FlexLayout.hpp deleted file mode 100644 index 7724c4c6..00000000 --- a/include/cru/ui/controls/FlexLayout.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "LayoutControl.hpp" - -namespace cru::ui::controls { -class CRU_UI_API FlexLayout : public LayoutControl { - public: - static constexpr StringView control_type = u"FlexLayout"; - - static FlexLayout* Create() { return new FlexLayout(); } - - protected: - FlexLayout(); - - public: - FlexLayout(const FlexLayout& other) = delete; - FlexLayout(FlexLayout&& other) = delete; - FlexLayout& operator=(const FlexLayout& other) = delete; - FlexLayout& operator=(FlexLayout&& other) = delete; - ~FlexLayout() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - FlexMainAlignment GetContentMainAlign() const; - void SetContentMainAlign(FlexMainAlignment value); - - FlexDirection GetFlexDirection() const; - void SetFlexDirection(FlexDirection direction); - - FlexCrossAlignment GetItemCrossAlign() const; - void SetItemCrossAlign(FlexCrossAlignment alignment); - - FlexChildLayoutData GetChildLayoutData(Control* control); - void SetChildLayoutData(Control* control, FlexChildLayoutData data); - - private: - std::shared_ptr render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IBorderControl.h b/include/cru/ui/controls/IBorderControl.h new file mode 100644 index 00000000..3178d7f2 --- /dev/null +++ b/include/cru/ui/controls/IBorderControl.h @@ -0,0 +1,10 @@ +#pragma once +#include "../style/ApplyBorderStyleInfo.h" +#include "Base.h" +#include "cru/common/Base.h" + +namespace cru::ui::controls { +struct CRU_UI_API IBorderControl : virtual Interface { + virtual void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) = 0; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IBorderControl.hpp b/include/cru/ui/controls/IBorderControl.hpp deleted file mode 100644 index a8bc0b51..00000000 --- a/include/cru/ui/controls/IBorderControl.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "../style/ApplyBorderStyleInfo.hpp" -#include "Base.hpp" -#include "cru/common/Base.hpp" - -namespace cru::ui::controls { -struct CRU_UI_API IBorderControl : virtual Interface { - virtual void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) = 0; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IClickableControl.h b/include/cru/ui/controls/IClickableControl.h new file mode 100644 index 00000000..48b3ad5f --- /dev/null +++ b/include/cru/ui/controls/IClickableControl.h @@ -0,0 +1,12 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Event.h" +#include "cru/ui/helper/ClickDetector.h" + +namespace cru::ui::controls { +struct CRU_UI_API IClickableControl : virtual Interface { + virtual helper::ClickState GetClickState() = 0; + virtual IEvent* ClickStateChangeEvent() = 0; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/IClickableControl.hpp b/include/cru/ui/controls/IClickableControl.hpp deleted file mode 100644 index af9ae100..00000000 --- a/include/cru/ui/controls/IClickableControl.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Event.hpp" -#include "cru/ui/helper/ClickDetector.hpp" - -namespace cru::ui::controls { -struct CRU_UI_API IClickableControl : virtual Interface { - virtual helper::ClickState GetClickState() = 0; - virtual IEvent* ClickStateChangeEvent() = 0; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/LayoutControl.h b/include/cru/ui/controls/LayoutControl.h new file mode 100644 index 00000000..639ecc74 --- /dev/null +++ b/include/cru/ui/controls/LayoutControl.h @@ -0,0 +1,37 @@ +#pragma once +#include "Control.h" + +namespace cru::ui::controls { +class CRU_UI_API LayoutControl : public Control { + protected: + LayoutControl() = default; + explicit LayoutControl(render::RenderObject* container_render_object) + : container_render_object_(container_render_object) {} + + public: + LayoutControl(const LayoutControl& other) = delete; + LayoutControl(LayoutControl&& other) = delete; + LayoutControl& operator=(const LayoutControl& other) = delete; + LayoutControl& operator=(LayoutControl&& other) = delete; + ~LayoutControl() override = default; + + using Control::AddChild; + using Control::RemoveChild; + + void ClearChildren(); + + protected: + // If container render object is not null. Render object of added or removed + // child control will automatically sync to the container render object. + render::RenderObject* GetContainerRenderObject() const; + void SetContainerRenderObject(render::RenderObject* ro) { + container_render_object_ = ro; + } + + void OnAddChild(Control* child, Index position) override; + void OnRemoveChild(Control* child, Index position) override; + + private: + render::RenderObject* container_render_object_ = nullptr; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/LayoutControl.hpp b/include/cru/ui/controls/LayoutControl.hpp deleted file mode 100644 index 3999e9bc..00000000 --- a/include/cru/ui/controls/LayoutControl.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "Control.hpp" - -namespace cru::ui::controls { -class CRU_UI_API LayoutControl : public Control { - protected: - LayoutControl() = default; - explicit LayoutControl(render::RenderObject* container_render_object) - : container_render_object_(container_render_object) {} - - public: - LayoutControl(const LayoutControl& other) = delete; - LayoutControl(LayoutControl&& other) = delete; - LayoutControl& operator=(const LayoutControl& other) = delete; - LayoutControl& operator=(LayoutControl&& other) = delete; - ~LayoutControl() override = default; - - using Control::AddChild; - using Control::RemoveChild; - - void ClearChildren(); - - protected: - // If container render object is not null. Render object of added or removed - // child control will automatically sync to the container render object. - render::RenderObject* GetContainerRenderObject() const; - void SetContainerRenderObject(render::RenderObject* ro) { - container_render_object_ = ro; - } - - void OnAddChild(Control* child, Index position) override; - void OnRemoveChild(Control* child, Index position) override; - - private: - render::RenderObject* container_render_object_ = nullptr; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/NoChildControl.h b/include/cru/ui/controls/NoChildControl.h new file mode 100644 index 00000000..6d2168cb --- /dev/null +++ b/include/cru/ui/controls/NoChildControl.h @@ -0,0 +1,20 @@ +#pragma once +#include "Control.h" + +namespace cru::ui::controls { +class CRU_UI_API NoChildControl : public Control { + protected: + NoChildControl() = default; + + public: + NoChildControl(const NoChildControl& other) = delete; + NoChildControl(NoChildControl&& other) = delete; + NoChildControl& operator=(const NoChildControl& other) = delete; + NoChildControl& operator=(NoChildControl&& other) = delete; + ~NoChildControl() override = default; + + private: + using Control::AddChild; + using Control::RemoveChild; +}; +} // namespace cru::ui diff --git a/include/cru/ui/controls/NoChildControl.hpp b/include/cru/ui/controls/NoChildControl.hpp deleted file mode 100644 index 0c432532..00000000 --- a/include/cru/ui/controls/NoChildControl.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Control.hpp" - -namespace cru::ui::controls { -class CRU_UI_API NoChildControl : public Control { - protected: - NoChildControl() = default; - - public: - NoChildControl(const NoChildControl& other) = delete; - NoChildControl(NoChildControl&& other) = delete; - NoChildControl& operator=(const NoChildControl& other) = delete; - NoChildControl& operator=(NoChildControl&& other) = delete; - ~NoChildControl() override = default; - - private: - using Control::AddChild; - using Control::RemoveChild; -}; -} // namespace cru::ui diff --git a/include/cru/ui/controls/Popup.h b/include/cru/ui/controls/Popup.h new file mode 100644 index 00000000..271ad4b7 --- /dev/null +++ b/include/cru/ui/controls/Popup.h @@ -0,0 +1,26 @@ +#pragma once +#include "RootControl.h" + +#include "cru/platform/gui/Base.h" + +#include + +namespace cru::ui::controls { +class CRU_UI_API Popup : public RootControl { + public: + static constexpr StringView kControlType = u"Popup"; + + static Popup* Create(Control* attached_control = nullptr) { + return new Popup(attached_control); + } + + explicit Popup(Control* attached_control = nullptr); + + CRU_DELETE_COPY(Popup) + CRU_DELETE_MOVE(Popup) + + ~Popup() override; + + String GetControlType() const override { return kControlType.ToString(); } +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Popup.hpp b/include/cru/ui/controls/Popup.hpp deleted file mode 100644 index 4076e45b..00000000 --- a/include/cru/ui/controls/Popup.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "RootControl.hpp" - -#include "cru/platform/gui/Base.hpp" - -#include - -namespace cru::ui::controls { -class CRU_UI_API Popup : public RootControl { - public: - static constexpr StringView kControlType = u"Popup"; - - static Popup* Create(Control* attached_control = nullptr) { - return new Popup(attached_control); - } - - explicit Popup(Control* attached_control = nullptr); - - CRU_DELETE_COPY(Popup) - CRU_DELETE_MOVE(Popup) - - ~Popup() override; - - String GetControlType() const override { return kControlType.ToString(); } -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/RootControl.h b/include/cru/ui/controls/RootControl.h new file mode 100644 index 00000000..c7ed916a --- /dev/null +++ b/include/cru/ui/controls/RootControl.h @@ -0,0 +1,39 @@ +#pragma once +#include "LayoutControl.h" + +#include "cru/common/Base.h" +#include "cru/common/Event.h" +#include "cru/platform/gui/Base.h" +#include "cru/platform/gui/Window.h" +#include "cru/ui/Base.h" +#include "cru/ui/host/WindowHost.h" + +namespace cru::ui::controls { +class CRU_UI_API RootControl : public LayoutControl { + protected: + explicit RootControl(Control* attached_control); + + public: + CRU_DELETE_COPY(RootControl) + CRU_DELETE_MOVE(RootControl) + ~RootControl() override; + + public: + render::RenderObject* GetRenderObject() const override; + + platform::gui::INativeWindow* GetNativeWindow(); + + protected: + void SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value); + + private: + std::unique_ptr window_host_; + + std::unique_ptr render_object_; + + Control* attached_control_; + + EventRevokerListGuard + gain_focus_on_create_and_destroy_when_lose_focus_event_guard_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/RootControl.hpp b/include/cru/ui/controls/RootControl.hpp deleted file mode 100644 index f70f2eeb..00000000 --- a/include/cru/ui/controls/RootControl.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "LayoutControl.hpp" - -#include "cru/common/Base.hpp" -#include "cru/common/Event.hpp" -#include "cru/platform/gui/Base.hpp" -#include "cru/platform/gui/Window.hpp" -#include "cru/ui/Base.hpp" -#include "cru/ui/host/WindowHost.hpp" - -namespace cru::ui::controls { -class CRU_UI_API RootControl : public LayoutControl { - protected: - explicit RootControl(Control* attached_control); - - public: - CRU_DELETE_COPY(RootControl) - CRU_DELETE_MOVE(RootControl) - ~RootControl() override; - - public: - render::RenderObject* GetRenderObject() const override; - - platform::gui::INativeWindow* GetNativeWindow(); - - protected: - void SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value); - - private: - std::unique_ptr window_host_; - - std::unique_ptr render_object_; - - Control* attached_control_; - - EventRevokerListGuard - gain_focus_on_create_and_destroy_when_lose_focus_event_guard_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ScrollView.h b/include/cru/ui/controls/ScrollView.h new file mode 100644 index 00000000..46c23691 --- /dev/null +++ b/include/cru/ui/controls/ScrollView.h @@ -0,0 +1,32 @@ +#pragma once +#include "ContentControl.h" +#include "cru/common/Base.h" +#include "cru/ui/render/RenderObject.h" +#include "cru/ui/render/ScrollRenderObject.h" + +#include +#include + +namespace cru::ui::controls { +class CRU_UI_API ScrollView : public ContentControl { + public: + static ScrollView* Create() { return new ScrollView(); } + + static constexpr StringView control_type = u"ScrollView"; + + ScrollView(); + + CRU_DELETE_COPY(ScrollView) + CRU_DELETE_MOVE(ScrollView) + + ~ScrollView() override = default; + + public: + String GetControlType() const override { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + private: + std::unique_ptr scroll_render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/ScrollView.hpp b/include/cru/ui/controls/ScrollView.hpp deleted file mode 100644 index 18a9bf97..00000000 --- a/include/cru/ui/controls/ScrollView.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "ContentControl.hpp" -#include "cru/common/Base.hpp" -#include "cru/ui/render/RenderObject.hpp" -#include "cru/ui/render/ScrollRenderObject.hpp" - -#include -#include - -namespace cru::ui::controls { -class CRU_UI_API ScrollView : public ContentControl { - public: - static ScrollView* Create() { return new ScrollView(); } - - static constexpr StringView control_type = u"ScrollView"; - - ScrollView(); - - CRU_DELETE_COPY(ScrollView) - CRU_DELETE_MOVE(ScrollView) - - ~ScrollView() override = default; - - public: - String GetControlType() const override { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - private: - std::unique_ptr scroll_render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/StackLayout.h b/include/cru/ui/controls/StackLayout.h new file mode 100644 index 00000000..36e8ab43 --- /dev/null +++ b/include/cru/ui/controls/StackLayout.h @@ -0,0 +1,31 @@ +#pragma once +#include "LayoutControl.h" +#include "cru/ui/Base.h" + +namespace cru::ui::controls { +class CRU_UI_API StackLayout : public LayoutControl { + public: + static constexpr StringView control_type = u"StackLayout"; + + static StackLayout* Create() { return new StackLayout(); } + + protected: + StackLayout(); + + public: + CRU_DELETE_COPY(StackLayout) + CRU_DELETE_MOVE(StackLayout) + + ~StackLayout() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + const StackChildLayoutData& GetChildLayoutData(Index position); + void SetChildLayoutData(Index position, StackChildLayoutData data); + + private: + std::shared_ptr render_object_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/StackLayout.hpp b/include/cru/ui/controls/StackLayout.hpp deleted file mode 100644 index 5d90dfda..00000000 --- a/include/cru/ui/controls/StackLayout.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "LayoutControl.hpp" -#include "cru/ui/Base.hpp" - -namespace cru::ui::controls { -class CRU_UI_API StackLayout : public LayoutControl { - public: - static constexpr StringView control_type = u"StackLayout"; - - static StackLayout* Create() { return new StackLayout(); } - - protected: - StackLayout(); - - public: - CRU_DELETE_COPY(StackLayout) - CRU_DELETE_MOVE(StackLayout) - - ~StackLayout() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - const StackChildLayoutData& GetChildLayoutData(Index position); - void SetChildLayoutData(Index position, StackChildLayoutData data); - - private: - std::shared_ptr render_object_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBlock.h b/include/cru/ui/controls/TextBlock.h new file mode 100644 index 00000000..5e5674a2 --- /dev/null +++ b/include/cru/ui/controls/TextBlock.h @@ -0,0 +1,44 @@ +#pragma once +#include "NoChildControl.h" + +#include "TextHostControlService.h" + +namespace cru::ui::controls { +class CRU_UI_API TextBlock : public NoChildControl, public virtual ITextHostControl { + public: + static constexpr StringView control_type = u"TextBlock"; + + static TextBlock* Create(); + static TextBlock* Create(String text, bool selectable = false); + + protected: + TextBlock(); + + public: + TextBlock(const TextBlock& other) = delete; + TextBlock(TextBlock&& other) = delete; + TextBlock& operator=(const TextBlock& other) = delete; + TextBlock& operator=(TextBlock&& other) = delete; + ~TextBlock() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + String GetText() const; + void SetText(String text); + + bool IsSelectable() const; + void SetSelectable(bool value); + + gsl::not_null GetTextRenderObject() override; + render::ScrollRenderObject* GetScrollRenderObject() override { + return nullptr; + } + + private: + std::unique_ptr text_render_object_; + + std::unique_ptr service_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBlock.hpp b/include/cru/ui/controls/TextBlock.hpp deleted file mode 100644 index 68e9ced1..00000000 --- a/include/cru/ui/controls/TextBlock.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include "NoChildControl.hpp" - -#include "TextHostControlService.hpp" - -namespace cru::ui::controls { -class CRU_UI_API TextBlock : public NoChildControl, public virtual ITextHostControl { - public: - static constexpr StringView control_type = u"TextBlock"; - - static TextBlock* Create(); - static TextBlock* Create(String text, bool selectable = false); - - protected: - TextBlock(); - - public: - TextBlock(const TextBlock& other) = delete; - TextBlock(TextBlock&& other) = delete; - TextBlock& operator=(const TextBlock& other) = delete; - TextBlock& operator=(TextBlock&& other) = delete; - ~TextBlock() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - String GetText() const; - void SetText(String text); - - bool IsSelectable() const; - void SetSelectable(bool value); - - gsl::not_null GetTextRenderObject() override; - render::ScrollRenderObject* GetScrollRenderObject() override { - return nullptr; - } - - private: - std::unique_ptr text_render_object_; - - std::unique_ptr service_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBox.h b/include/cru/ui/controls/TextBox.h new file mode 100644 index 00000000..2ed7db5e --- /dev/null +++ b/include/cru/ui/controls/TextBox.h @@ -0,0 +1,46 @@ +#pragma once +#include "NoChildControl.h" + +#include "IBorderControl.h" +#include "TextHostControlService.h" + +#include + +namespace cru::ui::controls { +class CRU_UI_API TextBox : public NoChildControl, + public virtual IBorderControl, + public virtual ITextHostControl { + public: + static constexpr StringView control_type = u"TextBox"; + + static TextBox* Create() { return new TextBox(); } + + protected: + TextBox(); + + public: + CRU_DELETE_COPY(TextBox) + CRU_DELETE_MOVE(TextBox) + + ~TextBox() override; + + String GetControlType() const final { return control_type.ToString(); } + + render::RenderObject* GetRenderObject() const override; + + gsl::not_null GetTextRenderObject() override; + render::ScrollRenderObject* GetScrollRenderObject() override; + + bool GetMultiLine() const; + void SetMultiLine(bool value); + + void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; + + private: + std::unique_ptr border_render_object_; + std::unique_ptr scroll_render_object_; + std::unique_ptr text_render_object_; + + std::unique_ptr service_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBox.hpp b/include/cru/ui/controls/TextBox.hpp deleted file mode 100644 index 241a8a16..00000000 --- a/include/cru/ui/controls/TextBox.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include "NoChildControl.hpp" - -#include "IBorderControl.hpp" -#include "TextHostControlService.hpp" - -#include - -namespace cru::ui::controls { -class CRU_UI_API TextBox : public NoChildControl, - public virtual IBorderControl, - public virtual ITextHostControl { - public: - static constexpr StringView control_type = u"TextBox"; - - static TextBox* Create() { return new TextBox(); } - - protected: - TextBox(); - - public: - CRU_DELETE_COPY(TextBox) - CRU_DELETE_MOVE(TextBox) - - ~TextBox() override; - - String GetControlType() const final { return control_type.ToString(); } - - render::RenderObject* GetRenderObject() const override; - - gsl::not_null GetTextRenderObject() override; - render::ScrollRenderObject* GetScrollRenderObject() override; - - bool GetMultiLine() const; - void SetMultiLine(bool value); - - void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; - - private: - std::unique_ptr border_render_object_; - std::unique_ptr scroll_render_object_; - std::unique_ptr text_render_object_; - - std::unique_ptr service_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextHostControlService.h b/include/cru/ui/controls/TextHostControlService.h new file mode 100644 index 00000000..5178107f --- /dev/null +++ b/include/cru/ui/controls/TextHostControlService.h @@ -0,0 +1,219 @@ +#pragma once +#include "Base.h" + +#include "cru/platform/gui/InputMethod.h" +#include "cru/platform/gui/TimerHelper.h" +#include "cru/platform/gui/UiApplication.h" +#include "cru/ui/controls/Control.h" +#include "cru/ui/helper/ShortcutHub.h" + +#include +#include + +namespace cru::ui::render { +class TextRenderObject; +class ScrollRenderObject; +} // namespace cru::ui::render + +namespace cru::ui::components { +class PopupMenu; +} + +namespace cru::ui::controls { +constexpr int k_default_caret_blink_duration = 500; + +struct CRU_UI_API ITextHostControl : virtual Interface { + virtual gsl::not_null GetTextRenderObject() = 0; + // May return nullptr. + virtual render::ScrollRenderObject* GetScrollRenderObject() = 0; +}; + +class TextHostControlService; + +class TextControlMovePattern : public Object { + public: + static TextControlMovePattern kLeft; + static TextControlMovePattern kRight; + static TextControlMovePattern kCtrlLeft; + static TextControlMovePattern kCtrlRight; + static TextControlMovePattern kUp; + static TextControlMovePattern kDown; + static TextControlMovePattern kHome; + static TextControlMovePattern kEnd; + static TextControlMovePattern kCtrlHome; + static TextControlMovePattern kCtrlEnd; + static TextControlMovePattern kPageUp; + static TextControlMovePattern kPageDown; + + static std::vector kDefaultPatterns; + + using MoveFunction = + std::function; + + TextControlMovePattern(String name, helper::ShortcutKeyBind key_bind, + MoveFunction move_function) + : name_(std::move(name)), + key_bind_(key_bind), + move_function_(move_function) {} + + CRU_DEFAULT_COPY(TextControlMovePattern) + CRU_DEFAULT_MOVE(TextControlMovePattern) + + ~TextControlMovePattern() override = default; + + public: + String GetName() const { return name_; } + helper::ShortcutKeyBind GetKeyBind() const { return key_bind_; } + gsl::index Move(TextHostControlService* service, StringView text, + gsl::index current_position) const { + return move_function_(service, text, current_position); + } + + private: + String name_; + helper::ShortcutKeyBind key_bind_; + MoveFunction move_function_; +}; + +class CRU_UI_API TextHostControlService : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService") + + public: + TextHostControlService(gsl::not_null control); + + CRU_DELETE_COPY(TextHostControlService) + CRU_DELETE_MOVE(TextHostControlService) + + ~TextHostControlService(); + + public: + bool IsEnabled() { return enable_; } + void SetEnabled(bool enable); + + bool IsEditable() { return this->editable_; } + void SetEditable(bool editable); + + bool IsContextMenuEnabled() { return this->context_menu_enabled_; } + void SetContextMenuEnabled(bool enabled); + + bool IsMultiLine() { return this->multi_line_; } + // If text contains line feed characters, it will be converted to space. + void SetMultiLine(bool multi_line); + + String GetText() { return this->text_; } + StringView GetTextView() { return this->text_; } + void SetText(String text, bool stop_composition = false); + + void InsertText(gsl::index position, StringView text, + bool stop_composition = false); + void DeleteChar(gsl::index position, bool stop_composition = false); + + // Return the position of deleted character. + gsl::index DeleteCharPrevious(gsl::index position, + bool stop_composition = false); + void DeleteText(TextRange range, bool stop_composition = false); + + void CancelComposition(); + + std::optional GetCompositionInfo(); + + bool IsCaretVisible() { return caret_visible_; } + void SetCaretVisible(bool visible); + + int GetCaretBlinkDuration() { return caret_blink_duration_; } + void SetCaretBlinkDuration(int milliseconds); + + gsl::index GetCaretPosition() { return selection_.GetEnd(); } + TextRange GetSelection() { return selection_; } + + StringView GetSelectedText(); + + void SetSelection(gsl::index caret_position); + void SetSelection(TextRange selection, bool scroll_to_caret = true); + + void SelectAll(); + + void ChangeSelectionEnd(gsl::index new_end); + void AbortSelection(); + + void DeleteSelectedText(); + // If some text is selected, then they are deleted first. Then insert text + // into caret position. + void ReplaceSelectedText(StringView text); + + void ScrollToCaret(); + + void Cut(); + void Copy(); + void Paste(); + + gsl::not_null GetTextRenderObject(); + render::ScrollRenderObject* GetScrollRenderObject(); + + private: + // May return nullptr. + platform::gui::IInputMethodContext* GetInputMethodContext(); + + void CoerceSelection(); + + void SetupCaret(); + void TearDownCaret(); + + void SyncTextRenderObject(); + + void UpdateInputMethodPosition(); + + template + void SetupOneHandler(events::RoutedEvent* (Control::*event)(), + void (TextHostControlService::*handler)( + typename events::RoutedEvent::EventArgs)) { + this->event_guard_ += (this->control_->*event)()->Bubble()->AddHandler( + std::bind(handler, this, std::placeholders::_1)); + } + + void MouseMoveHandler(events::MouseEventArgs& args); + void MouseDownHandler(events::MouseButtonEventArgs& args); + void MouseUpHandler(events::MouseButtonEventArgs& args); + void GainFocusHandler(events::FocusChangeEventArgs& args); + void LoseFocusHandler(events::FocusChangeEventArgs& args); + + void SetUpShortcuts(); + + enum ContextMenuItem : unsigned { + kSelectAll = 0b1, + kCut = 0b10, + kCopy = 0b100, + kPaste = 0b1000 + }; + + void OpenContextMenu(const Point& position, ContextMenuItem items); + + private: + gsl::not_null control_; + gsl::not_null text_host_control_; + + EventRevokerListGuard event_guard_; + EventRevokerListGuard input_method_context_event_guard_; + + String text_; + TextRange selection_; + + bool enable_ = false; + bool editable_ = false; + bool multi_line_ = false; + bool context_menu_enabled_ = true; + + bool caret_visible_ = false; + platform::gui::TimerAutoCanceler caret_timer_canceler_; + int caret_blink_duration_ = k_default_caret_blink_duration; + + helper::ShortcutHub shortcut_hub_; + + // true if left mouse is down and selecting + bool mouse_move_selecting_ = false; + + bool context_menu_dirty_ = true; + std::unique_ptr context_menu_; +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextHostControlService.hpp b/include/cru/ui/controls/TextHostControlService.hpp deleted file mode 100644 index be6a7c39..00000000 --- a/include/cru/ui/controls/TextHostControlService.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/platform/gui/InputMethod.hpp" -#include "cru/platform/gui/TimerHelper.hpp" -#include "cru/platform/gui/UiApplication.hpp" -#include "cru/ui/controls/Control.hpp" -#include "cru/ui/helper/ShortcutHub.hpp" - -#include -#include - -namespace cru::ui::render { -class TextRenderObject; -class ScrollRenderObject; -} // namespace cru::ui::render - -namespace cru::ui::components { -class PopupMenu; -} - -namespace cru::ui::controls { -constexpr int k_default_caret_blink_duration = 500; - -struct CRU_UI_API ITextHostControl : virtual Interface { - virtual gsl::not_null GetTextRenderObject() = 0; - // May return nullptr. - virtual render::ScrollRenderObject* GetScrollRenderObject() = 0; -}; - -class TextHostControlService; - -class TextControlMovePattern : public Object { - public: - static TextControlMovePattern kLeft; - static TextControlMovePattern kRight; - static TextControlMovePattern kCtrlLeft; - static TextControlMovePattern kCtrlRight; - static TextControlMovePattern kUp; - static TextControlMovePattern kDown; - static TextControlMovePattern kHome; - static TextControlMovePattern kEnd; - static TextControlMovePattern kCtrlHome; - static TextControlMovePattern kCtrlEnd; - static TextControlMovePattern kPageUp; - static TextControlMovePattern kPageDown; - - static std::vector kDefaultPatterns; - - using MoveFunction = - std::function; - - TextControlMovePattern(String name, helper::ShortcutKeyBind key_bind, - MoveFunction move_function) - : name_(std::move(name)), - key_bind_(key_bind), - move_function_(move_function) {} - - CRU_DEFAULT_COPY(TextControlMovePattern) - CRU_DEFAULT_MOVE(TextControlMovePattern) - - ~TextControlMovePattern() override = default; - - public: - String GetName() const { return name_; } - helper::ShortcutKeyBind GetKeyBind() const { return key_bind_; } - gsl::index Move(TextHostControlService* service, StringView text, - gsl::index current_position) const { - return move_function_(service, text, current_position); - } - - private: - String name_; - helper::ShortcutKeyBind key_bind_; - MoveFunction move_function_; -}; - -class CRU_UI_API TextHostControlService : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService") - - public: - TextHostControlService(gsl::not_null control); - - CRU_DELETE_COPY(TextHostControlService) - CRU_DELETE_MOVE(TextHostControlService) - - ~TextHostControlService(); - - public: - bool IsEnabled() { return enable_; } - void SetEnabled(bool enable); - - bool IsEditable() { return this->editable_; } - void SetEditable(bool editable); - - bool IsContextMenuEnabled() { return this->context_menu_enabled_; } - void SetContextMenuEnabled(bool enabled); - - bool IsMultiLine() { return this->multi_line_; } - // If text contains line feed characters, it will be converted to space. - void SetMultiLine(bool multi_line); - - String GetText() { return this->text_; } - StringView GetTextView() { return this->text_; } - void SetText(String text, bool stop_composition = false); - - void InsertText(gsl::index position, StringView text, - bool stop_composition = false); - void DeleteChar(gsl::index position, bool stop_composition = false); - - // Return the position of deleted character. - gsl::index DeleteCharPrevious(gsl::index position, - bool stop_composition = false); - void DeleteText(TextRange range, bool stop_composition = false); - - void CancelComposition(); - - std::optional GetCompositionInfo(); - - bool IsCaretVisible() { return caret_visible_; } - void SetCaretVisible(bool visible); - - int GetCaretBlinkDuration() { return caret_blink_duration_; } - void SetCaretBlinkDuration(int milliseconds); - - gsl::index GetCaretPosition() { return selection_.GetEnd(); } - TextRange GetSelection() { return selection_; } - - StringView GetSelectedText(); - - void SetSelection(gsl::index caret_position); - void SetSelection(TextRange selection, bool scroll_to_caret = true); - - void SelectAll(); - - void ChangeSelectionEnd(gsl::index new_end); - void AbortSelection(); - - void DeleteSelectedText(); - // If some text is selected, then they are deleted first. Then insert text - // into caret position. - void ReplaceSelectedText(StringView text); - - void ScrollToCaret(); - - void Cut(); - void Copy(); - void Paste(); - - gsl::not_null GetTextRenderObject(); - render::ScrollRenderObject* GetScrollRenderObject(); - - private: - // May return nullptr. - platform::gui::IInputMethodContext* GetInputMethodContext(); - - void CoerceSelection(); - - void SetupCaret(); - void TearDownCaret(); - - void SyncTextRenderObject(); - - void UpdateInputMethodPosition(); - - template - void SetupOneHandler(events::RoutedEvent* (Control::*event)(), - void (TextHostControlService::*handler)( - typename events::RoutedEvent::EventArgs)) { - this->event_guard_ += (this->control_->*event)()->Bubble()->AddHandler( - std::bind(handler, this, std::placeholders::_1)); - } - - void MouseMoveHandler(events::MouseEventArgs& args); - void MouseDownHandler(events::MouseButtonEventArgs& args); - void MouseUpHandler(events::MouseButtonEventArgs& args); - void GainFocusHandler(events::FocusChangeEventArgs& args); - void LoseFocusHandler(events::FocusChangeEventArgs& args); - - void SetUpShortcuts(); - - enum ContextMenuItem : unsigned { - kSelectAll = 0b1, - kCut = 0b10, - kCopy = 0b100, - kPaste = 0b1000 - }; - - void OpenContextMenu(const Point& position, ContextMenuItem items); - - private: - gsl::not_null control_; - gsl::not_null text_host_control_; - - EventRevokerListGuard event_guard_; - EventRevokerListGuard input_method_context_event_guard_; - - String text_; - TextRange selection_; - - bool enable_ = false; - bool editable_ = false; - bool multi_line_ = false; - bool context_menu_enabled_ = true; - - bool caret_visible_ = false; - platform::gui::TimerAutoCanceler caret_timer_canceler_; - int caret_blink_duration_ = k_default_caret_blink_duration; - - helper::ShortcutHub shortcut_hub_; - - // true if left mouse is down and selecting - bool mouse_move_selecting_ = false; - - bool context_menu_dirty_ = true; - std::unique_ptr context_menu_; -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Window.h b/include/cru/ui/controls/Window.h new file mode 100644 index 00000000..5fb6d594 --- /dev/null +++ b/include/cru/ui/controls/Window.h @@ -0,0 +1,27 @@ +#pragma once +#include "cru/platform/gui/Base.h" +#include "cru/ui/controls/RootControl.h" + +#include "cru/common/Base.h" + +namespace cru::ui::controls { +class CRU_UI_API Window final : public RootControl { + public: + static constexpr StringView control_type = u"Window"; + + public: + static Window* Create(Control* attached_control = nullptr); + + private: + explicit Window(Control* attached_control); + + public: + CRU_DELETE_COPY(Window) + CRU_DELETE_MOVE(Window) + + ~Window() override; + + public: + String GetControlType() const final { return control_type.ToString(); } +}; +} // namespace cru::ui::controls diff --git a/include/cru/ui/controls/Window.hpp b/include/cru/ui/controls/Window.hpp deleted file mode 100644 index c304a839..00000000 --- a/include/cru/ui/controls/Window.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "cru/platform/gui/Base.hpp" -#include "cru/ui/controls/RootControl.hpp" - -#include "cru/common/Base.hpp" - -namespace cru::ui::controls { -class CRU_UI_API Window final : public RootControl { - public: - static constexpr StringView control_type = u"Window"; - - public: - static Window* Create(Control* attached_control = nullptr); - - private: - explicit Window(Control* attached_control); - - public: - CRU_DELETE_COPY(Window) - CRU_DELETE_MOVE(Window) - - ~Window() override; - - public: - String GetControlType() const final { return control_type.ToString(); } -}; -} // namespace cru::ui::controls diff --git a/include/cru/ui/events/FocusChangeEventArgs.h b/include/cru/ui/events/FocusChangeEventArgs.h new file mode 100644 index 00000000..aaef25b4 --- /dev/null +++ b/include/cru/ui/events/FocusChangeEventArgs.h @@ -0,0 +1,23 @@ +#pragma once +#include "UiEventArgs.h" + +namespace cru::ui::events { + +class CRU_UI_API FocusChangeEventArgs : public UiEventArgs { + public: + FocusChangeEventArgs(Object* sender, Object* original_sender, + const bool is_window = false) + : UiEventArgs(sender, original_sender), is_window_(is_window) {} + FocusChangeEventArgs(const FocusChangeEventArgs& other) = default; + FocusChangeEventArgs(FocusChangeEventArgs&& other) = default; + FocusChangeEventArgs& operator=(const FocusChangeEventArgs& other) = default; + FocusChangeEventArgs& operator=(FocusChangeEventArgs&& other) = default; + ~FocusChangeEventArgs() override = default; + + // Return whether the focus change is caused by the window-wide focus change. + bool IsWindow() const { return is_window_; } + + private: + bool is_window_; +}; +} // namespace cru::ui::event diff --git a/include/cru/ui/events/FocusChangeEventArgs.hpp b/include/cru/ui/events/FocusChangeEventArgs.hpp deleted file mode 100644 index b72790a5..00000000 --- a/include/cru/ui/events/FocusChangeEventArgs.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "UiEventArgs.hpp" - -namespace cru::ui::events { - -class CRU_UI_API FocusChangeEventArgs : public UiEventArgs { - public: - FocusChangeEventArgs(Object* sender, Object* original_sender, - const bool is_window = false) - : UiEventArgs(sender, original_sender), is_window_(is_window) {} - FocusChangeEventArgs(const FocusChangeEventArgs& other) = default; - FocusChangeEventArgs(FocusChangeEventArgs&& other) = default; - FocusChangeEventArgs& operator=(const FocusChangeEventArgs& other) = default; - FocusChangeEventArgs& operator=(FocusChangeEventArgs&& other) = default; - ~FocusChangeEventArgs() override = default; - - // Return whether the focus change is caused by the window-wide focus change. - bool IsWindow() const { return is_window_; } - - private: - bool is_window_; -}; -} // namespace cru::ui::event diff --git a/include/cru/ui/events/KeyEventArgs.h b/include/cru/ui/events/KeyEventArgs.h new file mode 100644 index 00000000..0ece9126 --- /dev/null +++ b/include/cru/ui/events/KeyEventArgs.h @@ -0,0 +1,29 @@ +#pragma once +#include "UiEventArgs.h" + +#include "cru/platform/gui/Keyboard.h" + +namespace cru::ui::events { +class CRU_UI_API KeyEventArgs : public UiEventArgs { + public: + KeyEventArgs(Object* sender, Object* original_sender, + platform::gui::KeyCode key_code, + platform::gui::KeyModifier key_modifier) + : UiEventArgs(sender, original_sender), + key_code_(key_code), + key_modifier_(key_modifier) {} + KeyEventArgs(const KeyEventArgs& other) = default; + KeyEventArgs(KeyEventArgs&& other) = default; + KeyEventArgs& operator=(const KeyEventArgs& other) = default; + KeyEventArgs& operator=(KeyEventArgs&& other) = default; + ~KeyEventArgs() override = default; + + platform::gui::KeyCode GetKeyCode() const { return key_code_; } + platform::gui::KeyModifier GetKeyModifier() const { return key_modifier_; } + + private: + platform::gui::KeyCode key_code_; + platform::gui::KeyModifier key_modifier_; +}; + +} // namespace cru::ui::event diff --git a/include/cru/ui/events/KeyEventArgs.hpp b/include/cru/ui/events/KeyEventArgs.hpp deleted file mode 100644 index 133db1df..00000000 --- a/include/cru/ui/events/KeyEventArgs.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "UiEventArgs.hpp" - -#include "cru/platform/gui/Keyboard.hpp" - -namespace cru::ui::events { -class CRU_UI_API KeyEventArgs : public UiEventArgs { - public: - KeyEventArgs(Object* sender, Object* original_sender, - platform::gui::KeyCode key_code, - platform::gui::KeyModifier key_modifier) - : UiEventArgs(sender, original_sender), - key_code_(key_code), - key_modifier_(key_modifier) {} - KeyEventArgs(const KeyEventArgs& other) = default; - KeyEventArgs(KeyEventArgs&& other) = default; - KeyEventArgs& operator=(const KeyEventArgs& other) = default; - KeyEventArgs& operator=(KeyEventArgs&& other) = default; - ~KeyEventArgs() override = default; - - platform::gui::KeyCode GetKeyCode() const { return key_code_; } - platform::gui::KeyModifier GetKeyModifier() const { return key_modifier_; } - - private: - platform::gui::KeyCode key_code_; - platform::gui::KeyModifier key_modifier_; -}; - -} // namespace cru::ui::event diff --git a/include/cru/ui/events/MouseButtonEventArgs.h b/include/cru/ui/events/MouseButtonEventArgs.h new file mode 100644 index 00000000..13b3b0a4 --- /dev/null +++ b/include/cru/ui/events/MouseButtonEventArgs.h @@ -0,0 +1,35 @@ +#pragma once +#include "MouseEventArgs.h" + +#include "cru/platform/gui/Keyboard.h" + +namespace cru::ui::events { + +class CRU_UI_API MouseButtonEventArgs : public MouseEventArgs { + public: + MouseButtonEventArgs(Object* sender, Object* original_sender, + const Point& point, const MouseButton button, + platform::gui::KeyModifier key_modifier) + : MouseEventArgs(sender, original_sender, point), + button_(button), + key_modifier_(key_modifier) {} + MouseButtonEventArgs(Object* sender, Object* original_sender, + const MouseButton button, + platform::gui::KeyModifier key_modifier) + : MouseEventArgs(sender, original_sender), + button_(button), + key_modifier_(key_modifier) {} + MouseButtonEventArgs(const MouseButtonEventArgs& other) = default; + MouseButtonEventArgs(MouseButtonEventArgs&& other) = default; + MouseButtonEventArgs& operator=(const MouseButtonEventArgs& other) = default; + MouseButtonEventArgs& operator=(MouseButtonEventArgs&& other) = default; + ~MouseButtonEventArgs() override = default; + + MouseButton GetButton() const { return button_; } + platform::gui::KeyModifier GetKeyModifier() const { return key_modifier_; } + + private: + MouseButton button_; + platform::gui::KeyModifier key_modifier_; +}; +} // namespace cru::ui::event diff --git a/include/cru/ui/events/MouseButtonEventArgs.hpp b/include/cru/ui/events/MouseButtonEventArgs.hpp deleted file mode 100644 index 791ed03b..00000000 --- a/include/cru/ui/events/MouseButtonEventArgs.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "MouseEventArgs.hpp" - -#include "cru/platform/gui/Keyboard.hpp" - -namespace cru::ui::events { - -class CRU_UI_API MouseButtonEventArgs : public MouseEventArgs { - public: - MouseButtonEventArgs(Object* sender, Object* original_sender, - const Point& point, const MouseButton button, - platform::gui::KeyModifier key_modifier) - : MouseEventArgs(sender, original_sender, point), - button_(button), - key_modifier_(key_modifier) {} - MouseButtonEventArgs(Object* sender, Object* original_sender, - const MouseButton button, - platform::gui::KeyModifier key_modifier) - : MouseEventArgs(sender, original_sender), - button_(button), - key_modifier_(key_modifier) {} - MouseButtonEventArgs(const MouseButtonEventArgs& other) = default; - MouseButtonEventArgs(MouseButtonEventArgs&& other) = default; - MouseButtonEventArgs& operator=(const MouseButtonEventArgs& other) = default; - MouseButtonEventArgs& operator=(MouseButtonEventArgs&& other) = default; - ~MouseButtonEventArgs() override = default; - - MouseButton GetButton() const { return button_; } - platform::gui::KeyModifier GetKeyModifier() const { return key_modifier_; } - - private: - MouseButton button_; - platform::gui::KeyModifier key_modifier_; -}; -} // namespace cru::ui::event diff --git a/include/cru/ui/events/MouseEventArgs.h b/include/cru/ui/events/MouseEventArgs.h new file mode 100644 index 00000000..11ce6463 --- /dev/null +++ b/include/cru/ui/events/MouseEventArgs.h @@ -0,0 +1,27 @@ +#pragma once +#include "UiEventArgs.h" + +#include + +namespace cru::ui::events { +class CRU_UI_API MouseEventArgs : public UiEventArgs { + public: + MouseEventArgs(Object* sender, Object* original_sender, + const std::optional& point = std::nullopt) + : UiEventArgs(sender, original_sender), point_(point) {} + MouseEventArgs(const MouseEventArgs& other) = default; + MouseEventArgs(MouseEventArgs&& other) = default; + MouseEventArgs& operator=(const MouseEventArgs& other) = default; + MouseEventArgs& operator=(MouseEventArgs&& other) = default; + ~MouseEventArgs() override = default; + + // This point is relative to window client lefttop. + Point GetPoint() const { return point_.value_or(Point{}); } + Point GetPoint(render::RenderObject* render_target) const; + Point GetPointToContent(render::RenderObject* render_target) const; + Point GetPointOfScreen() const; + + private: + std::optional point_; +}; +} // namespace cru::ui::events diff --git a/include/cru/ui/events/MouseEventArgs.hpp b/include/cru/ui/events/MouseEventArgs.hpp deleted file mode 100644 index 0adc65b6..00000000 --- a/include/cru/ui/events/MouseEventArgs.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "UiEventArgs.hpp" - -#include - -namespace cru::ui::events { -class CRU_UI_API MouseEventArgs : public UiEventArgs { - public: - MouseEventArgs(Object* sender, Object* original_sender, - const std::optional& point = std::nullopt) - : UiEventArgs(sender, original_sender), point_(point) {} - MouseEventArgs(const MouseEventArgs& other) = default; - MouseEventArgs(MouseEventArgs&& other) = default; - MouseEventArgs& operator=(const MouseEventArgs& other) = default; - MouseEventArgs& operator=(MouseEventArgs&& other) = default; - ~MouseEventArgs() override = default; - - // This point is relative to window client lefttop. - Point GetPoint() const { return point_.value_or(Point{}); } - Point GetPoint(render::RenderObject* render_target) const; - Point GetPointToContent(render::RenderObject* render_target) const; - Point GetPointOfScreen() const; - - private: - std::optional point_; -}; -} // namespace cru::ui::events diff --git a/include/cru/ui/events/MouseWheelEventArgs.h b/include/cru/ui/events/MouseWheelEventArgs.h new file mode 100644 index 00000000..85791491 --- /dev/null +++ b/include/cru/ui/events/MouseWheelEventArgs.h @@ -0,0 +1,29 @@ +#pragma once +#include "MouseEventArgs.h" + +#include "cru/platform/gui/Keyboard.h" + +namespace cru::ui::events { +class CRU_UI_API MouseWheelEventArgs : public MouseEventArgs { + public: + MouseWheelEventArgs(Object* sender, Object* original_sender, + const Point& point, const float delta, + platform::gui::KeyModifier key_modifier) + : MouseEventArgs(sender, original_sender, point), + delta_(delta), + key_modifier_(key_modifier) {} + MouseWheelEventArgs(const MouseWheelEventArgs& other) = default; + MouseWheelEventArgs(MouseWheelEventArgs&& other) = default; + MouseWheelEventArgs& operator=(const MouseWheelEventArgs& other) = default; + MouseWheelEventArgs& operator=(MouseWheelEventArgs&& other) = default; + ~MouseWheelEventArgs() override = default; + + // Positive means down; Negative means up. + float GetDelta() const { return delta_; } + platform::gui::KeyModifier GetKeyModifier() const { return key_modifier_; } + + private: + float delta_; + platform::gui::KeyModifier key_modifier_; +}; +} // namespace cru::ui::event diff --git a/include/cru/ui/events/MouseWheelEventArgs.hpp b/include/cru/ui/events/MouseWheelEventArgs.hpp deleted file mode 100644 index c6c0fe10..00000000 --- a/include/cru/ui/events/MouseWheelEventArgs.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "MouseEventArgs.hpp" - -#include "cru/platform/gui/Keyboard.hpp" - -namespace cru::ui::events { -class CRU_UI_API MouseWheelEventArgs : public MouseEventArgs { - public: - MouseWheelEventArgs(Object* sender, Object* original_sender, - const Point& point, const float delta, - platform::gui::KeyModifier key_modifier) - : MouseEventArgs(sender, original_sender, point), - delta_(delta), - key_modifier_(key_modifier) {} - MouseWheelEventArgs(const MouseWheelEventArgs& other) = default; - MouseWheelEventArgs(MouseWheelEventArgs&& other) = default; - MouseWheelEventArgs& operator=(const MouseWheelEventArgs& other) = default; - MouseWheelEventArgs& operator=(MouseWheelEventArgs&& other) = default; - ~MouseWheelEventArgs() override = default; - - // Positive means down; Negative means up. - float GetDelta() const { return delta_; } - platform::gui::KeyModifier GetKeyModifier() const { return key_modifier_; } - - private: - float delta_; - platform::gui::KeyModifier key_modifier_; -}; -} // namespace cru::ui::event diff --git a/include/cru/ui/events/PaintEventArgs.h b/include/cru/ui/events/PaintEventArgs.h new file mode 100644 index 00000000..934c6c8c --- /dev/null +++ b/include/cru/ui/events/PaintEventArgs.h @@ -0,0 +1,25 @@ +#pragma once +#include "UiEventArgs.h" + +namespace cru::platform::graphics { +struct IPainter; +} + +namespace cru::ui::events { +class CRU_UI_API PaintEventArgs : public UiEventArgs { + public: + PaintEventArgs(Object* sender, Object* original_sender, + platform::graphics::IPainter* painter) + : UiEventArgs(sender, original_sender), painter_(painter) {} + PaintEventArgs(const PaintEventArgs& other) = default; + PaintEventArgs(PaintEventArgs&& other) = default; + PaintEventArgs& operator=(const PaintEventArgs& other) = default; + PaintEventArgs& operator=(PaintEventArgs&& other) = default; + ~PaintEventArgs() = default; + + platform::graphics::IPainter* GetPainter() const { return painter_; } + + private: + platform::graphics::IPainter* painter_; +}; +} // namespace cru::ui::event diff --git a/include/cru/ui/events/PaintEventArgs.hpp b/include/cru/ui/events/PaintEventArgs.hpp deleted file mode 100644 index f2b53977..00000000 --- a/include/cru/ui/events/PaintEventArgs.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "UiEventArgs.hpp" - -namespace cru::platform::graphics { -struct IPainter; -} - -namespace cru::ui::events { -class CRU_UI_API PaintEventArgs : public UiEventArgs { - public: - PaintEventArgs(Object* sender, Object* original_sender, - platform::graphics::IPainter* painter) - : UiEventArgs(sender, original_sender), painter_(painter) {} - PaintEventArgs(const PaintEventArgs& other) = default; - PaintEventArgs(PaintEventArgs&& other) = default; - PaintEventArgs& operator=(const PaintEventArgs& other) = default; - PaintEventArgs& operator=(PaintEventArgs&& other) = default; - ~PaintEventArgs() = default; - - platform::graphics::IPainter* GetPainter() const { return painter_; } - - private: - platform::graphics::IPainter* painter_; -}; -} // namespace cru::ui::event diff --git a/include/cru/ui/events/RoutedEvent.h b/include/cru/ui/events/RoutedEvent.h new file mode 100644 index 00000000..909678f8 --- /dev/null +++ b/include/cru/ui/events/RoutedEvent.h @@ -0,0 +1,39 @@ +#pragma once +#include "UiEventArgs.h" + +#include "cru/common/Event.h" + +namespace cru::ui::events { +// TEventArgs must not be a reference type. This class help add reference. +// EventArgs must be reference because the IsHandled property must be settable. +template +class CRU_UI_API RoutedEvent { + public: + static_assert(std::is_base_of_v, + "TEventArgs must be subclass of UiEventArgs."); + static_assert(!std::is_reference_v, + "TEventArgs must not be reference."); + + using RawEventArgs = TEventArgs; + using IEventType = IEvent; + using EventArgs = typename IEventType::EventArgs; + + RoutedEvent() = default; + RoutedEvent(const RoutedEvent& other) = delete; + RoutedEvent(RoutedEvent&& other) = delete; + RoutedEvent& operator=(const RoutedEvent& other) = delete; + RoutedEvent& operator=(RoutedEvent&& other) = delete; + ~RoutedEvent() = default; + + IEvent* Direct() { return &direct_; } + + IEvent* Bubble() { return &bubble_; } + + IEvent* Tunnel() { return &tunnel_; } + + private: + Event direct_; + Event bubble_; + Event tunnel_; +}; +} // namespace cru::ui::event diff --git a/include/cru/ui/events/RoutedEvent.hpp b/include/cru/ui/events/RoutedEvent.hpp deleted file mode 100644 index dd0bc21f..00000000 --- a/include/cru/ui/events/RoutedEvent.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "UiEventArgs.hpp" - -#include "cru/common/Event.hpp" - -namespace cru::ui::events { -// TEventArgs must not be a reference type. This class help add reference. -// EventArgs must be reference because the IsHandled property must be settable. -template -class CRU_UI_API RoutedEvent { - public: - static_assert(std::is_base_of_v, - "TEventArgs must be subclass of UiEventArgs."); - static_assert(!std::is_reference_v, - "TEventArgs must not be reference."); - - using RawEventArgs = TEventArgs; - using IEventType = IEvent; - using EventArgs = typename IEventType::EventArgs; - - RoutedEvent() = default; - RoutedEvent(const RoutedEvent& other) = delete; - RoutedEvent(RoutedEvent&& other) = delete; - RoutedEvent& operator=(const RoutedEvent& other) = delete; - RoutedEvent& operator=(RoutedEvent&& other) = delete; - ~RoutedEvent() = default; - - IEvent* Direct() { return &direct_; } - - IEvent* Bubble() { return &bubble_; } - - IEvent* Tunnel() { return &tunnel_; } - - private: - Event direct_; - Event bubble_; - Event tunnel_; -}; -} // namespace cru::ui::event diff --git a/include/cru/ui/events/UiEventArgs.h b/include/cru/ui/events/UiEventArgs.h new file mode 100644 index 00000000..fff84edd --- /dev/null +++ b/include/cru/ui/events/UiEventArgs.h @@ -0,0 +1,28 @@ +#pragma once +#include "../Base.h" + +namespace cru::ui::events { +class CRU_UI_API UiEventArgs : public Object { + public: + UiEventArgs(Object* sender, Object* original_sender) + : sender_(sender), original_sender_(original_sender), handled_(false) {} + + UiEventArgs(const UiEventArgs& other) = default; + UiEventArgs(UiEventArgs&& other) = default; + UiEventArgs& operator=(const UiEventArgs& other) = default; + UiEventArgs& operator=(UiEventArgs&& other) = default; + ~UiEventArgs() override = default; + + Object* GetSender() const { return sender_; } + + Object* GetOriginalSender() const { return original_sender_; } + + bool IsHandled() const { return handled_; } + void SetHandled(const bool handled = true) { handled_ = handled; } + + private: + Object* sender_; + Object* original_sender_; + bool handled_; +}; +} // namespace cru::ui::event diff --git a/include/cru/ui/events/UiEventArgs.hpp b/include/cru/ui/events/UiEventArgs.hpp deleted file mode 100644 index 1e1f9e93..00000000 --- a/include/cru/ui/events/UiEventArgs.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::events { -class CRU_UI_API UiEventArgs : public Object { - public: - UiEventArgs(Object* sender, Object* original_sender) - : sender_(sender), original_sender_(original_sender), handled_(false) {} - - UiEventArgs(const UiEventArgs& other) = default; - UiEventArgs(UiEventArgs&& other) = default; - UiEventArgs& operator=(const UiEventArgs& other) = default; - UiEventArgs& operator=(UiEventArgs&& other) = default; - ~UiEventArgs() override = default; - - Object* GetSender() const { return sender_; } - - Object* GetOriginalSender() const { return original_sender_; } - - bool IsHandled() const { return handled_; } - void SetHandled(const bool handled = true) { handled_ = handled; } - - private: - Object* sender_; - Object* original_sender_; - bool handled_; -}; -} // namespace cru::ui::event diff --git a/include/cru/ui/events/UiEvents.h b/include/cru/ui/events/UiEvents.h new file mode 100644 index 00000000..301ec694 --- /dev/null +++ b/include/cru/ui/events/UiEvents.h @@ -0,0 +1,10 @@ +#pragma once + +#include "FocusChangeEventArgs.h" +#include "KeyEventArgs.h" +#include "MouseButtonEventArgs.h" +#include "MouseEventArgs.h" +#include "MouseWheelEventArgs.h" +#include "PaintEventArgs.h" +#include "RoutedEvent.h" +#include "UiEventArgs.h" diff --git a/include/cru/ui/events/UiEvents.hpp b/include/cru/ui/events/UiEvents.hpp deleted file mode 100644 index bd6f7d2a..00000000 --- a/include/cru/ui/events/UiEvents.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "FocusChangeEventArgs.hpp" -#include "KeyEventArgs.hpp" -#include "MouseButtonEventArgs.hpp" -#include "MouseEventArgs.hpp" -#include "MouseWheelEventArgs.hpp" -#include "PaintEventArgs.hpp" -#include "RoutedEvent.hpp" -#include "UiEventArgs.hpp" diff --git a/include/cru/ui/helper/ClickDetector.h b/include/cru/ui/helper/ClickDetector.h new file mode 100644 index 00000000..6e30aaf0 --- /dev/null +++ b/include/cru/ui/helper/ClickDetector.h @@ -0,0 +1,87 @@ +#pragma once +#include "../controls/Control.h" + +namespace cru::ui::helper { +class CRU_UI_API ClickEventArgs : Object { + public: + ClickEventArgs(controls::Control* sender, const Point& down_point, + const Point& up_point, MouseButton button) + : sender_(sender), + down_point_(down_point), + up_point_(up_point), + button_(button) {} + + CRU_DEFAULT_COPY(ClickEventArgs) + CRU_DEFAULT_MOVE(ClickEventArgs) + + ~ClickEventArgs() override = default; + + controls::Control* GetSender() const { return sender_; } + Point GetDownPoint() const { return down_point_; } + Point GetUpPoint() const { return up_point_; } + MouseButton GetButton() const { return button_; } + + private: + controls::Control* sender_; + Point down_point_; + Point up_point_; + MouseButton button_; +}; + +enum class ClickState { + None, // Mouse is outside the control. + Hover, // Mouse hovers on the control but not pressed + Press, // Mouse is pressed and if released click is done. + PressInactive // Mouse is pressed but if released click is canceled. +}; + +class ClickDetector : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::ClickDetector") + + public: + explicit ClickDetector(controls::Control* control); + + CRU_DELETE_COPY(ClickDetector) + CRU_DELETE_MOVE(ClickDetector) + + ~ClickDetector() override = default; + + controls::Control* GetControl() const { return control_; } + + ClickState GetState() const { return state_; } + + // Default is enable. + bool IsEnabled() const { return enable_; } + // If disable when user is pressing, the pressing is deactivated. + void SetEnabled(bool enable); + + // Default is left and right. + MouseButton GetTriggerButton() const { return trigger_button_; } + // If unset the trigger button when user is pressing, the pressing is + // deactivated. + void SetTriggerButton(MouseButton trigger_button); + + IEvent* ClickEvent() { return &event_; } + + IEvent* StateChangeEvent() { return &state_change_event_; } + + private: + void SetState(ClickState state); + + private: + controls::Control* control_; + + ClickState state_ = ClickState::None; + + bool enable_ = true; + MouseButton trigger_button_ = mouse_buttons::left | mouse_buttons::right; + + Event event_; + Event state_change_event_; + + std::vector event_rovoker_guards_; + + Point down_point_; + MouseButton button_; +}; +} // namespace cru::ui::helper diff --git a/include/cru/ui/helper/ClickDetector.hpp b/include/cru/ui/helper/ClickDetector.hpp deleted file mode 100644 index fd80a953..00000000 --- a/include/cru/ui/helper/ClickDetector.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include "../controls/Control.hpp" - -namespace cru::ui::helper { -class CRU_UI_API ClickEventArgs : Object { - public: - ClickEventArgs(controls::Control* sender, const Point& down_point, - const Point& up_point, MouseButton button) - : sender_(sender), - down_point_(down_point), - up_point_(up_point), - button_(button) {} - - CRU_DEFAULT_COPY(ClickEventArgs) - CRU_DEFAULT_MOVE(ClickEventArgs) - - ~ClickEventArgs() override = default; - - controls::Control* GetSender() const { return sender_; } - Point GetDownPoint() const { return down_point_; } - Point GetUpPoint() const { return up_point_; } - MouseButton GetButton() const { return button_; } - - private: - controls::Control* sender_; - Point down_point_; - Point up_point_; - MouseButton button_; -}; - -enum class ClickState { - None, // Mouse is outside the control. - Hover, // Mouse hovers on the control but not pressed - Press, // Mouse is pressed and if released click is done. - PressInactive // Mouse is pressed but if released click is canceled. -}; - -class ClickDetector : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::ClickDetector") - - public: - explicit ClickDetector(controls::Control* control); - - CRU_DELETE_COPY(ClickDetector) - CRU_DELETE_MOVE(ClickDetector) - - ~ClickDetector() override = default; - - controls::Control* GetControl() const { return control_; } - - ClickState GetState() const { return state_; } - - // Default is enable. - bool IsEnabled() const { return enable_; } - // If disable when user is pressing, the pressing is deactivated. - void SetEnabled(bool enable); - - // Default is left and right. - MouseButton GetTriggerButton() const { return trigger_button_; } - // If unset the trigger button when user is pressing, the pressing is - // deactivated. - void SetTriggerButton(MouseButton trigger_button); - - IEvent* ClickEvent() { return &event_; } - - IEvent* StateChangeEvent() { return &state_change_event_; } - - private: - void SetState(ClickState state); - - private: - controls::Control* control_; - - ClickState state_ = ClickState::None; - - bool enable_ = true; - MouseButton trigger_button_ = mouse_buttons::left | mouse_buttons::right; - - Event event_; - Event state_change_event_; - - std::vector event_rovoker_guards_; - - Point down_point_; - MouseButton button_; -}; -} // namespace cru::ui::helper diff --git a/include/cru/ui/helper/ShortcutHub.h b/include/cru/ui/helper/ShortcutHub.h new file mode 100644 index 00000000..84e786aa --- /dev/null +++ b/include/cru/ui/helper/ShortcutHub.h @@ -0,0 +1,142 @@ +#pragma once +#include "../Base.h" + +#include "../events/UiEvents.h" +#include "cru/common/Event.h" +#include "cru/platform/gui/Keyboard.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cru::ui::helper { + +class ShortcutKeyBind { + public: + ShortcutKeyBind( + platform::gui::KeyCode key, + platform::gui::KeyModifier modifier = platform::gui::KeyModifiers::none) + : key_(key), modifier_(modifier) {} + + CRU_DEFAULT_COPY(ShortcutKeyBind) + CRU_DEFAULT_MOVE(ShortcutKeyBind) + + ~ShortcutKeyBind() = default; + + platform::gui::KeyCode GetKey() const { return key_; } + platform::gui::KeyModifier GetModifier() const { return modifier_; } + + ShortcutKeyBind AddModifier(platform::gui::KeyModifier modifier) const { + return ShortcutKeyBind(key_, modifier_ | modifier); + } + + bool Is(platform::gui::KeyCode key, + platform::gui::KeyModifier modifier) const { + return key == key_ && modifier == modifier_; + } + + bool operator==(const ShortcutKeyBind& other) const { + return this->key_ == other.key_ && this->modifier_ == other.modifier_; + } + + bool operator!=(const ShortcutKeyBind& other) const { + return !this->operator==(other); + } + + String ToString() const { + String result = u"("; + result += platform::gui::ToString(modifier_); + result += u")"; + result += platform::gui::ToString(key_); + return result; + } + + private: + platform::gui::KeyCode key_; + platform::gui::KeyModifier modifier_; +}; + +inline String ToString(const ShortcutKeyBind& key_bind) { + return key_bind.ToString(); +} +} // namespace cru::ui::helper + +namespace std { +template <> +struct hash { + std::size_t operator()(const cru::ui::helper::ShortcutKeyBind& value) const { + std::size_t result = 0; + cru::hash_combine(result, static_cast(value.GetKey())); + cru::hash_combine(result, static_cast(value.GetModifier())); + return result; + } +}; +} // namespace std + +namespace cru::ui::helper { +struct Shortcut { + // Just for debug. + String name; + ShortcutKeyBind key_bind; + // Return true if it consumes the shortcut. Or return false if it does not + // handle the shortcut. + std::function handler; +}; + +struct ShortcutInfo { + int id; + String name; + ShortcutKeyBind key_bind; + std::function handler; +}; + +class CRU_UI_API ShortcutHub : public Object { + public: + ShortcutHub() = default; + + CRU_DELETE_COPY(ShortcutHub) + CRU_DELETE_MOVE(ShortcutHub) + + ~ShortcutHub() override = default; + + int RegisterShortcut(String name, ShortcutKeyBind bind, + std::function handler) { + return RegisterShortcut({std::move(name), bind, std::move(handler)}); + } + + // Return an id used for unregistering. + int RegisterShortcut(Shortcut shortcut); + + void UnregisterShortcut(int id); + + std::vector GetAllShortcuts() const; + std::optional GetShortcut(int id) const; + const std::vector& GetShortcutByKeyBind( + const ShortcutKeyBind& key_bind) const; + + IEvent* FallbackKeyEvent() { return &fallback_event_; } + + void Install(controls::Control* control); + void Uninstall(); + + private: + void OnKeyDown(events::KeyEventArgs& event); + + private: + std::unordered_map> map_; + + std::vector empty_list_; + + int current_id_ = 1; + + Event fallback_event_; + + EventRevokerListGuard event_guard_; +}; +} // namespace cru::ui::helper diff --git a/include/cru/ui/helper/ShortcutHub.hpp b/include/cru/ui/helper/ShortcutHub.hpp deleted file mode 100644 index c7054786..00000000 --- a/include/cru/ui/helper/ShortcutHub.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include "../events/UiEvents.hpp" -#include "cru/common/Event.hpp" -#include "cru/platform/gui/Keyboard.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace cru::ui::helper { - -class ShortcutKeyBind { - public: - ShortcutKeyBind( - platform::gui::KeyCode key, - platform::gui::KeyModifier modifier = platform::gui::KeyModifiers::none) - : key_(key), modifier_(modifier) {} - - CRU_DEFAULT_COPY(ShortcutKeyBind) - CRU_DEFAULT_MOVE(ShortcutKeyBind) - - ~ShortcutKeyBind() = default; - - platform::gui::KeyCode GetKey() const { return key_; } - platform::gui::KeyModifier GetModifier() const { return modifier_; } - - ShortcutKeyBind AddModifier(platform::gui::KeyModifier modifier) const { - return ShortcutKeyBind(key_, modifier_ | modifier); - } - - bool Is(platform::gui::KeyCode key, - platform::gui::KeyModifier modifier) const { - return key == key_ && modifier == modifier_; - } - - bool operator==(const ShortcutKeyBind& other) const { - return this->key_ == other.key_ && this->modifier_ == other.modifier_; - } - - bool operator!=(const ShortcutKeyBind& other) const { - return !this->operator==(other); - } - - String ToString() const { - String result = u"("; - result += platform::gui::ToString(modifier_); - result += u")"; - result += platform::gui::ToString(key_); - return result; - } - - private: - platform::gui::KeyCode key_; - platform::gui::KeyModifier modifier_; -}; - -inline String ToString(const ShortcutKeyBind& key_bind) { - return key_bind.ToString(); -} -} // namespace cru::ui::helper - -namespace std { -template <> -struct hash { - std::size_t operator()(const cru::ui::helper::ShortcutKeyBind& value) const { - std::size_t result = 0; - cru::hash_combine(result, static_cast(value.GetKey())); - cru::hash_combine(result, static_cast(value.GetModifier())); - return result; - } -}; -} // namespace std - -namespace cru::ui::helper { -struct Shortcut { - // Just for debug. - String name; - ShortcutKeyBind key_bind; - // Return true if it consumes the shortcut. Or return false if it does not - // handle the shortcut. - std::function handler; -}; - -struct ShortcutInfo { - int id; - String name; - ShortcutKeyBind key_bind; - std::function handler; -}; - -class CRU_UI_API ShortcutHub : public Object { - public: - ShortcutHub() = default; - - CRU_DELETE_COPY(ShortcutHub) - CRU_DELETE_MOVE(ShortcutHub) - - ~ShortcutHub() override = default; - - int RegisterShortcut(String name, ShortcutKeyBind bind, - std::function handler) { - return RegisterShortcut({std::move(name), bind, std::move(handler)}); - } - - // Return an id used for unregistering. - int RegisterShortcut(Shortcut shortcut); - - void UnregisterShortcut(int id); - - std::vector GetAllShortcuts() const; - std::optional GetShortcut(int id) const; - const std::vector& GetShortcutByKeyBind( - const ShortcutKeyBind& key_bind) const; - - IEvent* FallbackKeyEvent() { return &fallback_event_; } - - void Install(controls::Control* control); - void Uninstall(); - - private: - void OnKeyDown(events::KeyEventArgs& event); - - private: - std::unordered_map> map_; - - std::vector empty_list_; - - int current_id_ = 1; - - Event fallback_event_; - - EventRevokerListGuard event_guard_; -}; -} // namespace cru::ui::helper diff --git a/include/cru/ui/host/LayoutPaintCycler.h b/include/cru/ui/host/LayoutPaintCycler.h new file mode 100644 index 00000000..e95ed81d --- /dev/null +++ b/include/cru/ui/host/LayoutPaintCycler.h @@ -0,0 +1,40 @@ +#pragma once +#include "../Base.h" + +#include "cru/platform/gui/TimerHelper.h" +#include "cru/platform/gui/UiApplication.h" + +#include + +namespace cru::ui::host { +class CRU_UI_API LayoutPaintCycler { + public: + explicit LayoutPaintCycler(WindowHost* host); + + CRU_DELETE_COPY(LayoutPaintCycler) + CRU_DELETE_MOVE(LayoutPaintCycler) + + ~LayoutPaintCycler(); + + public: + void InvalidateLayout(); + void InvalidatePaint(); + + bool IsLayoutDirty() { return layout_dirty_; } + + private: + void OnCycle(); + + private: + WindowHost* host_; + + platform::gui::TimerAutoCanceler timer_canceler_; + + bool layout_dirty_ = true; + bool paint_dirty_ = true; + + std::chrono::steady_clock::time_point last_cycle_time_; + std::chrono::steady_clock::duration cycle_threshold_ = + std::chrono::milliseconds(1000) / 144; +}; +} // namespace cru::ui::host diff --git a/include/cru/ui/host/LayoutPaintCycler.hpp b/include/cru/ui/host/LayoutPaintCycler.hpp deleted file mode 100644 index 1d44ad06..00000000 --- a/include/cru/ui/host/LayoutPaintCycler.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include "cru/platform/gui/TimerHelper.hpp" -#include "cru/platform/gui/UiApplication.hpp" - -#include - -namespace cru::ui::host { -class CRU_UI_API LayoutPaintCycler { - public: - explicit LayoutPaintCycler(WindowHost* host); - - CRU_DELETE_COPY(LayoutPaintCycler) - CRU_DELETE_MOVE(LayoutPaintCycler) - - ~LayoutPaintCycler(); - - public: - void InvalidateLayout(); - void InvalidatePaint(); - - bool IsLayoutDirty() { return layout_dirty_; } - - private: - void OnCycle(); - - private: - WindowHost* host_; - - platform::gui::TimerAutoCanceler timer_canceler_; - - bool layout_dirty_ = true; - bool paint_dirty_ = true; - - std::chrono::steady_clock::time_point last_cycle_time_; - std::chrono::steady_clock::duration cycle_threshold_ = - std::chrono::milliseconds(1000) / 144; -}; -} // namespace cru::ui::host diff --git a/include/cru/ui/host/WindowHost.h b/include/cru/ui/host/WindowHost.h new file mode 100644 index 00000000..caa50397 --- /dev/null +++ b/include/cru/ui/host/WindowHost.h @@ -0,0 +1,164 @@ +#pragma once +#include "../Base.h" + +#include "../render/Base.h" +#include "cru/common/Event.h" +#include "cru/platform/gui/Cursor.h" +#include "cru/platform/gui/UiApplication.h" +#include "cru/platform/gui/Window.h" + +#include +#include +#include + +namespace cru::ui::host { +class LayoutPaintCycler; + +struct AfterLayoutEventArgs {}; + +// The bridge between control tree and native window. +class CRU_UI_API WindowHost : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::host::WindowHost") + + public: + explicit WindowHost(controls::Control* root_control); + + CRU_DELETE_COPY(WindowHost) + CRU_DELETE_MOVE(WindowHost) + + ~WindowHost() override; + + public: + platform::gui::INativeWindow* GetNativeWindow() { return native_window_; } + + // Mark the layout as invalid, and arrange a re-layout later. + // This method could be called more than one times in a message cycle. But + // layout only takes place once. + void InvalidateLayout(); + + // Mark the paint as invalid, and arrange a re-paint later. + // This method could be called more than one times in a message cycle. But + // paint only takes place once. + void InvalidatePaint(); + + IEvent* AfterLayoutEvent() { + return &after_layout_event_; + } + + void Relayout(); + void RelayoutWithSize(const Size& available_size = Size::Infinate(), + bool set_window_size_to_fit_content = false); + + void Repaint(); + + // Is layout is invalid, wait for relayout and then run the action. Otherwist + // run it right now. + void RunAfterLayoutStable(std::function action); + + // If true, preferred size of root render object is set to window size when + // measure. Default is true. + bool IsLayoutPreferToFillWindow() const; + void SetLayoutPreferToFillWindow(bool value); + + // Get current control that mouse hovers on. This ignores the mouse-capture + // control. Even when mouse is captured by another control, this function + // return the control under cursor. You can use `GetMouseCaptureControl` to + // get more info. + controls::Control* GetMouseHoverControl() const { + return mouse_hover_control_; + } + + //*************** region: focus *************** + + controls::Control* GetFocusControl(); + + void SetFocusControl(controls::Control* control); + + //*************** region: focus *************** + + // Pass nullptr to release capture. If mouse is already capture by a control, + // this capture will fail and return false. If control is identical to the + // capturing control, capture is not changed and this function will return + // true. + // + // When capturing control changes, + // appropriate event will be sent. If mouse is not on the capturing control + // and capture is released, mouse enter event will be sent to the mouse-hover + // control. If mouse is not on the capturing control and capture is set, mouse + // leave event will be sent to the mouse-hover control. + bool CaptureMouseFor(controls::Control* control); + + // Return null if not captured. + controls::Control* GetMouseCaptureControl(); + + controls::Control* HitTest(const Point& point); + + void UpdateCursor(); + + IEvent* NativeWindowChangeEvent() { + return &native_window_change_event_; + } + + std::shared_ptr GetOverrideCursor(); + void SetOverrideCursor(std::shared_ptr cursor); + + private: + gsl::not_null CreateNativeWindow(); + + //*************** region: native messages *************** + void OnNativeDestroy(platform::gui::INativeWindow* window, std::nullptr_t); + void OnNativePaint(platform::gui::INativeWindow* window, std::nullptr_t); + void OnNativeResize(platform::gui::INativeWindow* window, const Size& size); + + void OnNativeFocus(platform::gui::INativeWindow* window, + cru::platform::gui::FocusChangeType focus); + + void OnNativeMouseEnterLeave(platform::gui::INativeWindow* window, + cru::platform::gui::MouseEnterLeaveType enter); + void OnNativeMouseMove(platform::gui::INativeWindow* window, + const Point& point); + void OnNativeMouseDown(platform::gui::INativeWindow* window, + const platform::gui::NativeMouseButtonEventArgs& args); + void OnNativeMouseUp(platform::gui::INativeWindow* window, + const platform::gui::NativeMouseButtonEventArgs& args); + void OnNativeMouseWheel(platform::gui::INativeWindow* window, + const platform::gui::NativeMouseWheelEventArgs& args); + + void OnNativeKeyDown(platform::gui::INativeWindow* window, + const platform::gui::NativeKeyEventArgs& args); + void OnNativeKeyUp(platform::gui::INativeWindow* window, + const platform::gui::NativeKeyEventArgs& args); + + //*************** region: event dispatcher helper *************** + + void DispatchMouseHoverControlChangeEvent(controls::Control* old_control, + controls::Control* new_control, + const Point& point, bool no_leave, + bool no_enter); + + private: + controls::Control* root_control_ = nullptr; + render::RenderObject* root_render_object_ = nullptr; + + platform::gui::INativeWindow* native_window_ = nullptr; + + std::unique_ptr layout_paint_cycler_; + + Event after_layout_event_; + std::vector > after_layout_stable_action_; + + std::vector event_revoker_guards_; + + controls::Control* mouse_hover_control_ = nullptr; + + controls::Control* focus_control_; + + controls::Control* mouse_captured_control_ = nullptr; + + bool layout_prefer_to_fill_window_ = false; + + Event native_window_change_event_; + + std::shared_ptr override_cursor_; +}; +} // namespace cru::ui::host diff --git a/include/cru/ui/host/WindowHost.hpp b/include/cru/ui/host/WindowHost.hpp deleted file mode 100644 index 7832174c..00000000 --- a/include/cru/ui/host/WindowHost.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include "../render/Base.hpp" -#include "cru/common/Event.hpp" -#include "cru/platform/gui/Cursor.hpp" -#include "cru/platform/gui/UiApplication.hpp" -#include "cru/platform/gui/Window.hpp" - -#include -#include -#include - -namespace cru::ui::host { -class LayoutPaintCycler; - -struct AfterLayoutEventArgs {}; - -// The bridge between control tree and native window. -class CRU_UI_API WindowHost : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::host::WindowHost") - - public: - explicit WindowHost(controls::Control* root_control); - - CRU_DELETE_COPY(WindowHost) - CRU_DELETE_MOVE(WindowHost) - - ~WindowHost() override; - - public: - platform::gui::INativeWindow* GetNativeWindow() { return native_window_; } - - // Mark the layout as invalid, and arrange a re-layout later. - // This method could be called more than one times in a message cycle. But - // layout only takes place once. - void InvalidateLayout(); - - // Mark the paint as invalid, and arrange a re-paint later. - // This method could be called more than one times in a message cycle. But - // paint only takes place once. - void InvalidatePaint(); - - IEvent* AfterLayoutEvent() { - return &after_layout_event_; - } - - void Relayout(); - void RelayoutWithSize(const Size& available_size = Size::Infinate(), - bool set_window_size_to_fit_content = false); - - void Repaint(); - - // Is layout is invalid, wait for relayout and then run the action. Otherwist - // run it right now. - void RunAfterLayoutStable(std::function action); - - // If true, preferred size of root render object is set to window size when - // measure. Default is true. - bool IsLayoutPreferToFillWindow() const; - void SetLayoutPreferToFillWindow(bool value); - - // Get current control that mouse hovers on. This ignores the mouse-capture - // control. Even when mouse is captured by another control, this function - // return the control under cursor. You can use `GetMouseCaptureControl` to - // get more info. - controls::Control* GetMouseHoverControl() const { - return mouse_hover_control_; - } - - //*************** region: focus *************** - - controls::Control* GetFocusControl(); - - void SetFocusControl(controls::Control* control); - - //*************** region: focus *************** - - // Pass nullptr to release capture. If mouse is already capture by a control, - // this capture will fail and return false. If control is identical to the - // capturing control, capture is not changed and this function will return - // true. - // - // When capturing control changes, - // appropriate event will be sent. If mouse is not on the capturing control - // and capture is released, mouse enter event will be sent to the mouse-hover - // control. If mouse is not on the capturing control and capture is set, mouse - // leave event will be sent to the mouse-hover control. - bool CaptureMouseFor(controls::Control* control); - - // Return null if not captured. - controls::Control* GetMouseCaptureControl(); - - controls::Control* HitTest(const Point& point); - - void UpdateCursor(); - - IEvent* NativeWindowChangeEvent() { - return &native_window_change_event_; - } - - std::shared_ptr GetOverrideCursor(); - void SetOverrideCursor(std::shared_ptr cursor); - - private: - gsl::not_null CreateNativeWindow(); - - //*************** region: native messages *************** - void OnNativeDestroy(platform::gui::INativeWindow* window, std::nullptr_t); - void OnNativePaint(platform::gui::INativeWindow* window, std::nullptr_t); - void OnNativeResize(platform::gui::INativeWindow* window, const Size& size); - - void OnNativeFocus(platform::gui::INativeWindow* window, - cru::platform::gui::FocusChangeType focus); - - void OnNativeMouseEnterLeave(platform::gui::INativeWindow* window, - cru::platform::gui::MouseEnterLeaveType enter); - void OnNativeMouseMove(platform::gui::INativeWindow* window, - const Point& point); - void OnNativeMouseDown(platform::gui::INativeWindow* window, - const platform::gui::NativeMouseButtonEventArgs& args); - void OnNativeMouseUp(platform::gui::INativeWindow* window, - const platform::gui::NativeMouseButtonEventArgs& args); - void OnNativeMouseWheel(platform::gui::INativeWindow* window, - const platform::gui::NativeMouseWheelEventArgs& args); - - void OnNativeKeyDown(platform::gui::INativeWindow* window, - const platform::gui::NativeKeyEventArgs& args); - void OnNativeKeyUp(platform::gui::INativeWindow* window, - const platform::gui::NativeKeyEventArgs& args); - - //*************** region: event dispatcher helper *************** - - void DispatchMouseHoverControlChangeEvent(controls::Control* old_control, - controls::Control* new_control, - const Point& point, bool no_leave, - bool no_enter); - - private: - controls::Control* root_control_ = nullptr; - render::RenderObject* root_render_object_ = nullptr; - - platform::gui::INativeWindow* native_window_ = nullptr; - - std::unique_ptr layout_paint_cycler_; - - Event after_layout_event_; - std::vector > after_layout_stable_action_; - - std::vector event_revoker_guards_; - - controls::Control* mouse_hover_control_ = nullptr; - - controls::Control* focus_control_; - - controls::Control* mouse_captured_control_ = nullptr; - - bool layout_prefer_to_fill_window_ = false; - - Event native_window_change_event_; - - std::shared_ptr override_cursor_; -}; -} // namespace cru::ui::host diff --git a/include/cru/ui/mapper/BorderStyleMapper.h b/include/cru/ui/mapper/BorderStyleMapper.h new file mode 100644 index 00000000..d585639f --- /dev/null +++ b/include/cru/ui/mapper/BorderStyleMapper.h @@ -0,0 +1,20 @@ +#pragma once +#include "Mapper.h" +#include "cru/ui/style/ApplyBorderStyleInfo.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper { +class CRU_UI_API BorderStyleMapper + : public BasicMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(BorderStyleMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + ui::style::ApplyBorderStyleInfo DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/BorderStyleMapper.hpp b/include/cru/ui/mapper/BorderStyleMapper.hpp deleted file mode 100644 index 7a574f38..00000000 --- a/include/cru/ui/mapper/BorderStyleMapper.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Mapper.hpp" -#include "cru/ui/style/ApplyBorderStyleInfo.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API BorderStyleMapper - : public BasicMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(BorderStyleMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - ui::style::ApplyBorderStyleInfo DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/BrushMapper.h b/include/cru/ui/mapper/BrushMapper.h new file mode 100644 index 00000000..be70e89e --- /dev/null +++ b/include/cru/ui/mapper/BrushMapper.h @@ -0,0 +1,20 @@ +#pragma once +#include "Mapper.h" +#include "cru/common/Base.h" +#include "cru/platform/graphics/Brush.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper { +class BrushMapper : public BasicRefMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(BrushMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + std::shared_ptr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/BrushMapper.hpp b/include/cru/ui/mapper/BrushMapper.hpp deleted file mode 100644 index b2021076..00000000 --- a/include/cru/ui/mapper/BrushMapper.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Mapper.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/Brush.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper { -class BrushMapper : public BasicRefMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(BrushMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - std::shared_ptr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/ColorMapper.h b/include/cru/ui/mapper/ColorMapper.h new file mode 100644 index 00000000..785f1ca9 --- /dev/null +++ b/include/cru/ui/mapper/ColorMapper.h @@ -0,0 +1,19 @@ +#pragma once +#include "Mapper.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper { +class CRU_UI_API ColorMapper : public BasicMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ColorMapper) + + public: + bool SupportMapFromString() override { return true; } + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + Color DoMapFromString(String str) override; + Color DoMapFromXml(xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/ColorMapper.hpp b/include/cru/ui/mapper/ColorMapper.hpp deleted file mode 100644 index d96ca74b..00000000 --- a/include/cru/ui/mapper/ColorMapper.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "Mapper.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API ColorMapper : public BasicMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ColorMapper) - - public: - bool SupportMapFromString() override { return true; } - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - Color DoMapFromString(String str) override; - Color DoMapFromXml(xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/CornerRadiusMapper.h b/include/cru/ui/mapper/CornerRadiusMapper.h new file mode 100644 index 00000000..b8998a1b --- /dev/null +++ b/include/cru/ui/mapper/CornerRadiusMapper.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Mapper.h" + +namespace cru::ui::mapper { +class CRU_UI_API CornerRadiusMapper : public BasicMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(CornerRadiusMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + CornerRadius DoMapFromXml(xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/CornerRadiusMapper.hpp b/include/cru/ui/mapper/CornerRadiusMapper.hpp deleted file mode 100644 index 4d83f2de..00000000 --- a/include/cru/ui/mapper/CornerRadiusMapper.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Mapper.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API CornerRadiusMapper : public BasicMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(CornerRadiusMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - CornerRadius DoMapFromXml(xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/CursorMapper.h b/include/cru/ui/mapper/CursorMapper.h new file mode 100644 index 00000000..d98a798c --- /dev/null +++ b/include/cru/ui/mapper/CursorMapper.h @@ -0,0 +1,21 @@ +#pragma once +#include "Mapper.h" +#include "cru/platform/gui/Cursor.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper { +class CRU_UI_API CursorMapper : public BasicRefMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(CursorMapper); + + public: + bool SupportMapFromString() override { return true; } + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + std::shared_ptr DoMapFromString(String str) override; + std::shared_ptr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/CursorMapper.hpp b/include/cru/ui/mapper/CursorMapper.hpp deleted file mode 100644 index 6cb61d87..00000000 --- a/include/cru/ui/mapper/CursorMapper.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "Mapper.hpp" -#include "cru/platform/gui/Cursor.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API CursorMapper : public BasicRefMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(CursorMapper); - - public: - bool SupportMapFromString() override { return true; } - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - std::shared_ptr DoMapFromString(String str) override; - std::shared_ptr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/FontMapper.h b/include/cru/ui/mapper/FontMapper.h new file mode 100644 index 00000000..545b94d8 --- /dev/null +++ b/include/cru/ui/mapper/FontMapper.h @@ -0,0 +1,19 @@ +#pragma once +#include "Mapper.h" +#include "cru/common/Base.h" +#include "cru/platform/graphics/Font.h" + +namespace cru::ui::mapper { +class FontMapper : public BasicRefMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(FontMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + std::shared_ptr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/FontMapper.hpp b/include/cru/ui/mapper/FontMapper.hpp deleted file mode 100644 index ad8c43b5..00000000 --- a/include/cru/ui/mapper/FontMapper.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "Mapper.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/graphics/Font.hpp" - -namespace cru::ui::mapper { -class FontMapper : public BasicRefMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(FontMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - std::shared_ptr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/Mapper.h b/include/cru/ui/mapper/Mapper.h new file mode 100644 index 00000000..fa7f8cef --- /dev/null +++ b/include/cru/ui/mapper/Mapper.h @@ -0,0 +1,92 @@ +#pragma once +#include "../Base.h" + +#include "cru/common/ClonablePtr.h" +#include "cru/common/Exception.h" +#include "cru/xml/XmlNode.h" + +#include +#include +#include +#include + +namespace cru::ui::mapper { +template +class BasicMapper; + +class CRU_UI_API MapperBase : public Object { + public: + explicit MapperBase(std::type_index type_index); + + CRU_DELETE_COPY(MapperBase) + CRU_DELETE_MOVE(MapperBase) + + ~MapperBase() override = default; + + public: + std::type_index GetTypeIndex() const { return type_index_; } + + template + BasicMapper* StaticCast() { + return static_cast*>(this); + } + + template + BasicMapper* DynamicCast() { + return dynamic_cast*>(this); + } + + virtual bool SupportMapFromString() { return false; } + virtual bool SupportMapFromXml() { return false; } + virtual bool XmlElementIsOfThisType(xml::XmlElementNode* node) { + return false; + } + + private: + std::type_index type_index_; +}; + +template +class CRU_UI_API BasicMapper : public MapperBase { + public: + static_assert(std::is_default_constructible_v, + "T must be default constructible."); + + BasicMapper() : MapperBase(typeid(T)) {} + + CRU_DELETE_COPY(BasicMapper) + CRU_DELETE_MOVE(BasicMapper) + + ~BasicMapper() override = default; + + virtual T MapFromString(String str) { + if (!SupportMapFromString()) { + throw Exception(u"This mapper does not support map from string."); + } + + return DoMapFromString(str); + } + + T MapFromXml(xml::XmlElementNode* node) { + if (!SupportMapFromXml()) { + throw Exception(u"This mapper does not support map from xml."); + } + + if (!XmlElementIsOfThisType(node)) { + throw Exception(u"This xml element is not of mapping type."); + } + + return DoMapFromXml(node); + } + + protected: + virtual T DoMapFromString(String str) { return {}; } + virtual T DoMapFromXml(xml::XmlElementNode* node) { return {}; } +}; + +template +using BasicRefMapper = BasicMapper>; + +template +using BasicPtrMapper = BasicMapper>; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/Mapper.hpp b/include/cru/ui/mapper/Mapper.hpp deleted file mode 100644 index c52bec70..00000000 --- a/include/cru/ui/mapper/Mapper.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include "cru/common/ClonablePtr.hpp" -#include "cru/common/Exception.hpp" -#include "cru/xml/XmlNode.hpp" - -#include -#include -#include -#include - -namespace cru::ui::mapper { -template -class BasicMapper; - -class CRU_UI_API MapperBase : public Object { - public: - explicit MapperBase(std::type_index type_index); - - CRU_DELETE_COPY(MapperBase) - CRU_DELETE_MOVE(MapperBase) - - ~MapperBase() override = default; - - public: - std::type_index GetTypeIndex() const { return type_index_; } - - template - BasicMapper* StaticCast() { - return static_cast*>(this); - } - - template - BasicMapper* DynamicCast() { - return dynamic_cast*>(this); - } - - virtual bool SupportMapFromString() { return false; } - virtual bool SupportMapFromXml() { return false; } - virtual bool XmlElementIsOfThisType(xml::XmlElementNode* node) { - return false; - } - - private: - std::type_index type_index_; -}; - -template -class CRU_UI_API BasicMapper : public MapperBase { - public: - static_assert(std::is_default_constructible_v, - "T must be default constructible."); - - BasicMapper() : MapperBase(typeid(T)) {} - - CRU_DELETE_COPY(BasicMapper) - CRU_DELETE_MOVE(BasicMapper) - - ~BasicMapper() override = default; - - virtual T MapFromString(String str) { - if (!SupportMapFromString()) { - throw Exception(u"This mapper does not support map from string."); - } - - return DoMapFromString(str); - } - - T MapFromXml(xml::XmlElementNode* node) { - if (!SupportMapFromXml()) { - throw Exception(u"This mapper does not support map from xml."); - } - - if (!XmlElementIsOfThisType(node)) { - throw Exception(u"This xml element is not of mapping type."); - } - - return DoMapFromXml(node); - } - - protected: - virtual T DoMapFromString(String str) { return {}; } - virtual T DoMapFromXml(xml::XmlElementNode* node) { return {}; } -}; - -template -using BasicRefMapper = BasicMapper>; - -template -using BasicPtrMapper = BasicMapper>; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/MapperRegistry.h b/include/cru/ui/mapper/MapperRegistry.h new file mode 100644 index 00000000..29d26156 --- /dev/null +++ b/include/cru/ui/mapper/MapperRegistry.h @@ -0,0 +1,58 @@ +#pragma once + +#include "Mapper.h" + +#include +#include + +namespace cru::ui::mapper { +class CRU_UI_API MapperRegistry { + public: + static MapperRegistry* GetInstance(); + + MapperRegistry(); + + CRU_DELETE_COPY(MapperRegistry) + CRU_DELETE_MOVE(MapperRegistry) + + ~MapperRegistry(); + + const std::vector& GetAllMappers() const { return mapper_list_; } + + template + BasicMapper* GetMapper() const { + for (auto mapper : mapper_list_) { + if (mapper->GetTypeIndex() == typeid(T)) { + return static_cast*>(mapper); + } + } + return nullptr; + } + + template + BasicRefMapper* GetRefMapper() const { + return GetMapper>(); + } + + template + BasicPtrMapper* GetPtrMapper() const { + return GetMapper>(); + } + + template + std::vector GetMappersByInterface() const { + std::vector result; + for (auto mapper : mapper_list_) { + auto m = dynamic_cast(mapper); + if (m) result.push_back(m); + } + return result; + } + + void RegisterMapper(MapperBase* mapper); + void UnregisterMapper(MapperBase* mapper); + + private: + std::vector mapper_list_; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/MapperRegistry.hpp b/include/cru/ui/mapper/MapperRegistry.hpp deleted file mode 100644 index 1c02be49..00000000 --- a/include/cru/ui/mapper/MapperRegistry.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include "Mapper.hpp" - -#include -#include - -namespace cru::ui::mapper { -class CRU_UI_API MapperRegistry { - public: - static MapperRegistry* GetInstance(); - - MapperRegistry(); - - CRU_DELETE_COPY(MapperRegistry) - CRU_DELETE_MOVE(MapperRegistry) - - ~MapperRegistry(); - - const std::vector& GetAllMappers() const { return mapper_list_; } - - template - BasicMapper* GetMapper() const { - for (auto mapper : mapper_list_) { - if (mapper->GetTypeIndex() == typeid(T)) { - return static_cast*>(mapper); - } - } - return nullptr; - } - - template - BasicRefMapper* GetRefMapper() const { - return GetMapper>(); - } - - template - BasicPtrMapper* GetPtrMapper() const { - return GetMapper>(); - } - - template - std::vector GetMappersByInterface() const { - std::vector result; - for (auto mapper : mapper_list_) { - auto m = dynamic_cast(mapper); - if (m) result.push_back(m); - } - return result; - } - - void RegisterMapper(MapperBase* mapper); - void UnregisterMapper(MapperBase* mapper); - - private: - std::vector mapper_list_; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/PointMapper.h b/include/cru/ui/mapper/PointMapper.h new file mode 100644 index 00000000..83dd135b --- /dev/null +++ b/include/cru/ui/mapper/PointMapper.h @@ -0,0 +1,18 @@ +#pragma once +#include "Mapper.h" + +namespace cru::ui::mapper { +class CRU_UI_API PointMapper : public BasicMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(PointMapper) + + public: + bool SupportMapFromString() override { return true; } + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + Point DoMapFromString(String str) override; + Point DoMapFromXml(xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/PointMapper.hpp b/include/cru/ui/mapper/PointMapper.hpp deleted file mode 100644 index b1837fe1..00000000 --- a/include/cru/ui/mapper/PointMapper.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "Mapper.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API PointMapper : public BasicMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(PointMapper) - - public: - bool SupportMapFromString() override { return true; } - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - Point DoMapFromString(String str) override; - Point DoMapFromXml(xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/SizeMapper.h b/include/cru/ui/mapper/SizeMapper.h new file mode 100644 index 00000000..6cf3eb9a --- /dev/null +++ b/include/cru/ui/mapper/SizeMapper.h @@ -0,0 +1,18 @@ +#pragma once +#include "Mapper.h" + +namespace cru::ui::mapper { +class CRU_UI_API SizeMapper : public BasicMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(SizeMapper) + + public: + bool SupportMapFromString() override { return true; } + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + Size DoMapFromString(String str) override; + Size DoMapFromXml(xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/SizeMapper.hpp b/include/cru/ui/mapper/SizeMapper.hpp deleted file mode 100644 index 6ab4b97d..00000000 --- a/include/cru/ui/mapper/SizeMapper.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "Mapper.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API SizeMapper : public BasicMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(SizeMapper) - - public: - bool SupportMapFromString() override { return true; } - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - Size DoMapFromString(String str) override; - Size DoMapFromXml(xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/ThicknessMapper.h b/include/cru/ui/mapper/ThicknessMapper.h new file mode 100644 index 00000000..10f6c87e --- /dev/null +++ b/include/cru/ui/mapper/ThicknessMapper.h @@ -0,0 +1,22 @@ +#pragma once +#include "Mapper.h" + +#include "../Base.h" +#include "cru/common/Base.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper { +class CRU_UI_API ThicknessMapper : public BasicMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ThicknessMapper) + + public: + bool SupportMapFromString() override { return true; } + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + Thickness DoMapFromString(String str) override; + Thickness DoMapFromXml(xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/ThicknessMapper.hpp b/include/cru/ui/mapper/ThicknessMapper.hpp deleted file mode 100644 index 4ffbeb9b..00000000 --- a/include/cru/ui/mapper/ThicknessMapper.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "Mapper.hpp" - -#include "../Base.hpp" -#include "cru/common/Base.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper { -class CRU_UI_API ThicknessMapper : public BasicMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ThicknessMapper) - - public: - bool SupportMapFromString() override { return true; } - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - Thickness DoMapFromString(String str) override; - Thickness DoMapFromXml(xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper diff --git a/include/cru/ui/mapper/style/AndConditionMapper.h b/include/cru/ui/mapper/style/AndConditionMapper.h new file mode 100644 index 00000000..142637a7 --- /dev/null +++ b/include/cru/ui/mapper/style/AndConditionMapper.h @@ -0,0 +1,25 @@ +#pragma once +#include "../Mapper.h" +#include "IConditionMapper.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API AndConditionMapper + : public BasicPtrMapper, + public virtual IConditionMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(AndConditionMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/AndConditionMapper.hpp b/include/cru/ui/mapper/style/AndConditionMapper.hpp deleted file mode 100644 index 747e496d..00000000 --- a/include/cru/ui/mapper/style/AndConditionMapper.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "IConditionMapper.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API AndConditionMapper - : public BasicPtrMapper, - public virtual IConditionMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(AndConditionMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/BorderStylerMapper.h b/include/cru/ui/mapper/style/BorderStylerMapper.h new file mode 100644 index 00000000..da09989b --- /dev/null +++ b/include/cru/ui/mapper/style/BorderStylerMapper.h @@ -0,0 +1,28 @@ +#pragma once +#include "../Mapper.h" +#include "cru/common/ClonablePtr.h" +#include "cru/ui/mapper/style/IStylerMapper.h" +#include "cru/ui/style/Styler.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API BorderStylerMapper + : public BasicPtrMapper, + public virtual IStylerMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(BorderStylerMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapStylerFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/BorderStylerMapper.hpp b/include/cru/ui/mapper/style/BorderStylerMapper.hpp deleted file mode 100644 index 2f48550c..00000000 --- a/include/cru/ui/mapper/style/BorderStylerMapper.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/ui/mapper/style/IStylerMapper.hpp" -#include "cru/ui/style/Styler.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API BorderStylerMapper - : public BasicPtrMapper, - public virtual IStylerMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(BorderStylerMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapStylerFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/ClickStateConditionMapper.h b/include/cru/ui/mapper/style/ClickStateConditionMapper.h new file mode 100644 index 00000000..0c25646c --- /dev/null +++ b/include/cru/ui/mapper/style/ClickStateConditionMapper.h @@ -0,0 +1,26 @@ +#pragma once +#include "../Mapper.h" +#include "IConditionMapper.h" +#include "cru/ui/style/Condition.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API ClickStateConditionMapper + : public BasicPtrMapper, + public virtual IConditionMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ClickStateConditionMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + public: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp b/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp deleted file mode 100644 index 63577641..00000000 --- a/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "IConditionMapper.hpp" -#include "cru/ui/style/Condition.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API ClickStateConditionMapper - : public BasicPtrMapper, - public virtual IConditionMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ClickStateConditionMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - public: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/CursorStylerMapper.h b/include/cru/ui/mapper/style/CursorStylerMapper.h new file mode 100644 index 00000000..37c3ade9 --- /dev/null +++ b/include/cru/ui/mapper/style/CursorStylerMapper.h @@ -0,0 +1,26 @@ +#pragma once +#include "../Mapper.h" +#include "cru/ui/mapper/style/IStylerMapper.h" +#include "cru/ui/style/Styler.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API CursorStylerMapper + : public BasicPtrMapper, + public virtual IStylerMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(CursorStylerMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapStylerFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/CursorStylerMapper.hpp b/include/cru/ui/mapper/style/CursorStylerMapper.hpp deleted file mode 100644 index 2b0c62a8..00000000 --- a/include/cru/ui/mapper/style/CursorStylerMapper.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "cru/ui/mapper/style/IStylerMapper.hpp" -#include "cru/ui/style/Styler.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API CursorStylerMapper - : public BasicPtrMapper, - public virtual IStylerMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(CursorStylerMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapStylerFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/FocusConditionMapper.h b/include/cru/ui/mapper/style/FocusConditionMapper.h new file mode 100644 index 00000000..bc7264d1 --- /dev/null +++ b/include/cru/ui/mapper/style/FocusConditionMapper.h @@ -0,0 +1,26 @@ +#pragma once +#include "../Mapper.h" +#include "IConditionMapper.h" +#include "cru/ui/style/Condition.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API FocusConditionMapper + : public BasicPtrMapper, + public virtual IConditionMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(FocusConditionMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/FocusConditionMapper.hpp b/include/cru/ui/mapper/style/FocusConditionMapper.hpp deleted file mode 100644 index 00809850..00000000 --- a/include/cru/ui/mapper/style/FocusConditionMapper.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "IConditionMapper.hpp" -#include "cru/ui/style/Condition.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API FocusConditionMapper - : public BasicPtrMapper, - public virtual IConditionMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(FocusConditionMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/HoverConditionMapper.h b/include/cru/ui/mapper/style/HoverConditionMapper.h new file mode 100644 index 00000000..c897f672 --- /dev/null +++ b/include/cru/ui/mapper/style/HoverConditionMapper.h @@ -0,0 +1,26 @@ +#pragma once +#include "../Mapper.h" +#include "IConditionMapper.h" +#include "cru/ui/style/Condition.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API HoverConditionMapper + : public BasicPtrMapper, + public virtual IConditionMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(HoverConditionMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/HoverConditionMapper.hpp b/include/cru/ui/mapper/style/HoverConditionMapper.hpp deleted file mode 100644 index bbd840f0..00000000 --- a/include/cru/ui/mapper/style/HoverConditionMapper.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "IConditionMapper.hpp" -#include "cru/ui/style/Condition.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API HoverConditionMapper - : public BasicPtrMapper, - public virtual IConditionMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(HoverConditionMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/IConditionMapper.h b/include/cru/ui/mapper/style/IConditionMapper.h new file mode 100644 index 00000000..7610dc8d --- /dev/null +++ b/include/cru/ui/mapper/style/IConditionMapper.h @@ -0,0 +1,17 @@ +#pragma once +#include "../../Base.h" +#include "cru/common/ClonablePtr.h" +#include "cru/ui/mapper/Mapper.h" +#include "cru/ui/style/Condition.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper::style { +struct CRU_UI_API IConditionMapper : virtual Interface { + bool XmlElementIsOfThisType(xml::XmlElementNode* node) { + return dynamic_cast(this)->XmlElementIsOfThisType(node); + } + + virtual ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) = 0; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/IConditionMapper.hpp b/include/cru/ui/mapper/style/IConditionMapper.hpp deleted file mode 100644 index 3fa7d10a..00000000 --- a/include/cru/ui/mapper/style/IConditionMapper.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "../../Base.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/ui/mapper/Mapper.hpp" -#include "cru/ui/style/Condition.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper::style { -struct CRU_UI_API IConditionMapper : virtual Interface { - bool XmlElementIsOfThisType(xml::XmlElementNode* node) { - return dynamic_cast(this)->XmlElementIsOfThisType(node); - } - - virtual ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) = 0; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/IStylerMapper.h b/include/cru/ui/mapper/style/IStylerMapper.h new file mode 100644 index 00000000..4c2ecd16 --- /dev/null +++ b/include/cru/ui/mapper/style/IStylerMapper.h @@ -0,0 +1,17 @@ +#pragma once +#include "../../Base.h" +#include "cru/common/ClonablePtr.h" +#include "cru/ui/mapper/Mapper.h" +#include "cru/ui/style/Styler.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper::style { +struct CRU_UI_API IStylerMapper : virtual Interface { + bool XmlElementIsOfThisType(xml::XmlElementNode* node) { + return dynamic_cast(this)->XmlElementIsOfThisType(node); + } + + virtual ClonablePtr MapStylerFromXml( + xml::XmlElementNode* node) = 0; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/IStylerMapper.hpp b/include/cru/ui/mapper/style/IStylerMapper.hpp deleted file mode 100644 index d00f39be..00000000 --- a/include/cru/ui/mapper/style/IStylerMapper.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "../../Base.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/ui/mapper/Mapper.hpp" -#include "cru/ui/style/Styler.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper::style { -struct CRU_UI_API IStylerMapper : virtual Interface { - bool XmlElementIsOfThisType(xml::XmlElementNode* node) { - return dynamic_cast(this)->XmlElementIsOfThisType(node); - } - - virtual ClonablePtr MapStylerFromXml( - xml::XmlElementNode* node) = 0; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/NoConditionMapper.h b/include/cru/ui/mapper/style/NoConditionMapper.h new file mode 100644 index 00000000..bc7ce623 --- /dev/null +++ b/include/cru/ui/mapper/style/NoConditionMapper.h @@ -0,0 +1,29 @@ +#pragma once +#include "../Mapper.h" +#include "IConditionMapper.h" +#include "cru/common/Base.h" +#include "cru/common/ClonablePtr.h" +#include "cru/ui/style/Condition.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API NoConditionMapper + : public BasicPtrMapper, + public virtual IConditionMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(NoConditionMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/NoConditionMapper.hpp b/include/cru/ui/mapper/style/NoConditionMapper.hpp deleted file mode 100644 index ed3a9699..00000000 --- a/include/cru/ui/mapper/style/NoConditionMapper.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "IConditionMapper.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/ui/style/Condition.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API NoConditionMapper - : public BasicPtrMapper, - public virtual IConditionMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(NoConditionMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/OrConditionMapper.h b/include/cru/ui/mapper/style/OrConditionMapper.h new file mode 100644 index 00000000..e93484b4 --- /dev/null +++ b/include/cru/ui/mapper/style/OrConditionMapper.h @@ -0,0 +1,25 @@ +#pragma once +#include "../Mapper.h" +#include "IConditionMapper.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API OrConditionMapper + : public BasicPtrMapper, + public virtual IConditionMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(OrConditionMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + ClonablePtr MapConditionFromXml( + xml::XmlElementNode* node) override { + return MapFromXml(node); + } + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/OrConditionMapper.hpp b/include/cru/ui/mapper/style/OrConditionMapper.hpp deleted file mode 100644 index 21a402c2..00000000 --- a/include/cru/ui/mapper/style/OrConditionMapper.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "IConditionMapper.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API OrConditionMapper - : public BasicPtrMapper, - public virtual IConditionMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(OrConditionMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - ClonablePtr MapConditionFromXml( - xml::XmlElementNode* node) override { - return MapFromXml(node); - } - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/StyleRuleMapper.h b/include/cru/ui/mapper/style/StyleRuleMapper.h new file mode 100644 index 00000000..cba4872c --- /dev/null +++ b/include/cru/ui/mapper/style/StyleRuleMapper.h @@ -0,0 +1,20 @@ +#pragma once +#include "../Mapper.h" +#include "cru/common/ClonablePtr.h" +#include "cru/ui/style/StyleRule.h" +#include "cru/xml/XmlNode.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API StyleRuleMapper : public BasicPtrMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(StyleRuleMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + ClonablePtr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/StyleRuleMapper.hpp b/include/cru/ui/mapper/style/StyleRuleMapper.hpp deleted file mode 100644 index ce5ccf00..00000000 --- a/include/cru/ui/mapper/style/StyleRuleMapper.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "../Mapper.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/ui/style/StyleRule.hpp" -#include "cru/xml/XmlNode.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API StyleRuleMapper : public BasicPtrMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(StyleRuleMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - ClonablePtr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/StyleRuleSetMapper.h b/include/cru/ui/mapper/style/StyleRuleSetMapper.h new file mode 100644 index 00000000..95f745e5 --- /dev/null +++ b/include/cru/ui/mapper/style/StyleRuleSetMapper.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include "../../style/StyleRuleSet.h" +#include "../Mapper.h" + +namespace cru::ui::mapper::style { +class CRU_UI_API StyleRuleSetMapper + : public BasicRefMapper { + public: + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(StyleRuleSetMapper) + + public: + bool SupportMapFromXml() override { return true; } + bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; + + protected: + std::shared_ptr DoMapFromXml( + xml::XmlElementNode* node) override; +}; +; +} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/mapper/style/StyleRuleSetMapper.hpp b/include/cru/ui/mapper/style/StyleRuleSetMapper.hpp deleted file mode 100644 index 66b95f4a..00000000 --- a/include/cru/ui/mapper/style/StyleRuleSetMapper.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "../../style/StyleRuleSet.hpp" -#include "../Mapper.hpp" - -namespace cru::ui::mapper::style { -class CRU_UI_API StyleRuleSetMapper - : public BasicRefMapper { - public: - CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(StyleRuleSetMapper) - - public: - bool SupportMapFromXml() override { return true; } - bool XmlElementIsOfThisType(xml::XmlElementNode* node) override; - - protected: - std::shared_ptr DoMapFromXml( - xml::XmlElementNode* node) override; -}; -; -} // namespace cru::ui::mapper::style diff --git a/include/cru/ui/render/Base.h b/include/cru/ui/render/Base.h new file mode 100644 index 00000000..fca67086 --- /dev/null +++ b/include/cru/ui/render/Base.h @@ -0,0 +1,12 @@ +#pragma once +#include "../Base.h" + +namespace cru::ui::render { +class RenderObject; +class BorderRenderObject; +class CanvasRenderObject; +class FlexLayoutRenderObject; +class ScrollRenderObject; +class StackLayoutRenderObject; +class TextRenderObject; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/Base.hpp b/include/cru/ui/render/Base.hpp deleted file mode 100644 index ac67349e..00000000 --- a/include/cru/ui/render/Base.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../Base.hpp" - -namespace cru::ui::render { -class RenderObject; -class BorderRenderObject; -class CanvasRenderObject; -class FlexLayoutRenderObject; -class ScrollRenderObject; -class StackLayoutRenderObject; -class TextRenderObject; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/BorderRenderObject.h b/include/cru/ui/render/BorderRenderObject.h new file mode 100644 index 00000000..d75a979f --- /dev/null +++ b/include/cru/ui/render/BorderRenderObject.h @@ -0,0 +1,109 @@ +#pragma once +#include +#include "../style/ApplyBorderStyleInfo.h" +#include "RenderObject.h" +#include "cru/platform/GraphicsBase.h" +#include "cru/ui/Base.h" + +namespace cru::ui::render { +class CRU_UI_API BorderRenderObject : public RenderObject { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::BorderRenderObject") + + public: + BorderRenderObject(); + BorderRenderObject(const BorderRenderObject& other) = delete; + BorderRenderObject(BorderRenderObject&& other) = delete; + BorderRenderObject& operator=(const BorderRenderObject& other) = delete; + BorderRenderObject& operator=(BorderRenderObject&& other) = delete; + ~BorderRenderObject() override; + + bool IsBorderEnabled() const { return is_border_enabled_; } + void SetBorderEnabled(bool enabled) { is_border_enabled_ = enabled; } + + std::shared_ptr GetBorderBrush() { + return border_brush_; + } + + void SetBorderBrush(std::shared_ptr brush) { + if (brush == border_brush_) return; + border_brush_ = std::move(brush); + InvalidatePaint(); + } + + Thickness GetBorderThickness() const { return border_thickness_; } + + void SetBorderThickness(const Thickness thickness) { + if (thickness == border_thickness_) return; + border_thickness_ = thickness; + InvalidateLayout(); + } + + CornerRadius GetBorderRadius() { return border_radius_; } + + void SetBorderRadius(const CornerRadius radius) { + if (radius == border_radius_) return; + border_radius_ = radius; + RecreateGeometry(); + } + + std::shared_ptr GetForegroundBrush() { + return foreground_brush_; + } + + void SetForegroundBrush(std::shared_ptr brush) { + if (brush == foreground_brush_) return; + foreground_brush_ = std::move(brush); + InvalidatePaint(); + } + + std::shared_ptr GetBackgroundBrush() { + return background_brush_; + } + + void SetBackgroundBrush(std::shared_ptr brush) { + if (brush == background_brush_) return; + background_brush_ = std::move(brush); + InvalidatePaint(); + } + + void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style); + + RenderObject* HitTest(const Point& point) override; + + Thickness GetOuterSpaceThickness() const override; + Rect GetPaddingRect() const override; + Rect GetContentRect() const override; + + std::u16string_view GetName() const override { return u"BorderRenderObject"; } + + protected: + void OnDrawCore(platform::graphics::IPainter* painter) override; + + Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + void OnAfterLayout() override; + + private: + void RecreateGeometry(); + + private: + bool is_border_enabled_ = false; + + std::shared_ptr border_brush_; + Thickness border_thickness_; + CornerRadius border_radius_; + + std::shared_ptr foreground_brush_; + std::shared_ptr background_brush_; + + // The ring. Used for painting. + std::unique_ptr geometry_; + // Area including inner area of the border. Used for painting foreground and + // background. + std::unique_ptr border_inner_geometry_; + // Area including border ring and inner area. Used for hit test. + std::unique_ptr border_outer_geometry_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/BorderRenderObject.hpp b/include/cru/ui/render/BorderRenderObject.hpp deleted file mode 100644 index bf4b27a1..00000000 --- a/include/cru/ui/render/BorderRenderObject.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once -#include -#include "../style/ApplyBorderStyleInfo.hpp" -#include "RenderObject.hpp" -#include "cru/platform/GraphicsBase.hpp" -#include "cru/ui/Base.hpp" - -namespace cru::ui::render { -class CRU_UI_API BorderRenderObject : public RenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::BorderRenderObject") - - public: - BorderRenderObject(); - BorderRenderObject(const BorderRenderObject& other) = delete; - BorderRenderObject(BorderRenderObject&& other) = delete; - BorderRenderObject& operator=(const BorderRenderObject& other) = delete; - BorderRenderObject& operator=(BorderRenderObject&& other) = delete; - ~BorderRenderObject() override; - - bool IsBorderEnabled() const { return is_border_enabled_; } - void SetBorderEnabled(bool enabled) { is_border_enabled_ = enabled; } - - std::shared_ptr GetBorderBrush() { - return border_brush_; - } - - void SetBorderBrush(std::shared_ptr brush) { - if (brush == border_brush_) return; - border_brush_ = std::move(brush); - InvalidatePaint(); - } - - Thickness GetBorderThickness() const { return border_thickness_; } - - void SetBorderThickness(const Thickness thickness) { - if (thickness == border_thickness_) return; - border_thickness_ = thickness; - InvalidateLayout(); - } - - CornerRadius GetBorderRadius() { return border_radius_; } - - void SetBorderRadius(const CornerRadius radius) { - if (radius == border_radius_) return; - border_radius_ = radius; - RecreateGeometry(); - } - - std::shared_ptr GetForegroundBrush() { - return foreground_brush_; - } - - void SetForegroundBrush(std::shared_ptr brush) { - if (brush == foreground_brush_) return; - foreground_brush_ = std::move(brush); - InvalidatePaint(); - } - - std::shared_ptr GetBackgroundBrush() { - return background_brush_; - } - - void SetBackgroundBrush(std::shared_ptr brush) { - if (brush == background_brush_) return; - background_brush_ = std::move(brush); - InvalidatePaint(); - } - - void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style); - - RenderObject* HitTest(const Point& point) override; - - Thickness GetOuterSpaceThickness() const override; - Rect GetPaddingRect() const override; - Rect GetContentRect() const override; - - std::u16string_view GetName() const override { return u"BorderRenderObject"; } - - protected: - void OnDrawCore(platform::graphics::IPainter* painter) override; - - Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - void OnAfterLayout() override; - - private: - void RecreateGeometry(); - - private: - bool is_border_enabled_ = false; - - std::shared_ptr border_brush_; - Thickness border_thickness_; - CornerRadius border_radius_; - - std::shared_ptr foreground_brush_; - std::shared_ptr background_brush_; - - // The ring. Used for painting. - std::unique_ptr geometry_; - // Area including inner area of the border. Used for painting foreground and - // background. - std::unique_ptr border_inner_geometry_; - // Area including border ring and inner area. Used for hit test. - std::unique_ptr border_outer_geometry_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/CanvasRenderObject.h b/include/cru/ui/render/CanvasRenderObject.h new file mode 100644 index 00000000..ca55ebc6 --- /dev/null +++ b/include/cru/ui/render/CanvasRenderObject.h @@ -0,0 +1,36 @@ +#pragma once +#include "RenderObject.h" + +namespace cru::ui::render { +// Layout logic: +// If no preferred size is set. Then (100, 100) is used and then coerced to +// required range. +class CRU_UI_API CanvasRenderObject : public RenderObject { + public: + CanvasRenderObject(); + + CRU_DELETE_COPY(CanvasRenderObject) + CRU_DELETE_MOVE(CanvasRenderObject) + + ~CanvasRenderObject(); + + public: + RenderObject* HitTest(const Point& point) override; + + Size GetDesiredSize() const { return desired_size_; } + + IEvent* PaintEvent() { return &paint_event_; } + + protected: + void OnDrawContent(platform::graphics::IPainter* painter) override; + + Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + private: + Size desired_size_{}; + + Event paint_event_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/CanvasRenderObject.hpp b/include/cru/ui/render/CanvasRenderObject.hpp deleted file mode 100644 index 68400271..00000000 --- a/include/cru/ui/render/CanvasRenderObject.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "RenderObject.hpp" - -namespace cru::ui::render { -// Layout logic: -// If no preferred size is set. Then (100, 100) is used and then coerced to -// required range. -class CRU_UI_API CanvasRenderObject : public RenderObject { - public: - CanvasRenderObject(); - - CRU_DELETE_COPY(CanvasRenderObject) - CRU_DELETE_MOVE(CanvasRenderObject) - - ~CanvasRenderObject(); - - public: - RenderObject* HitTest(const Point& point) override; - - Size GetDesiredSize() const { return desired_size_; } - - IEvent* PaintEvent() { return &paint_event_; } - - protected: - void OnDrawContent(platform::graphics::IPainter* painter) override; - - Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - private: - Size desired_size_{}; - - Event paint_event_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/FlexLayoutRenderObject.h b/include/cru/ui/render/FlexLayoutRenderObject.h new file mode 100644 index 00000000..3a8348f6 --- /dev/null +++ b/include/cru/ui/render/FlexLayoutRenderObject.h @@ -0,0 +1,120 @@ +#pragma once +#include "LayoutRenderObject.h" + +#include + +namespace cru::ui::render { +// Measure Logic (v0.1): +// Cross axis measure logic is the same as stack layout. +// +// 1. Layout all children with unspecified(infinate) max main axis length. +// +// 2. Add up main axis length of children to get total main length. +// +// 2.1. If preferred main axis length of parent is specified, then compare +// total length with it. If bigger, shrink is performed. If smaller, expand is +// performed. And preferred main axis length is used as target length. +// +// 2.2. If preferred main axis length of parent is not specified. +// +// 2.2.1. If max main axis length is specified and total length is bigger +// than max main axis length, shrink is performed and max main axis length is +// used as target length. +// +// 2.2.2. Or if max main axis length is specified and total length is smaller +// than max main axis length and any child has a positive expand factor, then +// expand is performed and max main axis length is used as target length. +// +// 2.2.3. Or if min main axis length is specified and total length is smaller +// than min main axis length, expand is performed and min main axis length is +// used as target length. +// +// 3. If shrink or expand is needed, then +// +// 3.1. Shrink: +// +// 3.1.1. Find out all shrink_factor > 0 children to form a adjusting list. +// +// 3.1.2. Use total main length minus target length to get the total shrink +// length. Add up all shrink_factor in adjusting list to get total shrink +// factor. +// +// 3.1.3. Iterate all children in adjusting list: +// +// 3.1.3.1. Calculate its own shrink length as +// shrink_factor / total_shrink_factor * total_shrink_length . +// Use current main axis length of child minus shrink length to get new +// measure length. +// +// 3.1.3.2. If min main axis length of the child is specified and new +// measure length is less than it, then min main axis length is used as new +// measure length. +// +// 3.1.3.3. Or if new measure length is less than 0, then it is coerced to +// 0. +// +// 3.1.3.4. Call measure with max and preferred main axis length set to new +// measure length. Cross axis length requirement is the same as step 1. +// +// 3.1.3.5. After measure, if it has min main axis length specified and +// actual main axis length is equal to it or its actual main axis length is +// 0, then remove it from adjusting list. +// +// 3.1.4. Add up main axis length of children to update total main length. If +// total main length is less than or equal to target length, goto step 4. +// +// 3.1.4. If adjusting list is not empty, go to step 3.1.2. +// +// 3.2. Expand: +// The same as shrink after you exchange related things except some minor +// things like do not do special things on 0. +// +// 4. If final total main axis length exceeeds the max main axis length (if +// specified), then report an error. And result main axis length is the coerced +// length. If final total main axis length is smaller than min main axis length +// (if specified), then coerce the length to the min value but not report error +// and just fill the rest space with blank. +// +class CRU_UI_API FlexLayoutRenderObject : public LayoutRenderObject { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::FlexLayoutRenderObject") + + public: + FlexLayoutRenderObject() = default; + FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete; + FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) = + delete; + FlexLayoutRenderObject(FlexLayoutRenderObject&& other) = delete; + FlexLayoutRenderObject& operator=(FlexLayoutRenderObject&& other) = delete; + ~FlexLayoutRenderObject() override = default; + + std::u16string_view GetName() const override; + + FlexDirection GetFlexDirection() const { return direction_; } + void SetFlexDirection(FlexDirection direction) { + direction_ = direction; + InvalidateLayout(); + } + + FlexMainAlignment GetContentMainAlign() const { return content_main_align_; } + void SetContentMainAlign(FlexMainAlignment align) { + content_main_align_ = align; + InvalidateLayout(); + } + + FlexCrossAlignment GetItemCrossAlign() const { return item_cross_align_; } + void SetItemCrossAlign(FlexCrossAlignment align) { + item_cross_align_ = align; + InvalidateLayout(); + } + + protected: + Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + private: + FlexDirection direction_ = FlexDirection::Horizontal; + FlexMainAlignment content_main_align_ = FlexMainAlignment::Start; + FlexCrossAlignment item_cross_align_ = FlexCrossAlignment::Center; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/FlexLayoutRenderObject.hpp b/include/cru/ui/render/FlexLayoutRenderObject.hpp deleted file mode 100644 index c6fb7211..00000000 --- a/include/cru/ui/render/FlexLayoutRenderObject.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once -#include "LayoutRenderObject.hpp" - -#include - -namespace cru::ui::render { -// Measure Logic (v0.1): -// Cross axis measure logic is the same as stack layout. -// -// 1. Layout all children with unspecified(infinate) max main axis length. -// -// 2. Add up main axis length of children to get total main length. -// -// 2.1. If preferred main axis length of parent is specified, then compare -// total length with it. If bigger, shrink is performed. If smaller, expand is -// performed. And preferred main axis length is used as target length. -// -// 2.2. If preferred main axis length of parent is not specified. -// -// 2.2.1. If max main axis length is specified and total length is bigger -// than max main axis length, shrink is performed and max main axis length is -// used as target length. -// -// 2.2.2. Or if max main axis length is specified and total length is smaller -// than max main axis length and any child has a positive expand factor, then -// expand is performed and max main axis length is used as target length. -// -// 2.2.3. Or if min main axis length is specified and total length is smaller -// than min main axis length, expand is performed and min main axis length is -// used as target length. -// -// 3. If shrink or expand is needed, then -// -// 3.1. Shrink: -// -// 3.1.1. Find out all shrink_factor > 0 children to form a adjusting list. -// -// 3.1.2. Use total main length minus target length to get the total shrink -// length. Add up all shrink_factor in adjusting list to get total shrink -// factor. -// -// 3.1.3. Iterate all children in adjusting list: -// -// 3.1.3.1. Calculate its own shrink length as -// shrink_factor / total_shrink_factor * total_shrink_length . -// Use current main axis length of child minus shrink length to get new -// measure length. -// -// 3.1.3.2. If min main axis length of the child is specified and new -// measure length is less than it, then min main axis length is used as new -// measure length. -// -// 3.1.3.3. Or if new measure length is less than 0, then it is coerced to -// 0. -// -// 3.1.3.4. Call measure with max and preferred main axis length set to new -// measure length. Cross axis length requirement is the same as step 1. -// -// 3.1.3.5. After measure, if it has min main axis length specified and -// actual main axis length is equal to it or its actual main axis length is -// 0, then remove it from adjusting list. -// -// 3.1.4. Add up main axis length of children to update total main length. If -// total main length is less than or equal to target length, goto step 4. -// -// 3.1.4. If adjusting list is not empty, go to step 3.1.2. -// -// 3.2. Expand: -// The same as shrink after you exchange related things except some minor -// things like do not do special things on 0. -// -// 4. If final total main axis length exceeeds the max main axis length (if -// specified), then report an error. And result main axis length is the coerced -// length. If final total main axis length is smaller than min main axis length -// (if specified), then coerce the length to the min value but not report error -// and just fill the rest space with blank. -// -class CRU_UI_API FlexLayoutRenderObject : public LayoutRenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::FlexLayoutRenderObject") - - public: - FlexLayoutRenderObject() = default; - FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete; - FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) = - delete; - FlexLayoutRenderObject(FlexLayoutRenderObject&& other) = delete; - FlexLayoutRenderObject& operator=(FlexLayoutRenderObject&& other) = delete; - ~FlexLayoutRenderObject() override = default; - - std::u16string_view GetName() const override; - - FlexDirection GetFlexDirection() const { return direction_; } - void SetFlexDirection(FlexDirection direction) { - direction_ = direction; - InvalidateLayout(); - } - - FlexMainAlignment GetContentMainAlign() const { return content_main_align_; } - void SetContentMainAlign(FlexMainAlignment align) { - content_main_align_ = align; - InvalidateLayout(); - } - - FlexCrossAlignment GetItemCrossAlign() const { return item_cross_align_; } - void SetItemCrossAlign(FlexCrossAlignment align) { - item_cross_align_ = align; - InvalidateLayout(); - } - - protected: - Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - private: - FlexDirection direction_ = FlexDirection::Horizontal; - FlexMainAlignment content_main_align_ = FlexMainAlignment::Start; - FlexCrossAlignment item_cross_align_ = FlexCrossAlignment::Center; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/LayoutHelper.h b/include/cru/ui/render/LayoutHelper.h new file mode 100644 index 00000000..c2377066 --- /dev/null +++ b/include/cru/ui/render/LayoutHelper.h @@ -0,0 +1,14 @@ +#pragma once +#include "Base.h" + +#include "MeasureRequirement.h" + +namespace cru::ui::render { +float CalculateAnchorByAlignment(Alignment alignment, float start_point, + float content_length, float child_length); + +MeasureLength StackLayoutCalculateChildMaxLength( + MeasureLength parent_preferred_size, MeasureLength parent_max_size, + MeasureLength child_min_size, std::u16string_view log_tag, + std::u16string_view exceeds_message); +} // namespace cru::ui::render diff --git a/include/cru/ui/render/LayoutHelper.hpp b/include/cru/ui/render/LayoutHelper.hpp deleted file mode 100644 index 518dc5a3..00000000 --- a/include/cru/ui/render/LayoutHelper.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "MeasureRequirement.hpp" - -namespace cru::ui::render { -float CalculateAnchorByAlignment(Alignment alignment, float start_point, - float content_length, float child_length); - -MeasureLength StackLayoutCalculateChildMaxLength( - MeasureLength parent_preferred_size, MeasureLength parent_max_size, - MeasureLength child_min_size, std::u16string_view log_tag, - std::u16string_view exceeds_message); -} // namespace cru::ui::render diff --git a/include/cru/ui/render/LayoutRenderObject.h b/include/cru/ui/render/LayoutRenderObject.h new file mode 100644 index 00000000..42a3aa55 --- /dev/null +++ b/include/cru/ui/render/LayoutRenderObject.h @@ -0,0 +1,86 @@ +#pragma once +#include "RenderObject.h" + +#include "cru/platform/graphics/util/Painter.h" + +namespace cru::ui::render { +template +class CRU_UI_API LayoutRenderObject : public RenderObject { + public: + using ChildLayoutData = TChildLayoutData; + + protected: + LayoutRenderObject() : RenderObject(ChildMode::Multiple) {} + + public: + CRU_DELETE_COPY(LayoutRenderObject) + CRU_DELETE_MOVE(LayoutRenderObject) + + ~LayoutRenderObject() override = default; + + const std::vector& GetChildLayoutDataList() const { + return this->child_layout_data_; + } + + void SetChildLayoutData(Index position, ChildLayoutData data) { + Expects(position >= 0 && + position < static_cast(this->child_layout_data_.size())); + this->child_layout_data_[position] = std::move(data); + this->InvalidateLayout(); + } + + const ChildLayoutData& GetChildLayoutData(Index position) const { + Expects(position >= 0 && + position < static_cast(this->child_layout_data_.size())); + return this->child_layout_data_[position]; + } + + RenderObject* HitTest(const Point& point) override; + + protected: + void OnAddChild(RenderObject* new_child, Index position) override; + void OnRemoveChild(RenderObject* removed_child, Index position) override; + + private: + std::vector child_layout_data_{}; +}; + +template +RenderObject* LayoutRenderObject::HitTest( + const Point& point) { + const auto& children = GetChildren(); + for (auto i = children.crbegin(); i != children.crend(); ++i) { + auto offset = (*i)->GetOffset(); + Point p{point.x - offset.x, point.y - offset.y}; + const auto result = (*i)->HitTest(p); + if (result != nullptr) { + return result; + } + } + + const auto margin = GetMargin(); + const auto size = GetSize(); + return Rect{margin.left, margin.top, + std::max(size.width - margin.GetHorizontalTotal(), 0.0f), + std::max(size.height - margin.GetVerticalTotal(), 0.0f)} + .IsPointInside(point) + ? this + : nullptr; +} // namespace cru::ui::render + +template +void LayoutRenderObject::OnAddChild(RenderObject* new_child, + const Index position) { + CRU_UNUSED(new_child) + + child_layout_data_.emplace(child_layout_data_.cbegin() + position); +} + +template +void LayoutRenderObject::OnRemoveChild( + RenderObject* removed_child, const Index position) { + CRU_UNUSED(removed_child) + + child_layout_data_.erase(child_layout_data_.cbegin() + position); +} +} // namespace cru::ui::render diff --git a/include/cru/ui/render/LayoutRenderObject.hpp b/include/cru/ui/render/LayoutRenderObject.hpp deleted file mode 100644 index 424a5831..00000000 --- a/include/cru/ui/render/LayoutRenderObject.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once -#include "RenderObject.hpp" - -#include "cru/platform/graphics/util/Painter.hpp" - -namespace cru::ui::render { -template -class CRU_UI_API LayoutRenderObject : public RenderObject { - public: - using ChildLayoutData = TChildLayoutData; - - protected: - LayoutRenderObject() : RenderObject(ChildMode::Multiple) {} - - public: - CRU_DELETE_COPY(LayoutRenderObject) - CRU_DELETE_MOVE(LayoutRenderObject) - - ~LayoutRenderObject() override = default; - - const std::vector& GetChildLayoutDataList() const { - return this->child_layout_data_; - } - - void SetChildLayoutData(Index position, ChildLayoutData data) { - Expects(position >= 0 && - position < static_cast(this->child_layout_data_.size())); - this->child_layout_data_[position] = std::move(data); - this->InvalidateLayout(); - } - - const ChildLayoutData& GetChildLayoutData(Index position) const { - Expects(position >= 0 && - position < static_cast(this->child_layout_data_.size())); - return this->child_layout_data_[position]; - } - - RenderObject* HitTest(const Point& point) override; - - protected: - void OnAddChild(RenderObject* new_child, Index position) override; - void OnRemoveChild(RenderObject* removed_child, Index position) override; - - private: - std::vector child_layout_data_{}; -}; - -template -RenderObject* LayoutRenderObject::HitTest( - const Point& point) { - const auto& children = GetChildren(); - for (auto i = children.crbegin(); i != children.crend(); ++i) { - auto offset = (*i)->GetOffset(); - Point p{point.x - offset.x, point.y - offset.y}; - const auto result = (*i)->HitTest(p); - if (result != nullptr) { - return result; - } - } - - const auto margin = GetMargin(); - const auto size = GetSize(); - return Rect{margin.left, margin.top, - std::max(size.width - margin.GetHorizontalTotal(), 0.0f), - std::max(size.height - margin.GetVerticalTotal(), 0.0f)} - .IsPointInside(point) - ? this - : nullptr; -} // namespace cru::ui::render - -template -void LayoutRenderObject::OnAddChild(RenderObject* new_child, - const Index position) { - CRU_UNUSED(new_child) - - child_layout_data_.emplace(child_layout_data_.cbegin() + position); -} - -template -void LayoutRenderObject::OnRemoveChild( - RenderObject* removed_child, const Index position) { - CRU_UNUSED(removed_child) - - child_layout_data_.erase(child_layout_data_.cbegin() + position); -} -} // namespace cru::ui::render diff --git a/include/cru/ui/render/MeasureRequirement.h b/include/cru/ui/render/MeasureRequirement.h new file mode 100644 index 00000000..c740385b --- /dev/null +++ b/include/cru/ui/render/MeasureRequirement.h @@ -0,0 +1,251 @@ +#pragma once +#include "Base.h" + +#include "cru/common/String.h" + +#include +#include +#include + +namespace cru::ui::render { +constexpr Size Min(const Size& left, const Size& right) { + return Size{std::min(left.width, right.width), + std::min(left.height, right.height)}; +} + +constexpr Size Max(const Size& left, const Size& right) { + return Size{std::max(left.width, right.width), + std::max(left.height, right.height)}; +} + +class MeasureLength final { + public: + struct tag_not_specify_t {}; + constexpr static tag_not_specify_t tag_not_specify{}; + + constexpr MeasureLength() : MeasureLength(tag_not_specify) {} + constexpr MeasureLength(tag_not_specify_t) : length_(-1) {} + constexpr MeasureLength(float length) : length_(length) { + Expects(length >= 0); + } + + MeasureLength(const MeasureLength& other) = default; + constexpr MeasureLength& operator=(const MeasureLength& other) = default; + constexpr MeasureLength& operator=(float length) { + Expects(length >= 0); + length_ = length; + return *this; + } + + ~MeasureLength() = default; + + constexpr static MeasureLength NotSpecified() { + return MeasureLength{tag_not_specify}; + } + + constexpr bool IsSpecified() const { return length_ >= 0.0f; } + + // What not specified means depends on situation. + constexpr bool IsNotSpecified() const { return length_ < 0.0f; } + + constexpr float GetLengthOr(float value) const { + return length_ < 0 ? value : length_; + } + + // If not specify max value of float is returned. + constexpr float GetLengthOrMax() const { + return GetLengthOr(std::numeric_limits::max()); + } + + // If not specify 0 is returned. + constexpr float GetLengthOr0() const { return GetLengthOr(0.f); } + + // If not specify, return value is undefined. + constexpr float GetLengthOrUndefined() const { return length_; } + + // Not operator overload because this semantics is not very clear. + constexpr MeasureLength Plus(float length) const { + if (IsSpecified()) + return length_ + length; + else + return NotSpecified(); + } + + // Not operator overload because this semantics is not very clear. + constexpr MeasureLength Minus(float length) const { + if (IsSpecified()) + return std::max(length_ - length, 0.f); + else + return NotSpecified(); + } + + constexpr bool operator==(MeasureLength other) const { + return (length_ < 0 && other.length_ < 0) || length_ == other.length_; + } + + constexpr bool operator!=(MeasureLength other) const { + return !operator==(other); + } + + constexpr static MeasureLength Min(MeasureLength left, MeasureLength right) { + if (left.IsNotSpecified()) { + if (right.IsNotSpecified()) + return NotSpecified(); + else + return right; + } else { + if (right.IsNotSpecified()) + return left; + else + return std::min(left.length_, right.length_); + } + } + + constexpr static MeasureLength Max(MeasureLength left, MeasureLength right) { + if (left.IsNotSpecified()) { + if (right.IsNotSpecified()) + return NotSpecified(); + else + return right; + } else { + if (left.IsNotSpecified()) + return left; + else + return std::max(left.length_, right.length_); + } + } + + String ToDebugString() const { + return IsSpecified() ? ToString(GetLengthOrUndefined()) : u"UNSPECIFIED"; + } + + private: + // -1 for not specify + float length_; +}; + +struct MeasureSize { + MeasureLength width; + MeasureLength height; + + constexpr MeasureSize() = default; + constexpr MeasureSize(MeasureLength width, MeasureLength height) + : width(width), height(height) {} + constexpr MeasureSize(const Size& size) + : width(size.width), height(size.height) {} + constexpr MeasureSize(const MeasureSize& other) = default; + + MeasureSize& operator=(const MeasureSize& other) = default; + constexpr MeasureSize& operator=(const Size& other) { + width = other.width; + height = other.height; + return *this; + } + + constexpr Size GetSizeOrMax() const { + return Size{width.GetLengthOrMax(), height.GetLengthOrMax()}; + } + + constexpr Size GetSizeOr0() const { + return Size{width.GetLengthOr0(), height.GetLengthOr0()}; + } + + constexpr MeasureSize Plus(const Size& size) const { + return MeasureSize{width.Plus(size.width), height.Plus(size.height)}; + } + + constexpr MeasureSize Minus(const Size& size) const { + return MeasureSize{width.Minus(size.width), height.Minus(size.height)}; + } + + constexpr MeasureSize OverrideBy(const MeasureSize& size) const { + return MeasureSize{ + size.width.IsSpecified() ? size.width.GetLengthOrUndefined() + : this->width, + size.height.IsSpecified() ? size.height.GetLengthOrUndefined() + : this->height, + }; + } + + String ToDebugString() const { + return Format(u"({}, {})", width.ToDebugString(), height.ToDebugString()); + } + + constexpr static MeasureSize NotSpecified() { + return MeasureSize{MeasureLength::NotSpecified(), + MeasureLength::NotSpecified()}; + } + + constexpr static MeasureSize Min(const MeasureSize& left, + const MeasureSize& right) { + return MeasureSize{MeasureLength::Min(left.width, right.width), + MeasureLength::Min(left.height, right.height)}; + } + + constexpr static MeasureSize Max(const MeasureSize& left, + const MeasureSize& right) { + return MeasureSize{MeasureLength::Max(left.width, right.width), + MeasureLength::Max(left.height, right.height)}; + } +}; + +struct MeasureRequirement { + MeasureSize max; + MeasureSize min; + + constexpr MeasureRequirement() = default; + constexpr MeasureRequirement(const MeasureSize& max, const MeasureSize& min) + : max(max), min(min) {} + + constexpr bool Satisfy(const Size& size) const { + auto normalized = Normalize(); + return normalized.max.width.GetLengthOrMax() >= size.width && + normalized.max.height.GetLengthOrMax() >= size.height && + normalized.min.width.GetLengthOr0() <= size.width && + normalized.min.height.GetLengthOr0() <= size.height; + } + + constexpr MeasureRequirement Normalize() const { + MeasureRequirement result = *this; + if (result.min.width.GetLengthOr0() > result.max.width.GetLengthOrMax()) + result.min.width = result.max.width; + + if (result.min.height.GetLengthOr0() > result.max.height.GetLengthOrMax()) + result.min.height = result.max.height; + return result; + } + + constexpr Size Coerce(const Size& size) const { + // This order guarentees result is the same as normalized. + return Min(Max(size, min.GetSizeOr0()), max.GetSizeOrMax()); + } + + constexpr MeasureSize Coerce(const MeasureSize& size) const { + MeasureSize result = size; + if (result.width.IsSpecified()) + // This order guarentees result is the same as normalized. + result.width = std::min(std::max(min.width.GetLengthOr0(), + result.width.GetLengthOrUndefined()), + max.width.GetLengthOrMax()); + + if (result.height.IsSpecified()) + // This order guarentees result is the same as normalized. + result.height = std::min(std::max(min.height.GetLengthOr0(), + result.height.GetLengthOrUndefined()), + max.height.GetLengthOrMax()); + + return result; + } + + String ToDebugString() const { + return Format(u"{{min: {}, max: {}}}", min.ToDebugString(), + max.ToDebugString()); + } + + constexpr static MeasureRequirement Merge(const MeasureRequirement& left, + const MeasureRequirement& right) { + return MeasureRequirement{MeasureSize::Min(left.max, right.max), + MeasureSize::Max(left.min, right.min)}; + } +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/MeasureRequirement.hpp b/include/cru/ui/render/MeasureRequirement.hpp deleted file mode 100644 index 90d02a02..00000000 --- a/include/cru/ui/render/MeasureRequirement.hpp +++ /dev/null @@ -1,251 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/String.hpp" - -#include -#include -#include - -namespace cru::ui::render { -constexpr Size Min(const Size& left, const Size& right) { - return Size{std::min(left.width, right.width), - std::min(left.height, right.height)}; -} - -constexpr Size Max(const Size& left, const Size& right) { - return Size{std::max(left.width, right.width), - std::max(left.height, right.height)}; -} - -class MeasureLength final { - public: - struct tag_not_specify_t {}; - constexpr static tag_not_specify_t tag_not_specify{}; - - constexpr MeasureLength() : MeasureLength(tag_not_specify) {} - constexpr MeasureLength(tag_not_specify_t) : length_(-1) {} - constexpr MeasureLength(float length) : length_(length) { - Expects(length >= 0); - } - - MeasureLength(const MeasureLength& other) = default; - constexpr MeasureLength& operator=(const MeasureLength& other) = default; - constexpr MeasureLength& operator=(float length) { - Expects(length >= 0); - length_ = length; - return *this; - } - - ~MeasureLength() = default; - - constexpr static MeasureLength NotSpecified() { - return MeasureLength{tag_not_specify}; - } - - constexpr bool IsSpecified() const { return length_ >= 0.0f; } - - // What not specified means depends on situation. - constexpr bool IsNotSpecified() const { return length_ < 0.0f; } - - constexpr float GetLengthOr(float value) const { - return length_ < 0 ? value : length_; - } - - // If not specify max value of float is returned. - constexpr float GetLengthOrMax() const { - return GetLengthOr(std::numeric_limits::max()); - } - - // If not specify 0 is returned. - constexpr float GetLengthOr0() const { return GetLengthOr(0.f); } - - // If not specify, return value is undefined. - constexpr float GetLengthOrUndefined() const { return length_; } - - // Not operator overload because this semantics is not very clear. - constexpr MeasureLength Plus(float length) const { - if (IsSpecified()) - return length_ + length; - else - return NotSpecified(); - } - - // Not operator overload because this semantics is not very clear. - constexpr MeasureLength Minus(float length) const { - if (IsSpecified()) - return std::max(length_ - length, 0.f); - else - return NotSpecified(); - } - - constexpr bool operator==(MeasureLength other) const { - return (length_ < 0 && other.length_ < 0) || length_ == other.length_; - } - - constexpr bool operator!=(MeasureLength other) const { - return !operator==(other); - } - - constexpr static MeasureLength Min(MeasureLength left, MeasureLength right) { - if (left.IsNotSpecified()) { - if (right.IsNotSpecified()) - return NotSpecified(); - else - return right; - } else { - if (right.IsNotSpecified()) - return left; - else - return std::min(left.length_, right.length_); - } - } - - constexpr static MeasureLength Max(MeasureLength left, MeasureLength right) { - if (left.IsNotSpecified()) { - if (right.IsNotSpecified()) - return NotSpecified(); - else - return right; - } else { - if (left.IsNotSpecified()) - return left; - else - return std::max(left.length_, right.length_); - } - } - - String ToDebugString() const { - return IsSpecified() ? ToString(GetLengthOrUndefined()) : u"UNSPECIFIED"; - } - - private: - // -1 for not specify - float length_; -}; - -struct MeasureSize { - MeasureLength width; - MeasureLength height; - - constexpr MeasureSize() = default; - constexpr MeasureSize(MeasureLength width, MeasureLength height) - : width(width), height(height) {} - constexpr MeasureSize(const Size& size) - : width(size.width), height(size.height) {} - constexpr MeasureSize(const MeasureSize& other) = default; - - MeasureSize& operator=(const MeasureSize& other) = default; - constexpr MeasureSize& operator=(const Size& other) { - width = other.width; - height = other.height; - return *this; - } - - constexpr Size GetSizeOrMax() const { - return Size{width.GetLengthOrMax(), height.GetLengthOrMax()}; - } - - constexpr Size GetSizeOr0() const { - return Size{width.GetLengthOr0(), height.GetLengthOr0()}; - } - - constexpr MeasureSize Plus(const Size& size) const { - return MeasureSize{width.Plus(size.width), height.Plus(size.height)}; - } - - constexpr MeasureSize Minus(const Size& size) const { - return MeasureSize{width.Minus(size.width), height.Minus(size.height)}; - } - - constexpr MeasureSize OverrideBy(const MeasureSize& size) const { - return MeasureSize{ - size.width.IsSpecified() ? size.width.GetLengthOrUndefined() - : this->width, - size.height.IsSpecified() ? size.height.GetLengthOrUndefined() - : this->height, - }; - } - - String ToDebugString() const { - return Format(u"({}, {})", width.ToDebugString(), height.ToDebugString()); - } - - constexpr static MeasureSize NotSpecified() { - return MeasureSize{MeasureLength::NotSpecified(), - MeasureLength::NotSpecified()}; - } - - constexpr static MeasureSize Min(const MeasureSize& left, - const MeasureSize& right) { - return MeasureSize{MeasureLength::Min(left.width, right.width), - MeasureLength::Min(left.height, right.height)}; - } - - constexpr static MeasureSize Max(const MeasureSize& left, - const MeasureSize& right) { - return MeasureSize{MeasureLength::Max(left.width, right.width), - MeasureLength::Max(left.height, right.height)}; - } -}; - -struct MeasureRequirement { - MeasureSize max; - MeasureSize min; - - constexpr MeasureRequirement() = default; - constexpr MeasureRequirement(const MeasureSize& max, const MeasureSize& min) - : max(max), min(min) {} - - constexpr bool Satisfy(const Size& size) const { - auto normalized = Normalize(); - return normalized.max.width.GetLengthOrMax() >= size.width && - normalized.max.height.GetLengthOrMax() >= size.height && - normalized.min.width.GetLengthOr0() <= size.width && - normalized.min.height.GetLengthOr0() <= size.height; - } - - constexpr MeasureRequirement Normalize() const { - MeasureRequirement result = *this; - if (result.min.width.GetLengthOr0() > result.max.width.GetLengthOrMax()) - result.min.width = result.max.width; - - if (result.min.height.GetLengthOr0() > result.max.height.GetLengthOrMax()) - result.min.height = result.max.height; - return result; - } - - constexpr Size Coerce(const Size& size) const { - // This order guarentees result is the same as normalized. - return Min(Max(size, min.GetSizeOr0()), max.GetSizeOrMax()); - } - - constexpr MeasureSize Coerce(const MeasureSize& size) const { - MeasureSize result = size; - if (result.width.IsSpecified()) - // This order guarentees result is the same as normalized. - result.width = std::min(std::max(min.width.GetLengthOr0(), - result.width.GetLengthOrUndefined()), - max.width.GetLengthOrMax()); - - if (result.height.IsSpecified()) - // This order guarentees result is the same as normalized. - result.height = std::min(std::max(min.height.GetLengthOr0(), - result.height.GetLengthOrUndefined()), - max.height.GetLengthOrMax()); - - return result; - } - - String ToDebugString() const { - return Format(u"{{min: {}, max: {}}}", min.ToDebugString(), - max.ToDebugString()); - } - - constexpr static MeasureRequirement Merge(const MeasureRequirement& left, - const MeasureRequirement& right) { - return MeasureRequirement{MeasureSize::Min(left.max, right.max), - MeasureSize::Max(left.min, right.min)}; - } -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/RenderObject.h b/include/cru/ui/render/RenderObject.h new file mode 100644 index 00000000..1e47e7fc --- /dev/null +++ b/include/cru/ui/render/RenderObject.h @@ -0,0 +1,240 @@ +#pragma once +#include "Base.h" + +#include "MeasureRequirement.h" +#include "cru/common/Base.h" +#include "cru/common/Event.h" +#include "cru/ui/Base.h" + +#include +#include +#include + +namespace cru::ui::render { +// Render object will not destroy its children when destroyed. Control must +// manage lifecycle of its render objects. Since control will destroy its +// children when destroyed, render objects will be destroyed along with it. +// +// About layout: +// Render object should be able to deal with arbitrary size as the result of +// measure and layout. +// +// Parent may pass calculated preferred size down. But the preferred size set on +// child itself takes precedence. +// +// Each render object should obey the measure requirement to set size and report +// a warning when that requirement can't be satisfied with probably bigger size +// of children than that of itself and optional visual effect to indicate that. +// +// If size of chilren are less than min size requirement, then render object +// should try to fill the rest area. If size of children are more than max size +// requirement, then render object should display a warning of the layout +// problem and use the max size of itself with children exceeding its bound. +// (Or better you could use some visual effect to indicate that.) +// +// To write a custom RenderObject, override following methods: +// public: +// void Draw(platform::graphics::IPainter* painter) override; +// RenderObject* HitTest(const Point& point) override; +// protected: +// Size OnMeasureContent(const MeasureRequirement& requirement) override; +// void OnLayoutContent(const Rect& content_rect) override; +class CRU_UI_API RenderObject : public Object { + friend host::WindowHost; + + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::RenderObject") + + protected: + enum class ChildMode { + None, + Single, + Multiple, + }; + + RenderObject() = default; + RenderObject(ChildMode child_mode) : RenderObject() { + SetChildMode(child_mode); + } + + public: + RenderObject(const RenderObject& other) = delete; + RenderObject(RenderObject&& other) = delete; + RenderObject& operator=(const RenderObject& other) = delete; + RenderObject& operator=(RenderObject&& other) = delete; + ~RenderObject() override = default; + + controls::Control* GetAttachedControl() const { return control_; } + void SetAttachedControl(controls::Control* new_control); + + host::WindowHost* GetWindowHost() const { return window_host_; } + + RenderObject* GetParent() const { return parent_; } + + const std::vector& GetChildren() const { return children_; } + Index GetChildCount() const { return static_cast(children_.size()); } + void AddChild(RenderObject* render_object, Index position); + void RemoveChild(Index position); + + RenderObject* GetFirstChild() const; + void TraverseDescendants(const std::function& action); + + // Offset from parent's lefttop to lefttop of this render object. Margin is + // accounted for. + Point GetOffset() const { return offset_; } + Size GetSize() const { return size_; } + Point GetTotalOffset() const; + Point FromRootToContent(const Point& point) const; + + Thickness GetMargin() const { return margin_; } + void SetMargin(const Thickness& margin) { + margin_ = margin; + InvalidateLayout(); + } + + Thickness GetPadding() const { return padding_; } + void SetPadding(const Thickness& padding) { + padding_ = padding; + InvalidateLayout(); + } + + MeasureSize GetPreferredSize() const { return preferred_size_; } + void SetPreferredSize(const MeasureSize& preferred_size) { + preferred_size_ = preferred_size; + InvalidateLayout(); + } + + MeasureSize GetMinSize() const { return custom_measure_requirement_.min; } + void SetMinSize(const MeasureSize& min_size) { + custom_measure_requirement_.min = min_size; + InvalidateLayout(); + } + + MeasureSize GetMaxSize() const { return custom_measure_requirement_.max; } + void SetMaxSize(const MeasureSize& max_size) { + custom_measure_requirement_.max = max_size; + InvalidateLayout(); + } + + MeasureRequirement GetCustomMeasureRequirement() const { + return custom_measure_requirement_; + } + + // This method will merge requirement passed by argument and requirement of + // the render object using MeasureRequirement::Merge and then call + // MeasureRequirement::Normalize on it. And it will use preferred size of the + // render object to override the one passed by argument. Then pass the two to + // OnMeasureCore and use the return value of it to set the size of this render + // object. This can be called multiple times on children during measure to + // adjust for better size. + void Measure(const MeasureRequirement& requirement, + const MeasureSize& preferred_size); + // This will set offset of this render object and call OnLayoutCore. + void Layout(const Point& offset); + + virtual Thickness GetOuterSpaceThickness() const; + virtual Rect GetPaddingRect() const; + virtual Rect GetContentRect() const; + + void Draw(platform::graphics::IPainter* painter); + + // Param point must be relative the lefttop of render object including margin. + // Add offset before pass point to children. + virtual RenderObject* HitTest(const Point& point) = 0; + + IEvent* AttachToHostEvent() { + return &attach_to_host_event_; + } + IEvent* DetachFromHostEvent() { + return &detach_from_host_event_; + } + + public: + void InvalidateLayout(); + void InvalidatePaint(); + + public: + virtual std::u16string_view GetName() const; + std::u16string GetDebugPathInTree() const; + + protected: + void SetChildMode(ChildMode mode) { child_mode_ = mode; } + + protected: + RenderObject* GetSingleChild() const; + + virtual void OnParentChanged(RenderObject* old_parent, + RenderObject* new_parent); + + // default is to invalidate both layout and paint + virtual void OnAddChild(RenderObject* new_child, Index position); + // default is to invalidate both layout and paint + virtual void OnRemoveChild(RenderObject* removed_child, Index position); + + // Draw all children with offset. + void DefaultDrawChildren(platform::graphics::IPainter* painter); + + // Draw all children with translation of content rect lefttop. + void DefaultDrawContent(platform::graphics::IPainter* painter); + + // Call DefaultDrawContent. Then call DefaultDrawChildren. + virtual void OnDrawCore(platform::graphics::IPainter* painter); + + virtual void OnDrawContent(platform::graphics::IPainter* painter); + + // Size measure including margin and padding. Please reduce margin and padding + // or other custom things and pass the result content measure requirement and + // preferred size to OnMeasureContent. Return value must not be negative and + // must obey requirement. + // Note: Implementation should coerce the preferred size into the requirement + // when pass them to OnMeasureContent. + virtual Size OnMeasureCore(const MeasureRequirement& requirement, + const MeasureSize& preferred_size); + + // Please reduce margin and padding or other custom things and pass the result + // content rect to OnLayoutContent. + virtual void OnLayoutCore(); + + // Override this function to measure content and children(Call Measure on + // them). Do not consider margin or padding in this method because they are + // already considered in OnMeasureCore. Returned size must obey requirement. + // Caller should guarantee preferred_size is corerced into required range. + virtual Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) = 0; + + // Layout all content and children(Call Layout on them). + // Lefttop of content_rect should be added when calculated children's offset. + virtual void OnLayoutContent(const Rect& content_rect) = 0; + + virtual void OnAttachedControlChanged(controls::Control* control) { + CRU_UNUSED(control) + } + + virtual void OnAfterLayout(); + + private: + void SetParent(RenderObject* new_parent); + + void SetWindowHostRecursive(host::WindowHost* host); + + private: + controls::Control* control_ = nullptr; + host::WindowHost* window_host_ = nullptr; + + RenderObject* parent_ = nullptr; + std::vector children_{}; + + ChildMode child_mode_ = ChildMode::None; + + Point offset_{}; + Size size_{}; + + MeasureSize preferred_size_; + MeasureRequirement custom_measure_requirement_; + + Thickness margin_{}; + Thickness padding_{}; + + Event attach_to_host_event_; + Event detach_from_host_event_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp deleted file mode 100644 index bac97640..00000000 --- a/include/cru/ui/render/RenderObject.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "MeasureRequirement.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/Event.hpp" -#include "cru/ui/Base.hpp" - -#include -#include -#include - -namespace cru::ui::render { -// Render object will not destroy its children when destroyed. Control must -// manage lifecycle of its render objects. Since control will destroy its -// children when destroyed, render objects will be destroyed along with it. -// -// About layout: -// Render object should be able to deal with arbitrary size as the result of -// measure and layout. -// -// Parent may pass calculated preferred size down. But the preferred size set on -// child itself takes precedence. -// -// Each render object should obey the measure requirement to set size and report -// a warning when that requirement can't be satisfied with probably bigger size -// of children than that of itself and optional visual effect to indicate that. -// -// If size of chilren are less than min size requirement, then render object -// should try to fill the rest area. If size of children are more than max size -// requirement, then render object should display a warning of the layout -// problem and use the max size of itself with children exceeding its bound. -// (Or better you could use some visual effect to indicate that.) -// -// To write a custom RenderObject, override following methods: -// public: -// void Draw(platform::graphics::IPainter* painter) override; -// RenderObject* HitTest(const Point& point) override; -// protected: -// Size OnMeasureContent(const MeasureRequirement& requirement) override; -// void OnLayoutContent(const Rect& content_rect) override; -class CRU_UI_API RenderObject : public Object { - friend host::WindowHost; - - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::RenderObject") - - protected: - enum class ChildMode { - None, - Single, - Multiple, - }; - - RenderObject() = default; - RenderObject(ChildMode child_mode) : RenderObject() { - SetChildMode(child_mode); - } - - public: - RenderObject(const RenderObject& other) = delete; - RenderObject(RenderObject&& other) = delete; - RenderObject& operator=(const RenderObject& other) = delete; - RenderObject& operator=(RenderObject&& other) = delete; - ~RenderObject() override = default; - - controls::Control* GetAttachedControl() const { return control_; } - void SetAttachedControl(controls::Control* new_control); - - host::WindowHost* GetWindowHost() const { return window_host_; } - - RenderObject* GetParent() const { return parent_; } - - const std::vector& GetChildren() const { return children_; } - Index GetChildCount() const { return static_cast(children_.size()); } - void AddChild(RenderObject* render_object, Index position); - void RemoveChild(Index position); - - RenderObject* GetFirstChild() const; - void TraverseDescendants(const std::function& action); - - // Offset from parent's lefttop to lefttop of this render object. Margin is - // accounted for. - Point GetOffset() const { return offset_; } - Size GetSize() const { return size_; } - Point GetTotalOffset() const; - Point FromRootToContent(const Point& point) const; - - Thickness GetMargin() const { return margin_; } - void SetMargin(const Thickness& margin) { - margin_ = margin; - InvalidateLayout(); - } - - Thickness GetPadding() const { return padding_; } - void SetPadding(const Thickness& padding) { - padding_ = padding; - InvalidateLayout(); - } - - MeasureSize GetPreferredSize() const { return preferred_size_; } - void SetPreferredSize(const MeasureSize& preferred_size) { - preferred_size_ = preferred_size; - InvalidateLayout(); - } - - MeasureSize GetMinSize() const { return custom_measure_requirement_.min; } - void SetMinSize(const MeasureSize& min_size) { - custom_measure_requirement_.min = min_size; - InvalidateLayout(); - } - - MeasureSize GetMaxSize() const { return custom_measure_requirement_.max; } - void SetMaxSize(const MeasureSize& max_size) { - custom_measure_requirement_.max = max_size; - InvalidateLayout(); - } - - MeasureRequirement GetCustomMeasureRequirement() const { - return custom_measure_requirement_; - } - - // This method will merge requirement passed by argument and requirement of - // the render object using MeasureRequirement::Merge and then call - // MeasureRequirement::Normalize on it. And it will use preferred size of the - // render object to override the one passed by argument. Then pass the two to - // OnMeasureCore and use the return value of it to set the size of this render - // object. This can be called multiple times on children during measure to - // adjust for better size. - void Measure(const MeasureRequirement& requirement, - const MeasureSize& preferred_size); - // This will set offset of this render object and call OnLayoutCore. - void Layout(const Point& offset); - - virtual Thickness GetOuterSpaceThickness() const; - virtual Rect GetPaddingRect() const; - virtual Rect GetContentRect() const; - - void Draw(platform::graphics::IPainter* painter); - - // Param point must be relative the lefttop of render object including margin. - // Add offset before pass point to children. - virtual RenderObject* HitTest(const Point& point) = 0; - - IEvent* AttachToHostEvent() { - return &attach_to_host_event_; - } - IEvent* DetachFromHostEvent() { - return &detach_from_host_event_; - } - - public: - void InvalidateLayout(); - void InvalidatePaint(); - - public: - virtual std::u16string_view GetName() const; - std::u16string GetDebugPathInTree() const; - - protected: - void SetChildMode(ChildMode mode) { child_mode_ = mode; } - - protected: - RenderObject* GetSingleChild() const; - - virtual void OnParentChanged(RenderObject* old_parent, - RenderObject* new_parent); - - // default is to invalidate both layout and paint - virtual void OnAddChild(RenderObject* new_child, Index position); - // default is to invalidate both layout and paint - virtual void OnRemoveChild(RenderObject* removed_child, Index position); - - // Draw all children with offset. - void DefaultDrawChildren(platform::graphics::IPainter* painter); - - // Draw all children with translation of content rect lefttop. - void DefaultDrawContent(platform::graphics::IPainter* painter); - - // Call DefaultDrawContent. Then call DefaultDrawChildren. - virtual void OnDrawCore(platform::graphics::IPainter* painter); - - virtual void OnDrawContent(platform::graphics::IPainter* painter); - - // Size measure including margin and padding. Please reduce margin and padding - // or other custom things and pass the result content measure requirement and - // preferred size to OnMeasureContent. Return value must not be negative and - // must obey requirement. - // Note: Implementation should coerce the preferred size into the requirement - // when pass them to OnMeasureContent. - virtual Size OnMeasureCore(const MeasureRequirement& requirement, - const MeasureSize& preferred_size); - - // Please reduce margin and padding or other custom things and pass the result - // content rect to OnLayoutContent. - virtual void OnLayoutCore(); - - // Override this function to measure content and children(Call Measure on - // them). Do not consider margin or padding in this method because they are - // already considered in OnMeasureCore. Returned size must obey requirement. - // Caller should guarantee preferred_size is corerced into required range. - virtual Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) = 0; - - // Layout all content and children(Call Layout on them). - // Lefttop of content_rect should be added when calculated children's offset. - virtual void OnLayoutContent(const Rect& content_rect) = 0; - - virtual void OnAttachedControlChanged(controls::Control* control) { - CRU_UNUSED(control) - } - - virtual void OnAfterLayout(); - - private: - void SetParent(RenderObject* new_parent); - - void SetWindowHostRecursive(host::WindowHost* host); - - private: - controls::Control* control_ = nullptr; - host::WindowHost* window_host_ = nullptr; - - RenderObject* parent_ = nullptr; - std::vector children_{}; - - ChildMode child_mode_ = ChildMode::None; - - Point offset_{}; - Size size_{}; - - MeasureSize preferred_size_; - MeasureRequirement custom_measure_requirement_; - - Thickness margin_{}; - Thickness padding_{}; - - Event attach_to_host_event_; - Event detach_from_host_event_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/ScrollBar.h b/include/cru/ui/render/ScrollBar.h new file mode 100644 index 00000000..84d4375b --- /dev/null +++ b/include/cru/ui/render/ScrollBar.h @@ -0,0 +1,255 @@ +#pragma once +#include "Base.h" +#include "cru/common/Base.h" +#include "cru/common/Event.h" +#include "cru/platform/graphics/Base.h" +#include "cru/platform/graphics/Brush.h" +#include "cru/platform/graphics/Geometry.h" +#include "cru/platform/graphics/Painter.h" +#include "cru/platform/gui/Cursor.h" +#include "cru/platform/gui/TimerHelper.h" +#include "cru/platform/gui/UiApplication.h" +#include "cru/ui/Base.h" +#include "cru/ui/controls/Control.h" +#include "cru/ui/helper/ClickDetector.h" + +#include +#include +#include +#include + +namespace cru::ui::render { +class ScrollRenderObject; + +enum class ScrollKind { Absolute, Relative, Page, Line }; + +struct Scroll { + Direction direction; + ScrollKind kind; + // For absolute, the new scroll position. Otherwise, offset. + float value; +}; + +enum class ScrollBarAreaKind { + UpArrow, // Line up + DownArrow, // Line down + UpSlot, // Page up + DownSlot, // Page down + Thumb +}; + +enum class ScrollBarBrushUsageKind { Arrow, ArrowBackground, Slot, Thumb }; +enum class ScrollBarBrushStateKind { Normal, Hover, Press, Disable }; + +String CRU_UI_API GenerateScrollBarThemeColorKey(ScrollBarBrushUsageKind usage, + ScrollBarBrushStateKind state); + +class CRU_UI_API ScrollBar : public Object { + public: + ScrollBar(gsl::not_null render_object, + Direction direction); + + CRU_DELETE_COPY(ScrollBar) + CRU_DELETE_MOVE(ScrollBar) + + ~ScrollBar() override; + + public: + Direction GetDirection() const { return direction_; } + + bool IsEnabled() const { return is_enabled_; } + void SetEnabled(bool value); + + bool IsExpanded() const { return is_expanded_; } + void SetExpanded(bool value); + + void Draw(platform::graphics::IPainter* painter); + + IEvent* ScrollAttemptEvent() { return &scroll_attempt_event_; } + + void InstallHandlers(controls::Control* control); + void UninstallHandlers() { InstallHandlers(nullptr); } + + gsl::not_null> + GetCollapsedThumbBrush(); + // Brush could be nullptr to use the theme brush. + void SetCollapsedThumbBrush( + std::shared_ptr brush); + gsl::not_null> GetBrush( + ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state); + // Brush could be nullptr to use the theme brush. + void SetBrush(ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state, + std::shared_ptr brush); + + protected: + void OnDraw(platform::graphics::IPainter* painter, bool expand); + + virtual void DrawUpArrow( + platform::graphics::IPainter* painter, const Rect& area, + gsl::not_null arrow_brush, + gsl::not_null background_brush) = 0; + virtual void DrawDownArrow( + platform::graphics::IPainter* painter, const Rect& area, + gsl::not_null arrow_brush, + gsl::not_null background_brush) = 0; + + std::optional ExpandedHitTest(const Point& point); + + virtual bool IsShowBar() = 0; + + virtual std::optional GetExpandedAreaRect( + ScrollBarAreaKind area_kind) = 0; + virtual std::optional GetCollapsedTriggerExpandAreaRect() = 0; + virtual std::optional GetCollapsedThumbRect() = 0; + + virtual float CalculateNewScrollPosition(const Rect& thumb_original_rect, + const Point& mouse_offset) = 0; + + virtual bool CanScrollUp() = 0; + virtual bool CanScrollDown() = 0; + + private: + void SetCursor(); + void RestoreCursor(); + + void BeginAutoCollapseTimer(); + void StopAutoCollapseTimer(); + + void OnMouseLeave(); + + ScrollBarBrushStateKind GetState(ScrollBarAreaKind area); + + protected: + gsl::not_null render_object_; + + std::unique_ptr arrow_geometry_; + + private: + Direction direction_; + + bool is_enabled_ = true; + + bool is_expanded_ = false; + + std::shared_ptr collapsed_thumb_brush_; + std::unordered_map< + ScrollBarBrushUsageKind, + std::unordered_map>> + brushes_; + + Rect move_thumb_thumb_original_rect_; + std::optional move_thumb_start_; + + std::optional mouse_hover_; + std::optional mouse_press_; + + EventRevokerListGuard event_guard_; + + Event scroll_attempt_event_; + + bool cursor_overrided_ = false; + + platform::gui::TimerAutoCanceler auto_collapse_timer_canceler_; +}; + +class CRU_UI_API HorizontalScrollBar : public ScrollBar { + public: + explicit HorizontalScrollBar( + gsl::not_null render_object); + + CRU_DELETE_COPY(HorizontalScrollBar) + CRU_DELETE_MOVE(HorizontalScrollBar) + + ~HorizontalScrollBar() override = default; + + protected: + void DrawUpArrow( + platform::graphics::IPainter* painter, const Rect& area, + gsl::not_null arrow_brush, + gsl::not_null background_brush) override; + void DrawDownArrow( + platform::graphics::IPainter* painter, const Rect& area, + gsl::not_null arrow_brush, + gsl::not_null background_brush) override; + + bool IsShowBar() override; + + std::optional GetExpandedAreaRect(ScrollBarAreaKind area_kind) override; + std::optional GetCollapsedTriggerExpandAreaRect() override; + std::optional GetCollapsedThumbRect() override; + + float CalculateNewScrollPosition(const Rect& thumb_original_rect, + const Point& mouse_offset) override; + + bool CanScrollUp() override; + bool CanScrollDown() override; +}; + +class CRU_UI_API VerticalScrollBar : public ScrollBar { + public: + explicit VerticalScrollBar(gsl::not_null render_object); + + CRU_DELETE_COPY(VerticalScrollBar) + CRU_DELETE_MOVE(VerticalScrollBar) + + ~VerticalScrollBar() override = default; + + protected: + void DrawUpArrow( + platform::graphics::IPainter* painter, const Rect& area, + gsl::not_null arrow_brush, + gsl::not_null background_brush) override; + void DrawDownArrow( + platform::graphics::IPainter* painter, const Rect& area, + gsl::not_null arrow_brush, + gsl::not_null background_brush) override; + + bool IsShowBar() override; + + std::optional GetExpandedAreaRect(ScrollBarAreaKind area_kind) override; + std::optional GetCollapsedTriggerExpandAreaRect() override; + std::optional GetCollapsedThumbRect() override; + + float CalculateNewScrollPosition(const Rect& thumb_original_rect, + const Point& mouse_offset) override; + + bool CanScrollUp() override; + bool CanScrollDown() override; +}; + +// A delegate to draw scrollbar and register related events. +class CRU_UI_API ScrollBarDelegate : public Object { + public: + explicit ScrollBarDelegate(gsl::not_null render_object); + + CRU_DELETE_COPY(ScrollBarDelegate) + CRU_DELETE_MOVE(ScrollBarDelegate) + + ~ScrollBarDelegate() override = default; + + public: + bool IsHorizontalBarEnabled() const { return horizontal_bar_.IsEnabled(); } + void SetHorizontalBarEnabled(bool value) { + horizontal_bar_.SetEnabled(value); + } + + bool IsVerticalBarEnabled() const { return horizontal_bar_.IsEnabled(); } + void SetVerticalBarEnabled(bool value) { horizontal_bar_.SetEnabled(value); } + + IEvent* ScrollAttemptEvent() { return &scroll_attempt_event_; } + + void DrawScrollBar(platform::graphics::IPainter* painter); + + void InstallHandlers(controls::Control* control); + void UninstallHandlers() { InstallHandlers(nullptr); } + + private: + gsl::not_null render_object_; + + HorizontalScrollBar horizontal_bar_; + VerticalScrollBar vertical_bar_; + + Event scroll_attempt_event_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/ScrollBar.hpp b/include/cru/ui/render/ScrollBar.hpp deleted file mode 100644 index f1007d4d..00000000 --- a/include/cru/ui/render/ScrollBar.hpp +++ /dev/null @@ -1,255 +0,0 @@ -#pragma once -#include "Base.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/Event.hpp" -#include "cru/platform/graphics/Base.hpp" -#include "cru/platform/graphics/Brush.hpp" -#include "cru/platform/graphics/Geometry.hpp" -#include "cru/platform/graphics/Painter.hpp" -#include "cru/platform/gui/Cursor.hpp" -#include "cru/platform/gui/TimerHelper.hpp" -#include "cru/platform/gui/UiApplication.hpp" -#include "cru/ui/Base.hpp" -#include "cru/ui/controls/Control.hpp" -#include "cru/ui/helper/ClickDetector.hpp" - -#include -#include -#include -#include - -namespace cru::ui::render { -class ScrollRenderObject; - -enum class ScrollKind { Absolute, Relative, Page, Line }; - -struct Scroll { - Direction direction; - ScrollKind kind; - // For absolute, the new scroll position. Otherwise, offset. - float value; -}; - -enum class ScrollBarAreaKind { - UpArrow, // Line up - DownArrow, // Line down - UpSlot, // Page up - DownSlot, // Page down - Thumb -}; - -enum class ScrollBarBrushUsageKind { Arrow, ArrowBackground, Slot, Thumb }; -enum class ScrollBarBrushStateKind { Normal, Hover, Press, Disable }; - -String CRU_UI_API GenerateScrollBarThemeColorKey(ScrollBarBrushUsageKind usage, - ScrollBarBrushStateKind state); - -class CRU_UI_API ScrollBar : public Object { - public: - ScrollBar(gsl::not_null render_object, - Direction direction); - - CRU_DELETE_COPY(ScrollBar) - CRU_DELETE_MOVE(ScrollBar) - - ~ScrollBar() override; - - public: - Direction GetDirection() const { return direction_; } - - bool IsEnabled() const { return is_enabled_; } - void SetEnabled(bool value); - - bool IsExpanded() const { return is_expanded_; } - void SetExpanded(bool value); - - void Draw(platform::graphics::IPainter* painter); - - IEvent* ScrollAttemptEvent() { return &scroll_attempt_event_; } - - void InstallHandlers(controls::Control* control); - void UninstallHandlers() { InstallHandlers(nullptr); } - - gsl::not_null> - GetCollapsedThumbBrush(); - // Brush could be nullptr to use the theme brush. - void SetCollapsedThumbBrush( - std::shared_ptr brush); - gsl::not_null> GetBrush( - ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state); - // Brush could be nullptr to use the theme brush. - void SetBrush(ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state, - std::shared_ptr brush); - - protected: - void OnDraw(platform::graphics::IPainter* painter, bool expand); - - virtual void DrawUpArrow( - platform::graphics::IPainter* painter, const Rect& area, - gsl::not_null arrow_brush, - gsl::not_null background_brush) = 0; - virtual void DrawDownArrow( - platform::graphics::IPainter* painter, const Rect& area, - gsl::not_null arrow_brush, - gsl::not_null background_brush) = 0; - - std::optional ExpandedHitTest(const Point& point); - - virtual bool IsShowBar() = 0; - - virtual std::optional GetExpandedAreaRect( - ScrollBarAreaKind area_kind) = 0; - virtual std::optional GetCollapsedTriggerExpandAreaRect() = 0; - virtual std::optional GetCollapsedThumbRect() = 0; - - virtual float CalculateNewScrollPosition(const Rect& thumb_original_rect, - const Point& mouse_offset) = 0; - - virtual bool CanScrollUp() = 0; - virtual bool CanScrollDown() = 0; - - private: - void SetCursor(); - void RestoreCursor(); - - void BeginAutoCollapseTimer(); - void StopAutoCollapseTimer(); - - void OnMouseLeave(); - - ScrollBarBrushStateKind GetState(ScrollBarAreaKind area); - - protected: - gsl::not_null render_object_; - - std::unique_ptr arrow_geometry_; - - private: - Direction direction_; - - bool is_enabled_ = true; - - bool is_expanded_ = false; - - std::shared_ptr collapsed_thumb_brush_; - std::unordered_map< - ScrollBarBrushUsageKind, - std::unordered_map>> - brushes_; - - Rect move_thumb_thumb_original_rect_; - std::optional move_thumb_start_; - - std::optional mouse_hover_; - std::optional mouse_press_; - - EventRevokerListGuard event_guard_; - - Event scroll_attempt_event_; - - bool cursor_overrided_ = false; - - platform::gui::TimerAutoCanceler auto_collapse_timer_canceler_; -}; - -class CRU_UI_API HorizontalScrollBar : public ScrollBar { - public: - explicit HorizontalScrollBar( - gsl::not_null render_object); - - CRU_DELETE_COPY(HorizontalScrollBar) - CRU_DELETE_MOVE(HorizontalScrollBar) - - ~HorizontalScrollBar() override = default; - - protected: - void DrawUpArrow( - platform::graphics::IPainter* painter, const Rect& area, - gsl::not_null arrow_brush, - gsl::not_null background_brush) override; - void DrawDownArrow( - platform::graphics::IPainter* painter, const Rect& area, - gsl::not_null arrow_brush, - gsl::not_null background_brush) override; - - bool IsShowBar() override; - - std::optional GetExpandedAreaRect(ScrollBarAreaKind area_kind) override; - std::optional GetCollapsedTriggerExpandAreaRect() override; - std::optional GetCollapsedThumbRect() override; - - float CalculateNewScrollPosition(const Rect& thumb_original_rect, - const Point& mouse_offset) override; - - bool CanScrollUp() override; - bool CanScrollDown() override; -}; - -class CRU_UI_API VerticalScrollBar : public ScrollBar { - public: - explicit VerticalScrollBar(gsl::not_null render_object); - - CRU_DELETE_COPY(VerticalScrollBar) - CRU_DELETE_MOVE(VerticalScrollBar) - - ~VerticalScrollBar() override = default; - - protected: - void DrawUpArrow( - platform::graphics::IPainter* painter, const Rect& area, - gsl::not_null arrow_brush, - gsl::not_null background_brush) override; - void DrawDownArrow( - platform::graphics::IPainter* painter, const Rect& area, - gsl::not_null arrow_brush, - gsl::not_null background_brush) override; - - bool IsShowBar() override; - - std::optional GetExpandedAreaRect(ScrollBarAreaKind area_kind) override; - std::optional GetCollapsedTriggerExpandAreaRect() override; - std::optional GetCollapsedThumbRect() override; - - float CalculateNewScrollPosition(const Rect& thumb_original_rect, - const Point& mouse_offset) override; - - bool CanScrollUp() override; - bool CanScrollDown() override; -}; - -// A delegate to draw scrollbar and register related events. -class CRU_UI_API ScrollBarDelegate : public Object { - public: - explicit ScrollBarDelegate(gsl::not_null render_object); - - CRU_DELETE_COPY(ScrollBarDelegate) - CRU_DELETE_MOVE(ScrollBarDelegate) - - ~ScrollBarDelegate() override = default; - - public: - bool IsHorizontalBarEnabled() const { return horizontal_bar_.IsEnabled(); } - void SetHorizontalBarEnabled(bool value) { - horizontal_bar_.SetEnabled(value); - } - - bool IsVerticalBarEnabled() const { return horizontal_bar_.IsEnabled(); } - void SetVerticalBarEnabled(bool value) { horizontal_bar_.SetEnabled(value); } - - IEvent* ScrollAttemptEvent() { return &scroll_attempt_event_; } - - void DrawScrollBar(platform::graphics::IPainter* painter); - - void InstallHandlers(controls::Control* control); - void UninstallHandlers() { InstallHandlers(nullptr); } - - private: - gsl::not_null render_object_; - - HorizontalScrollBar horizontal_bar_; - VerticalScrollBar vertical_bar_; - - Event scroll_attempt_event_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/ScrollRenderObject.h b/include/cru/ui/render/ScrollRenderObject.h new file mode 100644 index 00000000..bb282953 --- /dev/null +++ b/include/cru/ui/render/ScrollRenderObject.h @@ -0,0 +1,98 @@ +#pragma once +#include "RenderObject.h" + +#include "cru/common/Event.h" +#include "cru/platform/graphics/util/Painter.h" +#include "cru/ui/Base.h" +#include "cru/ui/render/ScrollBar.h" + +#include +#include + +namespace cru::ui::render { +// Measure logic: +// Measure child with unspecified min and max size. +// If parent's preferred size is specified, then it is used as measure result. +// Or child's size is coerced into requirement and then used as result. +// If no child, then use the preferred size if set or min size if set or 0. +// Layout logic: +// If child is smaller than content area, layout at lefttop. +// Or layout by scroll state. +class CRU_UI_API ScrollRenderObject : public RenderObject { + public: + ScrollRenderObject(); + + CRU_DELETE_COPY(ScrollRenderObject) + CRU_DELETE_MOVE(ScrollRenderObject) + + ~ScrollRenderObject() override = default; + + RenderObject* HitTest(const Point& point) override; + + // Return the coerced scroll offset. + Point GetScrollOffset(); + float GetScrollOffset(Direction direction) { + return direction == Direction::Horizontal ? GetScrollOffset().x + : GetScrollOffset().y; + } + void SetScrollOffset(const Point& offset); + void SetScrollOffset(std::optional x, std::optional y); + void SetScrollOffset(Direction direction, std::optional value) { + if (direction == Direction::Horizontal) { + SetScrollOffset(value, std::nullopt); + } else { + SetScrollOffset(std::nullopt, value); + } + } + + void ApplyScroll(const Scroll& scroll); + + Point GetRawScrollOffset() const { return scroll_offset_; } + + // Return the viewable area rect. + // Lefttop is scroll offset. Size is content size. + // If size exceeds view area, left and top is more important when calculate + // new scroll offset. + Rect GetViewRect() { + return Rect{GetScrollOffset(), GetContentRect().GetSize()}; + } + + // Rect lefttop relative to content rect. + // Param margin is just for convenience and it will just add to the rect. + void ScrollToContain(const Rect& rect, const Thickness& margin = Thickness{}); + + std::u16string_view GetName() const override { return u"ScrollRenderObject"; } + + bool IsMouseWheelScrollEnabled() const { return is_mouse_wheel_enabled_; } + void SetMouseWheelScrollEnabled(bool enable); + + bool HorizontalCanScrollUp(); + bool HorizontalCanScrollDown(); + bool VerticalCanScrollUp(); + bool VerticalCanScrollDown(); + + protected: + void OnDrawCore(platform::graphics::IPainter* painter) override; + + // Logic: + // If available size is bigger than child's preferred size, then child's + // preferred size is taken. + // If not, all available size is taken while forming a scroll area. + Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + void OnAttachedControlChanged(controls::Control* control) override; + + void InstallMouseWheelHandler(controls::Control* control); + + private: + Point scroll_offset_; + + std::unique_ptr scroll_bar_delegate_; + + bool is_mouse_wheel_enabled_ = true; + + EventRevokerListGuard guard_; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/ScrollRenderObject.hpp b/include/cru/ui/render/ScrollRenderObject.hpp deleted file mode 100644 index 19814c51..00000000 --- a/include/cru/ui/render/ScrollRenderObject.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include "RenderObject.hpp" - -#include "cru/common/Event.hpp" -#include "cru/platform/graphics/util/Painter.hpp" -#include "cru/ui/Base.hpp" -#include "cru/ui/render/ScrollBar.hpp" - -#include -#include - -namespace cru::ui::render { -// Measure logic: -// Measure child with unspecified min and max size. -// If parent's preferred size is specified, then it is used as measure result. -// Or child's size is coerced into requirement and then used as result. -// If no child, then use the preferred size if set or min size if set or 0. -// Layout logic: -// If child is smaller than content area, layout at lefttop. -// Or layout by scroll state. -class CRU_UI_API ScrollRenderObject : public RenderObject { - public: - ScrollRenderObject(); - - CRU_DELETE_COPY(ScrollRenderObject) - CRU_DELETE_MOVE(ScrollRenderObject) - - ~ScrollRenderObject() override = default; - - RenderObject* HitTest(const Point& point) override; - - // Return the coerced scroll offset. - Point GetScrollOffset(); - float GetScrollOffset(Direction direction) { - return direction == Direction::Horizontal ? GetScrollOffset().x - : GetScrollOffset().y; - } - void SetScrollOffset(const Point& offset); - void SetScrollOffset(std::optional x, std::optional y); - void SetScrollOffset(Direction direction, std::optional value) { - if (direction == Direction::Horizontal) { - SetScrollOffset(value, std::nullopt); - } else { - SetScrollOffset(std::nullopt, value); - } - } - - void ApplyScroll(const Scroll& scroll); - - Point GetRawScrollOffset() const { return scroll_offset_; } - - // Return the viewable area rect. - // Lefttop is scroll offset. Size is content size. - // If size exceeds view area, left and top is more important when calculate - // new scroll offset. - Rect GetViewRect() { - return Rect{GetScrollOffset(), GetContentRect().GetSize()}; - } - - // Rect lefttop relative to content rect. - // Param margin is just for convenience and it will just add to the rect. - void ScrollToContain(const Rect& rect, const Thickness& margin = Thickness{}); - - std::u16string_view GetName() const override { return u"ScrollRenderObject"; } - - bool IsMouseWheelScrollEnabled() const { return is_mouse_wheel_enabled_; } - void SetMouseWheelScrollEnabled(bool enable); - - bool HorizontalCanScrollUp(); - bool HorizontalCanScrollDown(); - bool VerticalCanScrollUp(); - bool VerticalCanScrollDown(); - - protected: - void OnDrawCore(platform::graphics::IPainter* painter) override; - - // Logic: - // If available size is bigger than child's preferred size, then child's - // preferred size is taken. - // If not, all available size is taken while forming a scroll area. - Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - void OnAttachedControlChanged(controls::Control* control) override; - - void InstallMouseWheelHandler(controls::Control* control); - - private: - Point scroll_offset_; - - std::unique_ptr scroll_bar_delegate_; - - bool is_mouse_wheel_enabled_ = true; - - EventRevokerListGuard guard_; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/StackLayoutRenderObject.h b/include/cru/ui/render/StackLayoutRenderObject.h new file mode 100644 index 00000000..e141d16e --- /dev/null +++ b/include/cru/ui/render/StackLayoutRenderObject.h @@ -0,0 +1,57 @@ +#pragma once +#include "LayoutRenderObject.h" +#include "cru/ui/Base.h" + +namespace cru::ui::render { +// Measure Logic: +// Following rules are applied both horizontally and vertically. +// +// 1. Measure each children with min size not specified and max size as +// following rules: +// +// 1.1. If parent's preferred size is set and it is not less than child's min +// size, then it is used as child's max size. +// +// 1.2. Or if parent's max size is set, then it is used as child's max size. +// If it is less than child's min size, then log an warning about that. +// +// 2. Result size is children's max size. +// +// 3. If preferred size is specified and result size is smaller than it, coerce +// result size to preferred size. +// +// 4. If result size is smaller than min size (if specified), coerce result size +// to min size. +class CRU_UI_API StackLayoutRenderObject + : public LayoutRenderObject { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render:StackLayoutRenderObject") + + public: + StackLayoutRenderObject() = default; + CRU_DELETE_COPY(StackLayoutRenderObject) + CRU_DELETE_MOVE(StackLayoutRenderObject) + ~StackLayoutRenderObject() = default; + + std::u16string_view GetName() const override { + return u"StackLayoutRenderObject"; + } + + Alignment GetDefaultHorizontalAlignment() const { + return default_vertical_alignment_; + } + void SetDefaultHorizontalAlignment(Alignment alignment); + Alignment GetDefaultVerticalAlignment() { + return default_horizontal_alignment_; + } + void SetDefaultVertialAlignment(Alignment alignment); + + protected: + Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + private: + Alignment default_horizontal_alignment_ = Alignment::Start; + Alignment default_vertical_alignment_ = Alignment::Start; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/StackLayoutRenderObject.hpp b/include/cru/ui/render/StackLayoutRenderObject.hpp deleted file mode 100644 index 2f832e55..00000000 --- a/include/cru/ui/render/StackLayoutRenderObject.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include "LayoutRenderObject.hpp" -#include "cru/ui/Base.hpp" - -namespace cru::ui::render { -// Measure Logic: -// Following rules are applied both horizontally and vertically. -// -// 1. Measure each children with min size not specified and max size as -// following rules: -// -// 1.1. If parent's preferred size is set and it is not less than child's min -// size, then it is used as child's max size. -// -// 1.2. Or if parent's max size is set, then it is used as child's max size. -// If it is less than child's min size, then log an warning about that. -// -// 2. Result size is children's max size. -// -// 3. If preferred size is specified and result size is smaller than it, coerce -// result size to preferred size. -// -// 4. If result size is smaller than min size (if specified), coerce result size -// to min size. -class CRU_UI_API StackLayoutRenderObject - : public LayoutRenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render:StackLayoutRenderObject") - - public: - StackLayoutRenderObject() = default; - CRU_DELETE_COPY(StackLayoutRenderObject) - CRU_DELETE_MOVE(StackLayoutRenderObject) - ~StackLayoutRenderObject() = default; - - std::u16string_view GetName() const override { - return u"StackLayoutRenderObject"; - } - - Alignment GetDefaultHorizontalAlignment() const { - return default_vertical_alignment_; - } - void SetDefaultHorizontalAlignment(Alignment alignment); - Alignment GetDefaultVerticalAlignment() { - return default_horizontal_alignment_; - } - void SetDefaultVertialAlignment(Alignment alignment); - - protected: - Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - private: - Alignment default_horizontal_alignment_ = Alignment::Start; - Alignment default_vertical_alignment_ = Alignment::Start; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/render/TextRenderObject.h b/include/cru/ui/render/TextRenderObject.h new file mode 100644 index 00000000..3b5f581a --- /dev/null +++ b/include/cru/ui/render/TextRenderObject.h @@ -0,0 +1,121 @@ +#pragma once +#include "RenderObject.h" + +#include + +namespace cru::ui::render { +// Layout logic: +// 1. If preferred width is set then it is taken to do a text measure. If not +// set, then max width is taken to do that. +// 2. If the actual width of text after measure exceeds the required width, +// coerced value is returned and an error is reported. If preferred width is set +// and actual width is smaller than that, then preferred width is used. If +// preferred width is not set, then the same thing is applied to min width. +// 3. If actual height of text is bigger than max height, an error is reported +// and coerced value is returned. Or height is lifted up to be at least +// preferred size if set or min height. +// +// If the result layout box is bigger than actual text box, then text is center +// aligned. +class CRU_UI_API TextRenderObject : public RenderObject { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::TextRenderObject") + + public: + constexpr static float default_caret_width = 2; + + public: + TextRenderObject(std::shared_ptr brush, + std::shared_ptr font, + std::shared_ptr selection_brush, + std::shared_ptr caret_brush); + TextRenderObject(const TextRenderObject& other) = delete; + TextRenderObject(TextRenderObject&& other) = delete; + TextRenderObject& operator=(const TextRenderObject& other) = delete; + TextRenderObject& operator=(TextRenderObject&& other) = delete; + ~TextRenderObject() override; + + String GetText() const; + void SetText(String new_text); + + void SetBrush(std::shared_ptr new_brush); + + std::shared_ptr GetFont() const; + void SetFont(std::shared_ptr font); + + bool IsEditMode(); + void SetEditMode(bool enable); + + Index GetLineCount(); + Index GetLineIndexFromCharIndex(Index char_index); + float GetLineHeight(Index line_index); + std::vector TextRangeRect(const TextRange& text_range); + Rect TextSinglePoint(gsl::index position, bool trailing); + platform::graphics::TextHitTestResult TextHitTest(const Point& point); + + std::optional GetSelectionRange() const { + return selection_range_; + } + void SetSelectionRange(std::optional new_range); + + std::shared_ptr GetSelectionBrush() const { + return selection_brush_; + } + void SetSelectionBrush(std::shared_ptr new_brush); + + bool IsDrawCaret() const { return draw_caret_; } + void SetDrawCaret(bool draw_caret); + void ToggleDrawCaret() { SetDrawCaret(!IsDrawCaret()); } + + // Caret position can be any value. When it is negative, 0 is used. When it + // exceeds the size of the string, the size of the string is used. + gsl::index GetCaretPosition() const { return caret_position_; } + void SetCaretPosition(gsl::index position); + + // Lefttop relative to content lefttop. + Rect GetCaretRectInContent(); + // Lefttop relative to render object lefttop. + Rect GetCaretRect(); + + std::shared_ptr GetCaretBrush() const { + return caret_brush_; + } + void GetCaretBrush(std::shared_ptr brush); + + float GetCaretWidth() const { return caret_width_; } + void SetCaretWidth(float width); + + bool IsMeasureIncludingTrailingSpace() const { + return is_measure_including_trailing_space_; + } + void SetMeasureIncludingTrailingSpace(bool including); + + RenderObject* HitTest(const Point& point) override; + + std::u16string_view GetName() const override { return u"TextRenderObject"; } + + protected: + void OnDrawContent(platform::graphics::IPainter* painter) override; + + // See remarks of this class. + Size OnMeasureContent(const MeasureRequirement& requirement, + const MeasureSize& preferred_size) override; + void OnLayoutContent(const Rect& content_rect) override; + + void OnAfterLayout() override; + + private: + std::shared_ptr brush_; + std::shared_ptr font_; + std::unique_ptr text_layout_; + + std::optional selection_range_ = std::nullopt; + std::shared_ptr selection_brush_; + + bool draw_caret_ = false; + gsl::index caret_position_ = 0; + std::shared_ptr caret_brush_; + float caret_width_ = default_caret_width; + + bool is_measure_including_trailing_space_ = false; +}; +} // namespace cru::ui::render diff --git a/include/cru/ui/render/TextRenderObject.hpp b/include/cru/ui/render/TextRenderObject.hpp deleted file mode 100644 index 601bd0a8..00000000 --- a/include/cru/ui/render/TextRenderObject.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once -#include "RenderObject.hpp" - -#include - -namespace cru::ui::render { -// Layout logic: -// 1. If preferred width is set then it is taken to do a text measure. If not -// set, then max width is taken to do that. -// 2. If the actual width of text after measure exceeds the required width, -// coerced value is returned and an error is reported. If preferred width is set -// and actual width is smaller than that, then preferred width is used. If -// preferred width is not set, then the same thing is applied to min width. -// 3. If actual height of text is bigger than max height, an error is reported -// and coerced value is returned. Or height is lifted up to be at least -// preferred size if set or min height. -// -// If the result layout box is bigger than actual text box, then text is center -// aligned. -class CRU_UI_API TextRenderObject : public RenderObject { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::TextRenderObject") - - public: - constexpr static float default_caret_width = 2; - - public: - TextRenderObject(std::shared_ptr brush, - std::shared_ptr font, - std::shared_ptr selection_brush, - std::shared_ptr caret_brush); - TextRenderObject(const TextRenderObject& other) = delete; - TextRenderObject(TextRenderObject&& other) = delete; - TextRenderObject& operator=(const TextRenderObject& other) = delete; - TextRenderObject& operator=(TextRenderObject&& other) = delete; - ~TextRenderObject() override; - - String GetText() const; - void SetText(String new_text); - - void SetBrush(std::shared_ptr new_brush); - - std::shared_ptr GetFont() const; - void SetFont(std::shared_ptr font); - - bool IsEditMode(); - void SetEditMode(bool enable); - - Index GetLineCount(); - Index GetLineIndexFromCharIndex(Index char_index); - float GetLineHeight(Index line_index); - std::vector TextRangeRect(const TextRange& text_range); - Rect TextSinglePoint(gsl::index position, bool trailing); - platform::graphics::TextHitTestResult TextHitTest(const Point& point); - - std::optional GetSelectionRange() const { - return selection_range_; - } - void SetSelectionRange(std::optional new_range); - - std::shared_ptr GetSelectionBrush() const { - return selection_brush_; - } - void SetSelectionBrush(std::shared_ptr new_brush); - - bool IsDrawCaret() const { return draw_caret_; } - void SetDrawCaret(bool draw_caret); - void ToggleDrawCaret() { SetDrawCaret(!IsDrawCaret()); } - - // Caret position can be any value. When it is negative, 0 is used. When it - // exceeds the size of the string, the size of the string is used. - gsl::index GetCaretPosition() const { return caret_position_; } - void SetCaretPosition(gsl::index position); - - // Lefttop relative to content lefttop. - Rect GetCaretRectInContent(); - // Lefttop relative to render object lefttop. - Rect GetCaretRect(); - - std::shared_ptr GetCaretBrush() const { - return caret_brush_; - } - void GetCaretBrush(std::shared_ptr brush); - - float GetCaretWidth() const { return caret_width_; } - void SetCaretWidth(float width); - - bool IsMeasureIncludingTrailingSpace() const { - return is_measure_including_trailing_space_; - } - void SetMeasureIncludingTrailingSpace(bool including); - - RenderObject* HitTest(const Point& point) override; - - std::u16string_view GetName() const override { return u"TextRenderObject"; } - - protected: - void OnDrawContent(platform::graphics::IPainter* painter) override; - - // See remarks of this class. - Size OnMeasureContent(const MeasureRequirement& requirement, - const MeasureSize& preferred_size) override; - void OnLayoutContent(const Rect& content_rect) override; - - void OnAfterLayout() override; - - private: - std::shared_ptr brush_; - std::shared_ptr font_; - std::unique_ptr text_layout_; - - std::optional selection_range_ = std::nullopt; - std::shared_ptr selection_brush_; - - bool draw_caret_ = false; - gsl::index caret_position_ = 0; - std::shared_ptr caret_brush_; - float caret_width_ = default_caret_width; - - bool is_measure_including_trailing_space_ = false; -}; -} // namespace cru::ui::render diff --git a/include/cru/ui/style/ApplyBorderStyleInfo.h b/include/cru/ui/style/ApplyBorderStyleInfo.h new file mode 100644 index 00000000..2e6753fc --- /dev/null +++ b/include/cru/ui/style/ApplyBorderStyleInfo.h @@ -0,0 +1,30 @@ +#pragma once +#include "../Base.h" + +#include + +namespace cru::ui::style { +struct ApplyBorderStyleInfo { + ApplyBorderStyleInfo() = default; + + explicit ApplyBorderStyleInfo( + std::optional> border_brush, + std::optional border_thickness = std::nullopt, + std::optional border_radius = std::nullopt, + std::optional> + foreground_brush = std::nullopt, + std::optional> + background_brush = std::nullopt) + : border_brush(std::move(border_brush)), + border_thickness(std::move(border_thickness)), + border_radius(std::move(border_radius)), + foreground_brush(std::move(foreground_brush)), + background_brush(std::move(background_brush)) {} + + std::optional> border_brush; + std::optional border_thickness; + std::optional border_radius; + std::optional> foreground_brush; + std::optional> background_brush; +}; +} // namespace cru::ui::style diff --git a/include/cru/ui/style/ApplyBorderStyleInfo.hpp b/include/cru/ui/style/ApplyBorderStyleInfo.hpp deleted file mode 100644 index 7ae5b2c5..00000000 --- a/include/cru/ui/style/ApplyBorderStyleInfo.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include - -namespace cru::ui::style { -struct ApplyBorderStyleInfo { - ApplyBorderStyleInfo() = default; - - explicit ApplyBorderStyleInfo( - std::optional> border_brush, - std::optional border_thickness = std::nullopt, - std::optional border_radius = std::nullopt, - std::optional> - foreground_brush = std::nullopt, - std::optional> - background_brush = std::nullopt) - : border_brush(std::move(border_brush)), - border_thickness(std::move(border_thickness)), - border_radius(std::move(border_radius)), - foreground_brush(std::move(foreground_brush)), - background_brush(std::move(background_brush)) {} - - std::optional> border_brush; - std::optional border_thickness; - std::optional border_radius; - std::optional> foreground_brush; - std::optional> background_brush; -}; -} // namespace cru::ui::style diff --git a/include/cru/ui/style/Condition.h b/include/cru/ui/style/Condition.h new file mode 100644 index 00000000..221a7428 --- /dev/null +++ b/include/cru/ui/style/Condition.h @@ -0,0 +1,133 @@ +#pragma once +#include "../Base.h" +#include "cru/common/Base.h" +#include "cru/common/ClonablePtr.h" +#include "cru/common/Event.h" +#include "cru/ui/controls/IClickableControl.h" +#include "cru/ui/helper/ClickDetector.h" + +#include +#include +#include +#include + +namespace cru::ui::style { +class Condition : public Object { + public: + virtual std::vector ChangeOn( + controls::Control* control) const = 0; + virtual bool Judge(controls::Control* control) const = 0; + + virtual Condition* Clone() const = 0; +}; + +class NoCondition : public Condition { + public: + static ClonablePtr Create() { + return ClonablePtr(new NoCondition); + }; + + std::vector ChangeOn(controls::Control*) const override { + return {}; + } + + bool Judge(controls::Control*) const override { return true; } + + NoCondition* Clone() const override { return new NoCondition; } +}; + +class CompoundCondition : public Condition { + public: + explicit CompoundCondition(std::vector> conditions); + + std::vector ChangeOn(controls::Control* control) const override; + + protected: + std::vector> conditions_; +}; + +class AndCondition : public CompoundCondition { + public: + static ClonablePtr Create( + std::vector> conditions) { + return ClonablePtr(new AndCondition(std::move(conditions))); + } + + using CompoundCondition::CompoundCondition; + + bool Judge(controls::Control* control) const override; + + AndCondition* Clone() const override { return new AndCondition(conditions_); } +}; + +class OrCondition : public CompoundCondition { + public: + static ClonablePtr Create( + std::vector> conditions) { + return ClonablePtr(new OrCondition(std::move(conditions))); + } + + using CompoundCondition::CompoundCondition; + + bool Judge(controls::Control* control) const override; + + OrCondition* Clone() const override { return new OrCondition(conditions_); } +}; + +class FocusCondition : public Condition { + public: + static ClonablePtr Create(bool has_focus) { + return ClonablePtr(new FocusCondition(has_focus)); + } + + explicit FocusCondition(bool has_focus); + + std::vector ChangeOn(controls::Control* control) const override; + bool Judge(controls::Control* control) const override; + + FocusCondition* Clone() const override { + return new FocusCondition(has_focus_); + } + + private: + bool has_focus_; +}; + +class HoverCondition : public Condition { + public: + static ClonablePtr Create(bool hover) { + return ClonablePtr(new HoverCondition(hover)); + } + + explicit HoverCondition(bool hover) : hover_(hover) {} + + std::vector ChangeOn(controls::Control* control) const override; + bool Judge(controls::Control* control) const override; + + HoverCondition* Clone() const override { return new HoverCondition(hover_); } + + private: + bool hover_; +}; + +class ClickStateCondition : public Condition { + public: + static ClonablePtr Create( + helper::ClickState click_state) { + return ClonablePtr( + new ClickStateCondition(click_state)); + } + + explicit ClickStateCondition(helper::ClickState click_state); + + std::vector ChangeOn(controls::Control* control) const override; + bool Judge(controls::Control* control) const override; + + ClickStateCondition* Clone() const override { + return new ClickStateCondition(click_state_); + } + + private: + helper::ClickState click_state_; +}; +} // namespace cru::ui::style diff --git a/include/cru/ui/style/Condition.hpp b/include/cru/ui/style/Condition.hpp deleted file mode 100644 index 89da81f6..00000000 --- a/include/cru/ui/style/Condition.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once -#include "../Base.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/common/Event.hpp" -#include "cru/ui/controls/IClickableControl.hpp" -#include "cru/ui/helper/ClickDetector.hpp" - -#include -#include -#include -#include - -namespace cru::ui::style { -class Condition : public Object { - public: - virtual std::vector ChangeOn( - controls::Control* control) const = 0; - virtual bool Judge(controls::Control* control) const = 0; - - virtual Condition* Clone() const = 0; -}; - -class NoCondition : public Condition { - public: - static ClonablePtr Create() { - return ClonablePtr(new NoCondition); - }; - - std::vector ChangeOn(controls::Control*) const override { - return {}; - } - - bool Judge(controls::Control*) const override { return true; } - - NoCondition* Clone() const override { return new NoCondition; } -}; - -class CompoundCondition : public Condition { - public: - explicit CompoundCondition(std::vector> conditions); - - std::vector ChangeOn(controls::Control* control) const override; - - protected: - std::vector> conditions_; -}; - -class AndCondition : public CompoundCondition { - public: - static ClonablePtr Create( - std::vector> conditions) { - return ClonablePtr(new AndCondition(std::move(conditions))); - } - - using CompoundCondition::CompoundCondition; - - bool Judge(controls::Control* control) const override; - - AndCondition* Clone() const override { return new AndCondition(conditions_); } -}; - -class OrCondition : public CompoundCondition { - public: - static ClonablePtr Create( - std::vector> conditions) { - return ClonablePtr(new OrCondition(std::move(conditions))); - } - - using CompoundCondition::CompoundCondition; - - bool Judge(controls::Control* control) const override; - - OrCondition* Clone() const override { return new OrCondition(conditions_); } -}; - -class FocusCondition : public Condition { - public: - static ClonablePtr Create(bool has_focus) { - return ClonablePtr(new FocusCondition(has_focus)); - } - - explicit FocusCondition(bool has_focus); - - std::vector ChangeOn(controls::Control* control) const override; - bool Judge(controls::Control* control) const override; - - FocusCondition* Clone() const override { - return new FocusCondition(has_focus_); - } - - private: - bool has_focus_; -}; - -class HoverCondition : public Condition { - public: - static ClonablePtr Create(bool hover) { - return ClonablePtr(new HoverCondition(hover)); - } - - explicit HoverCondition(bool hover) : hover_(hover) {} - - std::vector ChangeOn(controls::Control* control) const override; - bool Judge(controls::Control* control) const override; - - HoverCondition* Clone() const override { return new HoverCondition(hover_); } - - private: - bool hover_; -}; - -class ClickStateCondition : public Condition { - public: - static ClonablePtr Create( - helper::ClickState click_state) { - return ClonablePtr( - new ClickStateCondition(click_state)); - } - - explicit ClickStateCondition(helper::ClickState click_state); - - std::vector ChangeOn(controls::Control* control) const override; - bool Judge(controls::Control* control) const override; - - ClickStateCondition* Clone() const override { - return new ClickStateCondition(click_state_); - } - - private: - helper::ClickState click_state_; -}; -} // namespace cru::ui::style diff --git a/include/cru/ui/style/StyleRule.h b/include/cru/ui/style/StyleRule.h new file mode 100644 index 00000000..68b239f3 --- /dev/null +++ b/include/cru/ui/style/StyleRule.h @@ -0,0 +1,49 @@ +#pragma once +#include "../Base.h" +#include "Condition.h" +#include "Styler.h" +#include "cru/common/ClonablePtr.h" + +#include +#include + +namespace cru::ui::style { +class StyleRule : public Object { + public: + static ClonablePtr Create(ClonablePtr condition, + ClonablePtr styler, + String name = {}) { + return ClonablePtr(new StyleRule( + std::move(condition), std::move(styler), std::move(name))); + } + + StyleRule(ClonablePtr condition, ClonablePtr styler, + String name = {}); + + CRU_DEFAULT_COPY(StyleRule) + CRU_DEFAULT_MOVE(StyleRule) + + ~StyleRule() override = default; + + public: + String GetName() const { return name_; } + Condition* GetCondition() const { return condition_.get(); } + Styler* GetStyler() const { return styler_.get(); } + + StyleRule WithNewCondition(ClonablePtr condition, + String name = {}) const { + return StyleRule{std::move(condition), styler_, std::move(name)}; + } + + StyleRule WithNewStyler(ClonablePtr styler, String name = {}) const { + return StyleRule{condition_, std::move(styler), std::move(name)}; + } + + bool CheckAndApply(controls::Control* control) const; + + private: + ClonablePtr condition_; + ClonablePtr styler_; + String name_; +}; +} // namespace cru::ui::style diff --git a/include/cru/ui/style/StyleRule.hpp b/include/cru/ui/style/StyleRule.hpp deleted file mode 100644 index 743aa759..00000000 --- a/include/cru/ui/style/StyleRule.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include "../Base.hpp" -#include "Condition.hpp" -#include "Styler.hpp" -#include "cru/common/ClonablePtr.hpp" - -#include -#include - -namespace cru::ui::style { -class StyleRule : public Object { - public: - static ClonablePtr Create(ClonablePtr condition, - ClonablePtr styler, - String name = {}) { - return ClonablePtr(new StyleRule( - std::move(condition), std::move(styler), std::move(name))); - } - - StyleRule(ClonablePtr condition, ClonablePtr styler, - String name = {}); - - CRU_DEFAULT_COPY(StyleRule) - CRU_DEFAULT_MOVE(StyleRule) - - ~StyleRule() override = default; - - public: - String GetName() const { return name_; } - Condition* GetCondition() const { return condition_.get(); } - Styler* GetStyler() const { return styler_.get(); } - - StyleRule WithNewCondition(ClonablePtr condition, - String name = {}) const { - return StyleRule{std::move(condition), styler_, std::move(name)}; - } - - StyleRule WithNewStyler(ClonablePtr styler, String name = {}) const { - return StyleRule{condition_, std::move(styler), std::move(name)}; - } - - bool CheckAndApply(controls::Control* control) const; - - private: - ClonablePtr condition_; - ClonablePtr styler_; - String name_; -}; -} // namespace cru::ui::style diff --git a/include/cru/ui/style/StyleRuleSet.h b/include/cru/ui/style/StyleRuleSet.h new file mode 100644 index 00000000..34d0fad4 --- /dev/null +++ b/include/cru/ui/style/StyleRuleSet.h @@ -0,0 +1,80 @@ +#pragma once +#include "StyleRule.h" +#include "cru/common/Base.h" +#include "cru/common/Event.h" + +#include + +namespace cru::ui::style { +class StyleRuleSet : public Object { + public: + StyleRuleSet() = default; + explicit StyleRuleSet(std::shared_ptr parent); + + CRU_DELETE_COPY(StyleRuleSet) + CRU_DELETE_MOVE(StyleRuleSet) + + ~StyleRuleSet() override = default; + + public: + std::shared_ptr GetParent() const { return parent_; } + void SetParent(std::shared_ptr parent); + + gsl::index GetSize() const { return static_cast(rules_.size()); } + const std::vector& GetRules() const { return rules_; } + + void AddStyleRule(StyleRule rule) { + AddStyleRule(std::move(rule), GetSize()); + } + + void AddStyleRule(StyleRule rule, gsl::index index); + + void RemoveStyleRule(gsl::index index, gsl::index count = 1); + + void Clear() { RemoveStyleRule(0, GetSize()); } + + void Set(const StyleRuleSet& other, bool set_parent = false); + + const StyleRule& operator[](gsl::index index) const { return rules_[index]; } + + // Triggered whenever a change happened to this (rule add or remove, parent + // change ...). Subscribe to this and update style change listeners and style. + IEvent* ChangeEvent() { return &change_event_; } + + private: + void RaiseChangeEvent() { change_event_.Raise(nullptr); } + + private: + Event change_event_; + + std::shared_ptr parent_ = nullptr; + EventRevokerGuard parent_change_event_guard_; + + std::vector rules_; +}; + +class StyleRuleSetBind { + public: + StyleRuleSetBind(controls::Control* control, + std::shared_ptr ruleset); + + CRU_DELETE_COPY(StyleRuleSetBind) + CRU_DELETE_MOVE(StyleRuleSetBind) + + ~StyleRuleSetBind() = default; + + private: + void UpdateRuleSetChainCache(); + void UpdateChangeListener(); + void UpdateStyle(); + + private: + controls::Control* control_; + std::shared_ptr ruleset_; + + // child first, parent last. + std::vector ruleset_chain_cache_; + + EventRevokerListGuard guard_; +}; +} // namespace cru::ui::style diff --git a/include/cru/ui/style/StyleRuleSet.hpp b/include/cru/ui/style/StyleRuleSet.hpp deleted file mode 100644 index 32b02d78..00000000 --- a/include/cru/ui/style/StyleRuleSet.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -#include "StyleRule.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/Event.hpp" - -#include - -namespace cru::ui::style { -class StyleRuleSet : public Object { - public: - StyleRuleSet() = default; - explicit StyleRuleSet(std::shared_ptr parent); - - CRU_DELETE_COPY(StyleRuleSet) - CRU_DELETE_MOVE(StyleRuleSet) - - ~StyleRuleSet() override = default; - - public: - std::shared_ptr GetParent() const { return parent_; } - void SetParent(std::shared_ptr parent); - - gsl::index GetSize() const { return static_cast(rules_.size()); } - const std::vector& GetRules() const { return rules_; } - - void AddStyleRule(StyleRule rule) { - AddStyleRule(std::move(rule), GetSize()); - } - - void AddStyleRule(StyleRule rule, gsl::index index); - - void RemoveStyleRule(gsl::index index, gsl::index count = 1); - - void Clear() { RemoveStyleRule(0, GetSize()); } - - void Set(const StyleRuleSet& other, bool set_parent = false); - - const StyleRule& operator[](gsl::index index) const { return rules_[index]; } - - // Triggered whenever a change happened to this (rule add or remove, parent - // change ...). Subscribe to this and update style change listeners and style. - IEvent* ChangeEvent() { return &change_event_; } - - private: - void RaiseChangeEvent() { change_event_.Raise(nullptr); } - - private: - Event change_event_; - - std::shared_ptr parent_ = nullptr; - EventRevokerGuard parent_change_event_guard_; - - std::vector rules_; -}; - -class StyleRuleSetBind { - public: - StyleRuleSetBind(controls::Control* control, - std::shared_ptr ruleset); - - CRU_DELETE_COPY(StyleRuleSetBind) - CRU_DELETE_MOVE(StyleRuleSetBind) - - ~StyleRuleSetBind() = default; - - private: - void UpdateRuleSetChainCache(); - void UpdateChangeListener(); - void UpdateStyle(); - - private: - controls::Control* control_; - std::shared_ptr ruleset_; - - // child first, parent last. - std::vector ruleset_chain_cache_; - - EventRevokerListGuard guard_; -}; -} // namespace cru::ui::style diff --git a/include/cru/ui/style/Styler.h b/include/cru/ui/style/Styler.h new file mode 100644 index 00000000..9bdec294 --- /dev/null +++ b/include/cru/ui/style/Styler.h @@ -0,0 +1,90 @@ +#pragma once +#include "../Base.h" +#include "ApplyBorderStyleInfo.h" +#include "cru/common/Base.h" +#include "cru/common/ClonablePtr.h" +#include "cru/platform/gui/Cursor.h" +#include "cru/ui/controls/Control.h" + +#include +#include + +namespace cru::ui::style { +class Styler : public Object { + public: + virtual void Apply(controls::Control* control) const = 0; + + virtual Styler* Clone() const = 0; +}; + +class CompoundStyler : public Styler { + public: + template + static ClonablePtr Create(ClonablePtr... s) { + return ClonablePtr( + new CompoundStyler(std::vector>{std::move(s)...})); + } + + static ClonablePtr Create( + std::vector> stylers) { + return ClonablePtr(new CompoundStyler(std::move(stylers))); + } + + explicit CompoundStyler(std::vector> stylers) + : stylers_(std::move(stylers)) {} + + void Apply(controls::Control* control) const override { + for (const auto& styler : stylers_) { + styler->Apply(control); + } + } + + virtual CompoundStyler* Clone() const override { + return new CompoundStyler(stylers_); + } + + private: + std::vector> stylers_; +}; + +class BorderStyler : public Styler { + public: + static ClonablePtr Create() { + return ClonablePtr(new BorderStyler()); + } + + static ClonablePtr Create(ApplyBorderStyleInfo style) { + return ClonablePtr(new BorderStyler(std::move(style))); + } + + BorderStyler() = default; + explicit BorderStyler(ApplyBorderStyleInfo style); + + void Apply(controls::Control* control) const override; + + BorderStyler* Clone() const override { return new BorderStyler(style_); } + + private: + ApplyBorderStyleInfo style_; +}; + +class CursorStyler : public Styler { + public: + static ClonablePtr Create( + std::shared_ptr cursor) { + return ClonablePtr(new CursorStyler(std::move(cursor))); + } + + static ClonablePtr Create(platform::gui::SystemCursorType type); + + explicit CursorStyler(std::shared_ptr cursor) + : cursor_(std::move(cursor)) {} + + void Apply(controls::Control* control) const override; + + CursorStyler* Clone() const override { return new CursorStyler(cursor_); } + + private: + std::shared_ptr cursor_; +}; +} // namespace cru::ui::style diff --git a/include/cru/ui/style/Styler.hpp b/include/cru/ui/style/Styler.hpp deleted file mode 100644 index 3bf0b027..00000000 --- a/include/cru/ui/style/Styler.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once -#include "../Base.hpp" -#include "ApplyBorderStyleInfo.hpp" -#include "cru/common/Base.hpp" -#include "cru/common/ClonablePtr.hpp" -#include "cru/platform/gui/Cursor.hpp" -#include "cru/ui/controls/Control.hpp" - -#include -#include - -namespace cru::ui::style { -class Styler : public Object { - public: - virtual void Apply(controls::Control* control) const = 0; - - virtual Styler* Clone() const = 0; -}; - -class CompoundStyler : public Styler { - public: - template - static ClonablePtr Create(ClonablePtr... s) { - return ClonablePtr( - new CompoundStyler(std::vector>{std::move(s)...})); - } - - static ClonablePtr Create( - std::vector> stylers) { - return ClonablePtr(new CompoundStyler(std::move(stylers))); - } - - explicit CompoundStyler(std::vector> stylers) - : stylers_(std::move(stylers)) {} - - void Apply(controls::Control* control) const override { - for (const auto& styler : stylers_) { - styler->Apply(control); - } - } - - virtual CompoundStyler* Clone() const override { - return new CompoundStyler(stylers_); - } - - private: - std::vector> stylers_; -}; - -class BorderStyler : public Styler { - public: - static ClonablePtr Create() { - return ClonablePtr(new BorderStyler()); - } - - static ClonablePtr Create(ApplyBorderStyleInfo style) { - return ClonablePtr(new BorderStyler(std::move(style))); - } - - BorderStyler() = default; - explicit BorderStyler(ApplyBorderStyleInfo style); - - void Apply(controls::Control* control) const override; - - BorderStyler* Clone() const override { return new BorderStyler(style_); } - - private: - ApplyBorderStyleInfo style_; -}; - -class CursorStyler : public Styler { - public: - static ClonablePtr Create( - std::shared_ptr cursor) { - return ClonablePtr(new CursorStyler(std::move(cursor))); - } - - static ClonablePtr Create(platform::gui::SystemCursorType type); - - explicit CursorStyler(std::shared_ptr cursor) - : cursor_(std::move(cursor)) {} - - void Apply(controls::Control* control) const override; - - CursorStyler* Clone() const override { return new CursorStyler(cursor_); } - - private: - std::shared_ptr cursor_; -}; -} // namespace cru::ui::style diff --git a/include/cru/win/Base.h b/include/cru/win/Base.h new file mode 100644 index 00000000..75da7287 --- /dev/null +++ b/include/cru/win/Base.h @@ -0,0 +1,13 @@ +#pragma once + +#include "WinPreConfig.h" + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_WIN_EXPORT_API +#define CRU_WIN_API __declspec(dllexport) +#else +#define CRU_WIN_API __declspec(dllimport) +#endif +#else +#define CRU_WIN_API +#endif diff --git a/include/cru/win/Base.hpp b/include/cru/win/Base.hpp deleted file mode 100644 index d78f2538..00000000 --- a/include/cru/win/Base.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "WinPreConfig.hpp" - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_WIN_EXPORT_API -#define CRU_WIN_API __declspec(dllexport) -#else -#define CRU_WIN_API __declspec(dllimport) -#endif -#else -#define CRU_WIN_API -#endif diff --git a/include/cru/win/DebugLogger.h b/include/cru/win/DebugLogger.h new file mode 100644 index 00000000..6a7173ea --- /dev/null +++ b/include/cru/win/DebugLogger.h @@ -0,0 +1,24 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Logger.h" + +namespace cru::platform::win { + +class CRU_WIN_API WinDebugLoggerSource : public ::cru::log::ILogSource { + public: + WinDebugLoggerSource() = default; + + CRU_DELETE_COPY(WinDebugLoggerSource) + CRU_DELETE_MOVE(WinDebugLoggerSource) + + ~WinDebugLoggerSource() = default; + + void Write(::cru::log::LogLevel level, StringView s) override { + CRU_UNUSED(level) + + String m = s.ToString(); + ::OutputDebugStringW(reinterpret_cast(m.c_str())); + } +}; +} // namespace cru::platform::win diff --git a/include/cru/win/DebugLogger.hpp b/include/cru/win/DebugLogger.hpp deleted file mode 100644 index 05793607..00000000 --- a/include/cru/win/DebugLogger.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Logger.hpp" - -namespace cru::platform::win { - -class CRU_WIN_API WinDebugLoggerSource : public ::cru::log::ILogSource { - public: - WinDebugLoggerSource() = default; - - CRU_DELETE_COPY(WinDebugLoggerSource) - CRU_DELETE_MOVE(WinDebugLoggerSource) - - ~WinDebugLoggerSource() = default; - - void Write(::cru::log::LogLevel level, StringView s) override { - CRU_UNUSED(level) - - String m = s.ToString(); - ::OutputDebugStringW(reinterpret_cast(m.c_str())); - } -}; -} // namespace cru::platform::win diff --git a/include/cru/win/Exception.h b/include/cru/win/Exception.h new file mode 100644 index 00000000..af8b495c --- /dev/null +++ b/include/cru/win/Exception.h @@ -0,0 +1,3 @@ +#pragma once +#include "cru/common/platform/win/Exception.h" +#include "cru/platform/Exception.h" diff --git a/include/cru/win/Exception.hpp b/include/cru/win/Exception.hpp deleted file mode 100644 index 3c42ff65..00000000 --- a/include/cru/win/Exception.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -#include "cru/common/platform/win/Exception.hpp" -#include "cru/platform/Exception.hpp" diff --git a/include/cru/win/StdOutLogger.h b/include/cru/win/StdOutLogger.h new file mode 100644 index 00000000..831d006f --- /dev/null +++ b/include/cru/win/StdOutLogger.h @@ -0,0 +1,23 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Logger.h" + +namespace cru::platform::win { +class CRU_WIN_API WinStdOutLoggerSource : public ::cru::log::ILogSource { + public: + WinStdOutLoggerSource() = default; + + CRU_DELETE_COPY(WinStdOutLoggerSource) + CRU_DELETE_MOVE(WinStdOutLoggerSource) + + ~WinStdOutLoggerSource() = default; + + void Write(::cru::log::LogLevel level, StringView s) override { + CRU_UNUSED(level) + + String m = s.ToString(); + std::fputws(reinterpret_cast(m.c_str()), stdout); + } +}; +} // namespace cru::platform::win diff --git a/include/cru/win/StdOutLogger.hpp b/include/cru/win/StdOutLogger.hpp deleted file mode 100644 index cfda0a85..00000000 --- a/include/cru/win/StdOutLogger.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Logger.hpp" - -namespace cru::platform::win { -class CRU_WIN_API WinStdOutLoggerSource : public ::cru::log::ILogSource { - public: - WinStdOutLoggerSource() = default; - - CRU_DELETE_COPY(WinStdOutLoggerSource) - CRU_DELETE_MOVE(WinStdOutLoggerSource) - - ~WinStdOutLoggerSource() = default; - - void Write(::cru::log::LogLevel level, StringView s) override { - CRU_UNUSED(level) - - String m = s.ToString(); - std::fputws(reinterpret_cast(m.c_str()), stdout); - } -}; -} // namespace cru::platform::win diff --git a/include/cru/win/WinPreConfig.h b/include/cru/win/WinPreConfig.h new file mode 100644 index 00000000..e714bf5e --- /dev/null +++ b/include/cru/win/WinPreConfig.h @@ -0,0 +1,2 @@ +#pragma once +#include "cru/common/platform/win/WinPreConfig.h" diff --git a/include/cru/win/WinPreConfig.hpp b/include/cru/win/WinPreConfig.hpp deleted file mode 100644 index 1658e45d..00000000 --- a/include/cru/win/WinPreConfig.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#include "cru/common/platform/win/WinPreConfig.hpp" diff --git a/include/cru/win/graphics/direct/Base.h b/include/cru/win/graphics/direct/Base.h new file mode 100644 index 00000000..5f6f8c99 --- /dev/null +++ b/include/cru/win/graphics/direct/Base.h @@ -0,0 +1,18 @@ +#pragma once +#include "../../WinPreConfig.h" + +#include +#include +#include +#include +#include + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_WIN_GRAPHICS_DIRECT_EXPORT_API +#define CRU_WIN_GRAPHICS_DIRECT_API __declspec(dllexport) +#else +#define CRU_WIN_GRAPHICS_DIRECT_API __declspec(dllimport) +#endif +#else +#define CRU_WIN_GRAPHICS_DIRECT_API +#endif diff --git a/include/cru/win/graphics/direct/Base.hpp b/include/cru/win/graphics/direct/Base.hpp deleted file mode 100644 index 49fc7897..00000000 --- a/include/cru/win/graphics/direct/Base.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "../../WinPreConfig.hpp" - -#include -#include -#include -#include -#include - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_WIN_GRAPHICS_DIRECT_EXPORT_API -#define CRU_WIN_GRAPHICS_DIRECT_API __declspec(dllexport) -#else -#define CRU_WIN_GRAPHICS_DIRECT_API __declspec(dllimport) -#endif -#else -#define CRU_WIN_GRAPHICS_DIRECT_API -#endif diff --git a/include/cru/win/graphics/direct/Brush.h b/include/cru/win/graphics/direct/Brush.h new file mode 100644 index 00000000..fe5321b7 --- /dev/null +++ b/include/cru/win/graphics/direct/Brush.h @@ -0,0 +1,40 @@ +#pragma once +#include "ComResource.h" +#include "Resource.h" + +#include "cru/platform/graphics/Brush.h" + +namespace cru::platform::graphics::win::direct { +struct CRU_WIN_GRAPHICS_DIRECT_API ID2DBrush : virtual IBrush { + virtual ID2D1Brush* GetD2DBrushInterface() const = 0; +}; + +class CRU_WIN_GRAPHICS_DIRECT_API D2DSolidColorBrush + : public DirectGraphicsResource, + public virtual ISolidColorBrush, + public virtual ID2DBrush, + public virtual IComResource { + public: + explicit D2DSolidColorBrush(DirectGraphicsFactory* factory); + + CRU_DELETE_COPY(D2DSolidColorBrush) + CRU_DELETE_MOVE(D2DSolidColorBrush) + + ~D2DSolidColorBrush() override = default; + + public: + Color GetColor() override { return color_; } + void SetColor(const Color& color) override; + + ID2D1Brush* GetD2DBrushInterface() const override { return brush_.Get(); } + + ID2D1SolidColorBrush* GetComInterface() const override { + return brush_.Get(); + } + + private: + Color color_ = colors::black; + + Microsoft::WRL::ComPtr brush_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Brush.hpp b/include/cru/win/graphics/direct/Brush.hpp deleted file mode 100644 index 22b0a8af..00000000 --- a/include/cru/win/graphics/direct/Brush.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "ComResource.hpp" -#include "Resource.hpp" - -#include "cru/platform/graphics/Brush.hpp" - -namespace cru::platform::graphics::win::direct { -struct CRU_WIN_GRAPHICS_DIRECT_API ID2DBrush : virtual IBrush { - virtual ID2D1Brush* GetD2DBrushInterface() const = 0; -}; - -class CRU_WIN_GRAPHICS_DIRECT_API D2DSolidColorBrush - : public DirectGraphicsResource, - public virtual ISolidColorBrush, - public virtual ID2DBrush, - public virtual IComResource { - public: - explicit D2DSolidColorBrush(DirectGraphicsFactory* factory); - - CRU_DELETE_COPY(D2DSolidColorBrush) - CRU_DELETE_MOVE(D2DSolidColorBrush) - - ~D2DSolidColorBrush() override = default; - - public: - Color GetColor() override { return color_; } - void SetColor(const Color& color) override; - - ID2D1Brush* GetD2DBrushInterface() const override { return brush_.Get(); } - - ID2D1SolidColorBrush* GetComInterface() const override { - return brush_.Get(); - } - - private: - Color color_ = colors::black; - - Microsoft::WRL::ComPtr brush_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/ComResource.h b/include/cru/win/graphics/direct/ComResource.h new file mode 100644 index 00000000..36023b84 --- /dev/null +++ b/include/cru/win/graphics/direct/ComResource.h @@ -0,0 +1,11 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Base.h" + +namespace cru::platform::graphics::win::direct { +template +struct CRU_WIN_GRAPHICS_DIRECT_API IComResource : virtual Interface { + virtual TInterface* GetComInterface() const = 0; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/ComResource.hpp b/include/cru/win/graphics/direct/ComResource.hpp deleted file mode 100644 index f8738f6e..00000000 --- a/include/cru/win/graphics/direct/ComResource.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Base.hpp" - -namespace cru::platform::graphics::win::direct { -template -struct CRU_WIN_GRAPHICS_DIRECT_API IComResource : virtual Interface { - virtual TInterface* GetComInterface() const = 0; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/ConvertUtil.h b/include/cru/win/graphics/direct/ConvertUtil.h new file mode 100644 index 00000000..8066a265 --- /dev/null +++ b/include/cru/win/graphics/direct/ConvertUtil.h @@ -0,0 +1,107 @@ +#pragma once +#include "Base.h" + +#include "cru/platform/graphics/Base.h" + +namespace cru::platform::graphics::win::direct { +inline D2D1_MATRIX_3X2_F Convert(const platform::Matrix& matrix) { + D2D1_MATRIX_3X2_F m; + m._11 = matrix.m11; + m._12 = matrix.m12; + m._21 = matrix.m21; + m._22 = matrix.m22; + m._31 = matrix.m31; + m._32 = matrix.m32; + return m; +} + +inline D2D1_COLOR_F Convert(const Color& color) { + return D2D1::ColorF(color.red / 255.0f, color.green / 255.0f, + color.blue / 255.0f, color.alpha / 255.0f); +} + +inline D2D1_POINT_2F Convert(const Point& point) { + return D2D1::Point2F(point.x, point.y); +} + +inline D2D1_RECT_F Convert(const Rect& rect) { + return D2D1::RectF(rect.left, rect.top, rect.left + rect.width, + rect.top + rect.height); +} + +inline D2D1_ROUNDED_RECT Convert(const RoundedRect& rounded_rect) { + return D2D1::RoundedRect(Convert(rounded_rect.rect), rounded_rect.radius_x, + rounded_rect.radius_y); +} + +inline D2D1_ELLIPSE Convert(const Ellipse& ellipse) { + return D2D1::Ellipse(Convert(ellipse.center), ellipse.radius_x, + ellipse.radius_y); +} + +inline platform::Matrix Convert(const D2D1_MATRIX_3X2_F& matrix) { + return platform::Matrix{matrix._11, matrix._12, matrix._21, + matrix._22, matrix._31, matrix._32}; +} + +inline Color Convert(const D2D1_COLOR_F& color) { + auto floor = [](float n) { return static_cast(n + 0.5f); }; + return Color{floor(color.r * 255.0f), floor(color.g * 255.0f), + floor(color.b * 255.0f), floor(color.a * 255.0f)}; +} + +inline Point Convert(const D2D1_POINT_2F& point) { + return Point(point.x, point.y); +} + +inline Rect Convert(const D2D1_RECT_F& rect) { + return Rect(rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top); +} + +inline RoundedRect Convert(const D2D1_ROUNDED_RECT& rounded_rect) { + return RoundedRect(Convert(rounded_rect.rect), rounded_rect.radiusX, + rounded_rect.radiusY); +} + +inline Ellipse Convert(const D2D1_ELLIPSE& ellipse) { + return Ellipse(Convert(ellipse.point), ellipse.radiusX, ellipse.radiusY); +} + +inline bool operator==(const D2D1_POINT_2F& left, const D2D1_POINT_2F& right) { + return left.x == right.x && left.y == right.y; +} + +inline bool operator!=(const D2D1_POINT_2F& left, const D2D1_POINT_2F& right) { + return !(left == right); +} + +inline bool operator==(const D2D1_RECT_F& left, const D2D1_RECT_F& right) { + return left.left == right.left && left.top == right.top && + left.right == right.right && left.bottom == right.bottom; +} + +inline bool operator!=(const D2D1_RECT_F& left, const D2D1_RECT_F& right) { + return !(left == right); +} + +inline bool operator==(const D2D1_ROUNDED_RECT& left, + const D2D1_ROUNDED_RECT& right) { + return left.rect == right.rect && left.radiusX == right.radiusX && + left.radiusY == right.radiusY; +} + +inline bool operator!=(const D2D1_ROUNDED_RECT& left, + const D2D1_ROUNDED_RECT& right) { + return !(left == right); +} + +inline bool operator==(const D2D1_ELLIPSE& left, const D2D1_ELLIPSE& right) { + return left.point == right.point && left.radiusX == right.radiusX && + left.radiusY == right.radiusY; +} + +inline bool operator!=(const D2D1_ELLIPSE& left, const D2D1_ELLIPSE& right) { + return !(left == right); +} +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/ConvertUtil.hpp b/include/cru/win/graphics/direct/ConvertUtil.hpp deleted file mode 100644 index 963b22f3..00000000 --- a/include/cru/win/graphics/direct/ConvertUtil.hpp +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/platform/graphics/Base.hpp" - -namespace cru::platform::graphics::win::direct { -inline D2D1_MATRIX_3X2_F Convert(const platform::Matrix& matrix) { - D2D1_MATRIX_3X2_F m; - m._11 = matrix.m11; - m._12 = matrix.m12; - m._21 = matrix.m21; - m._22 = matrix.m22; - m._31 = matrix.m31; - m._32 = matrix.m32; - return m; -} - -inline D2D1_COLOR_F Convert(const Color& color) { - return D2D1::ColorF(color.red / 255.0f, color.green / 255.0f, - color.blue / 255.0f, color.alpha / 255.0f); -} - -inline D2D1_POINT_2F Convert(const Point& point) { - return D2D1::Point2F(point.x, point.y); -} - -inline D2D1_RECT_F Convert(const Rect& rect) { - return D2D1::RectF(rect.left, rect.top, rect.left + rect.width, - rect.top + rect.height); -} - -inline D2D1_ROUNDED_RECT Convert(const RoundedRect& rounded_rect) { - return D2D1::RoundedRect(Convert(rounded_rect.rect), rounded_rect.radius_x, - rounded_rect.radius_y); -} - -inline D2D1_ELLIPSE Convert(const Ellipse& ellipse) { - return D2D1::Ellipse(Convert(ellipse.center), ellipse.radius_x, - ellipse.radius_y); -} - -inline platform::Matrix Convert(const D2D1_MATRIX_3X2_F& matrix) { - return platform::Matrix{matrix._11, matrix._12, matrix._21, - matrix._22, matrix._31, matrix._32}; -} - -inline Color Convert(const D2D1_COLOR_F& color) { - auto floor = [](float n) { return static_cast(n + 0.5f); }; - return Color{floor(color.r * 255.0f), floor(color.g * 255.0f), - floor(color.b * 255.0f), floor(color.a * 255.0f)}; -} - -inline Point Convert(const D2D1_POINT_2F& point) { - return Point(point.x, point.y); -} - -inline Rect Convert(const D2D1_RECT_F& rect) { - return Rect(rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top); -} - -inline RoundedRect Convert(const D2D1_ROUNDED_RECT& rounded_rect) { - return RoundedRect(Convert(rounded_rect.rect), rounded_rect.radiusX, - rounded_rect.radiusY); -} - -inline Ellipse Convert(const D2D1_ELLIPSE& ellipse) { - return Ellipse(Convert(ellipse.point), ellipse.radiusX, ellipse.radiusY); -} - -inline bool operator==(const D2D1_POINT_2F& left, const D2D1_POINT_2F& right) { - return left.x == right.x && left.y == right.y; -} - -inline bool operator!=(const D2D1_POINT_2F& left, const D2D1_POINT_2F& right) { - return !(left == right); -} - -inline bool operator==(const D2D1_RECT_F& left, const D2D1_RECT_F& right) { - return left.left == right.left && left.top == right.top && - left.right == right.right && left.bottom == right.bottom; -} - -inline bool operator!=(const D2D1_RECT_F& left, const D2D1_RECT_F& right) { - return !(left == right); -} - -inline bool operator==(const D2D1_ROUNDED_RECT& left, - const D2D1_ROUNDED_RECT& right) { - return left.rect == right.rect && left.radiusX == right.radiusX && - left.radiusY == right.radiusY; -} - -inline bool operator!=(const D2D1_ROUNDED_RECT& left, - const D2D1_ROUNDED_RECT& right) { - return !(left == right); -} - -inline bool operator==(const D2D1_ELLIPSE& left, const D2D1_ELLIPSE& right) { - return left.point == right.point && left.radiusX == right.radiusX && - left.radiusY == right.radiusY; -} - -inline bool operator!=(const D2D1_ELLIPSE& left, const D2D1_ELLIPSE& right) { - return !(left == right); -} -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Exception.h b/include/cru/win/graphics/direct/Exception.h new file mode 100644 index 00000000..21dde875 --- /dev/null +++ b/include/cru/win/graphics/direct/Exception.h @@ -0,0 +1,7 @@ +#pragma once +#include "../../Exception.h" + +namespace cru::platform::graphics::win::direct { +using platform::win::HResultError; +using platform::win::ThrowIfFailed; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Exception.hpp b/include/cru/win/graphics/direct/Exception.hpp deleted file mode 100644 index 72493f2f..00000000 --- a/include/cru/win/graphics/direct/Exception.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "../../Exception.hpp" - -namespace cru::platform::graphics::win::direct { -using platform::win::HResultError; -using platform::win::ThrowIfFailed; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Factory.h b/include/cru/win/graphics/direct/Factory.h new file mode 100644 index 00000000..368c68f0 --- /dev/null +++ b/include/cru/win/graphics/direct/Factory.h @@ -0,0 +1,68 @@ +#pragma once +#include "Resource.h" + +#include "ImageFactory.h" + +#include "cru/common/platform/win/ComAutoInit.h" +#include "cru/platform/graphics/Base.h" +#include "cru/platform/graphics/Factory.h" + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API DirectGraphicsFactory + : public DirectResource, + public virtual IGraphicsFactory { + public: + DirectGraphicsFactory(); + + CRU_DELETE_COPY(DirectGraphicsFactory) + CRU_DELETE_MOVE(DirectGraphicsFactory) + + ~DirectGraphicsFactory() override; + + public: + ID3D11Device* GetD3D11Device() const { return d3d11_device_.Get(); } + ID2D1Factory2* GetD2D1Factory() const { return d2d1_factory_.Get(); } + ID2D1Device1* GetD2D1Device() const { return d2d1_device_.Get(); } + IDXGIFactory2* GetDxgiFactory() const { return dxgi_factory_.Get(); } + IDWriteFactory* GetDWriteFactory() const { return dwrite_factory_.Get(); } + IDWriteFontCollection* GetSystemFontCollection() const { + return dwrite_system_font_collection_.Get(); + } + + public: + Microsoft::WRL::ComPtr CreateD2D1DeviceContext(); + + // This context should only be used to create graphic resources like brush. + // Because graphic resources can be shared if they are created in the same + // device. + ID2D1DeviceContext* GetDefaultD2D1DeviceContext() { + return d2d1_device_context_.Get(); + } + + public: + std::unique_ptr CreateSolidColorBrush() override; + + std::unique_ptr CreateGeometryBuilder() override; + + std::unique_ptr CreateFont(String font_family, + float font_size) override; + + std::unique_ptr CreateTextLayout(std::shared_ptr font, + String text) override; + + IImageFactory* GetImageFactory() override; + + private: + platform::win::ComAutoInit com_auto_init_; + + Microsoft::WRL::ComPtr d3d11_device_; + Microsoft::WRL::ComPtr d2d1_factory_; + Microsoft::WRL::ComPtr d2d1_device_; + Microsoft::WRL::ComPtr d2d1_device_context_; + Microsoft::WRL::ComPtr dxgi_factory_; + Microsoft::WRL::ComPtr dwrite_factory_; + Microsoft::WRL::ComPtr dwrite_system_font_collection_; + + std::unique_ptr image_factory_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Factory.hpp b/include/cru/win/graphics/direct/Factory.hpp deleted file mode 100644 index 4ceed7c5..00000000 --- a/include/cru/win/graphics/direct/Factory.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "ImageFactory.hpp" - -#include "cru/common/platform/win/ComAutoInit.hpp" -#include "cru/platform/graphics/Base.hpp" -#include "cru/platform/graphics/Factory.hpp" - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API DirectGraphicsFactory - : public DirectResource, - public virtual IGraphicsFactory { - public: - DirectGraphicsFactory(); - - CRU_DELETE_COPY(DirectGraphicsFactory) - CRU_DELETE_MOVE(DirectGraphicsFactory) - - ~DirectGraphicsFactory() override; - - public: - ID3D11Device* GetD3D11Device() const { return d3d11_device_.Get(); } - ID2D1Factory2* GetD2D1Factory() const { return d2d1_factory_.Get(); } - ID2D1Device1* GetD2D1Device() const { return d2d1_device_.Get(); } - IDXGIFactory2* GetDxgiFactory() const { return dxgi_factory_.Get(); } - IDWriteFactory* GetDWriteFactory() const { return dwrite_factory_.Get(); } - IDWriteFontCollection* GetSystemFontCollection() const { - return dwrite_system_font_collection_.Get(); - } - - public: - Microsoft::WRL::ComPtr CreateD2D1DeviceContext(); - - // This context should only be used to create graphic resources like brush. - // Because graphic resources can be shared if they are created in the same - // device. - ID2D1DeviceContext* GetDefaultD2D1DeviceContext() { - return d2d1_device_context_.Get(); - } - - public: - std::unique_ptr CreateSolidColorBrush() override; - - std::unique_ptr CreateGeometryBuilder() override; - - std::unique_ptr CreateFont(String font_family, - float font_size) override; - - std::unique_ptr CreateTextLayout(std::shared_ptr font, - String text) override; - - IImageFactory* GetImageFactory() override; - - private: - platform::win::ComAutoInit com_auto_init_; - - Microsoft::WRL::ComPtr d3d11_device_; - Microsoft::WRL::ComPtr d2d1_factory_; - Microsoft::WRL::ComPtr d2d1_device_; - Microsoft::WRL::ComPtr d2d1_device_context_; - Microsoft::WRL::ComPtr dxgi_factory_; - Microsoft::WRL::ComPtr dwrite_factory_; - Microsoft::WRL::ComPtr dwrite_system_font_collection_; - - std::unique_ptr image_factory_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Font.h b/include/cru/win/graphics/direct/Font.h new file mode 100644 index 00000000..e08ec5a3 --- /dev/null +++ b/include/cru/win/graphics/direct/Font.h @@ -0,0 +1,34 @@ +#pragma once +#include "ComResource.h" +#include "Resource.h" + +#include "cru/platform/graphics/Font.h" + +#include + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API DWriteFont + : public DirectGraphicsResource, + public virtual IFont, + public virtual IComResource { + public: + DWriteFont(DirectGraphicsFactory* factory, String font_family, + float font_size); + + CRU_DELETE_COPY(DWriteFont) + CRU_DELETE_MOVE(DWriteFont) + + ~DWriteFont() override = default; + + public: + IDWriteTextFormat* GetComInterface() const override { + return text_format_.Get(); + } + + float GetFontSize() override; + + private: + String font_family_; + Microsoft::WRL::ComPtr text_format_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Font.hpp b/include/cru/win/graphics/direct/Font.hpp deleted file mode 100644 index 3bf423a0..00000000 --- a/include/cru/win/graphics/direct/Font.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "ComResource.hpp" -#include "Resource.hpp" - -#include "cru/platform/graphics/Font.hpp" - -#include - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API DWriteFont - : public DirectGraphicsResource, - public virtual IFont, - public virtual IComResource { - public: - DWriteFont(DirectGraphicsFactory* factory, String font_family, - float font_size); - - CRU_DELETE_COPY(DWriteFont) - CRU_DELETE_MOVE(DWriteFont) - - ~DWriteFont() override = default; - - public: - IDWriteTextFormat* GetComInterface() const override { - return text_format_.Get(); - } - - float GetFontSize() override; - - private: - String font_family_; - Microsoft::WRL::ComPtr text_format_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Geometry.h b/include/cru/win/graphics/direct/Geometry.h new file mode 100644 index 00000000..8e40c383 --- /dev/null +++ b/include/cru/win/graphics/direct/Geometry.h @@ -0,0 +1,59 @@ +#pragma once +#include "ComResource.h" +#include "Resource.h" + +#include "cru/platform/graphics/Geometry.h" + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API D2DGeometryBuilder + : public DirectGraphicsResource, + public virtual IGeometryBuilder { + public: + explicit D2DGeometryBuilder(DirectGraphicsFactory* factory); + + CRU_DELETE_COPY(D2DGeometryBuilder) + CRU_DELETE_MOVE(D2DGeometryBuilder) + + ~D2DGeometryBuilder() override = default; + + public: + void BeginFigure(const Point& point) override; + void LineTo(const Point& point) override; + void QuadraticBezierTo(const Point& control_point, + const Point& end_point) override; + void CloseFigure(bool close) override; + + std::unique_ptr Build() override; + + private: + bool IsValid() { return geometry_ != nullptr; } + void CheckValidation(); + + private: + Microsoft::WRL::ComPtr geometry_; + Microsoft::WRL::ComPtr geometry_sink_; +}; + +class CRU_WIN_GRAPHICS_DIRECT_API D2DGeometry + : public DirectGraphicsResource, + public virtual IGeometry, + public IComResource { + public: + D2DGeometry(DirectGraphicsFactory* factory, + Microsoft::WRL::ComPtr geometry); + + CRU_DELETE_COPY(D2DGeometry) + CRU_DELETE_MOVE(D2DGeometry) + + ~D2DGeometry() override = default; + + public: + ID2D1Geometry* GetComInterface() const override { return geometry_.Get(); } + + public: + bool FillContains(const Point& point) override; + + private: + Microsoft::WRL::ComPtr geometry_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Geometry.hpp b/include/cru/win/graphics/direct/Geometry.hpp deleted file mode 100644 index 3849045e..00000000 --- a/include/cru/win/graphics/direct/Geometry.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include "ComResource.hpp" -#include "Resource.hpp" - -#include "cru/platform/graphics/Geometry.hpp" - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API D2DGeometryBuilder - : public DirectGraphicsResource, - public virtual IGeometryBuilder { - public: - explicit D2DGeometryBuilder(DirectGraphicsFactory* factory); - - CRU_DELETE_COPY(D2DGeometryBuilder) - CRU_DELETE_MOVE(D2DGeometryBuilder) - - ~D2DGeometryBuilder() override = default; - - public: - void BeginFigure(const Point& point) override; - void LineTo(const Point& point) override; - void QuadraticBezierTo(const Point& control_point, - const Point& end_point) override; - void CloseFigure(bool close) override; - - std::unique_ptr Build() override; - - private: - bool IsValid() { return geometry_ != nullptr; } - void CheckValidation(); - - private: - Microsoft::WRL::ComPtr geometry_; - Microsoft::WRL::ComPtr geometry_sink_; -}; - -class CRU_WIN_GRAPHICS_DIRECT_API D2DGeometry - : public DirectGraphicsResource, - public virtual IGeometry, - public IComResource { - public: - D2DGeometry(DirectGraphicsFactory* factory, - Microsoft::WRL::ComPtr geometry); - - CRU_DELETE_COPY(D2DGeometry) - CRU_DELETE_MOVE(D2DGeometry) - - ~D2DGeometry() override = default; - - public: - ID2D1Geometry* GetComInterface() const override { return geometry_.Get(); } - - public: - bool FillContains(const Point& point) override; - - private: - Microsoft::WRL::ComPtr geometry_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Image.h b/include/cru/win/graphics/direct/Image.h new file mode 100644 index 00000000..0b51f350 --- /dev/null +++ b/include/cru/win/graphics/direct/Image.h @@ -0,0 +1,31 @@ +#pragma once +#include "Resource.h" +#include "cru/platform/graphics/Image.h" + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API Direct2DImage : public DirectGraphicsResource, + public virtual IImage { + public: + Direct2DImage(DirectGraphicsFactory* graphics_factory, + Microsoft::WRL::ComPtr d2d_bitmap); + + CRU_DELETE_COPY(Direct2DImage) + CRU_DELETE_MOVE(Direct2DImage) + + ~Direct2DImage() override; + + public: + float GetWidth() override; + float GetHeight() override; + + std::unique_ptr CreateWithRect(const Rect& rect) override; + + const Microsoft::WRL::ComPtr& GetD2DBitmap() const { + return d2d_bitmap_; + } + + private: + Microsoft::WRL::ComPtr d2d_bitmap_; +}; + +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Image.hpp b/include/cru/win/graphics/direct/Image.hpp deleted file mode 100644 index 06448621..00000000 --- a/include/cru/win/graphics/direct/Image.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/platform/graphics/Image.hpp" - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API Direct2DImage : public DirectGraphicsResource, - public virtual IImage { - public: - Direct2DImage(DirectGraphicsFactory* graphics_factory, - Microsoft::WRL::ComPtr d2d_bitmap); - - CRU_DELETE_COPY(Direct2DImage) - CRU_DELETE_MOVE(Direct2DImage) - - ~Direct2DImage() override; - - public: - float GetWidth() override; - float GetHeight() override; - - std::unique_ptr CreateWithRect(const Rect& rect) override; - - const Microsoft::WRL::ComPtr& GetD2DBitmap() const { - return d2d_bitmap_; - } - - private: - Microsoft::WRL::ComPtr d2d_bitmap_; -}; - -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/ImageFactory.h b/include/cru/win/graphics/direct/ImageFactory.h new file mode 100644 index 00000000..34d363b0 --- /dev/null +++ b/include/cru/win/graphics/direct/ImageFactory.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Resource.h" +#include "cru/platform/graphics/Image.h" +#include "cru/platform/graphics/ImageFactory.h" + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API WinImageFactory + : public DirectGraphicsResource, + public virtual IImageFactory { + public: + explicit WinImageFactory(DirectGraphicsFactory* graphics_factory); + + CRU_DELETE_COPY(WinImageFactory) + CRU_DELETE_MOVE(WinImageFactory) + + ~WinImageFactory() override; + + public: + std::unique_ptr DecodeFromStream(io::Stream* stream) override; + + private: + DirectGraphicsFactory* graphics_factory_; + + Microsoft::WRL::ComPtr wic_imaging_factory_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/ImageFactory.hpp b/include/cru/win/graphics/direct/ImageFactory.hpp deleted file mode 100644 index fa450039..00000000 --- a/include/cru/win/graphics/direct/ImageFactory.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "Resource.hpp" -#include "cru/platform/graphics/Image.hpp" -#include "cru/platform/graphics/ImageFactory.hpp" - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API WinImageFactory - : public DirectGraphicsResource, - public virtual IImageFactory { - public: - explicit WinImageFactory(DirectGraphicsFactory* graphics_factory); - - CRU_DELETE_COPY(WinImageFactory) - CRU_DELETE_MOVE(WinImageFactory) - - ~WinImageFactory() override; - - public: - std::unique_ptr DecodeFromStream(io::Stream* stream) override; - - private: - DirectGraphicsFactory* graphics_factory_; - - Microsoft::WRL::ComPtr wic_imaging_factory_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Painter.h b/include/cru/win/graphics/direct/Painter.h new file mode 100644 index 00000000..b1795395 --- /dev/null +++ b/include/cru/win/graphics/direct/Painter.h @@ -0,0 +1,75 @@ +#pragma once +#include "ComResource.h" +#include "Resource.h" + +#include "cru/platform/graphics/Painter.h" + +#include + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API D2DDeviceContextPainter + : public DirectResource, + public virtual IPainter, + public virtual IComResource { + public: + explicit D2DDeviceContextPainter(ID2D1DeviceContext1* device_context); + + CRU_DELETE_COPY(D2DDeviceContextPainter) + CRU_DELETE_MOVE(D2DDeviceContextPainter) + + ~D2DDeviceContextPainter() override = default; + + public: + ID2D1DeviceContext1* GetComInterface() const override { + return device_context_; + } + + public: + Matrix GetTransform() override; + void SetTransform(const platform::Matrix& matrix) override; + void ConcatTransform(const Matrix& matrix) override; + + void Clear(const Color& color) override; + + void DrawLine(const Point& start, const Point& end, IBrush* brush, + float width) override; + void StrokeRectangle(const Rect& rectangle, IBrush* brush, + float width) override; + void FillRectangle(const Rect& rectangle, IBrush* brush) override; + void StrokeEllipse(const Rect& outline_rect, IBrush* brush, + float width) override; + void FillEllipse(const Rect& outline_rect, IBrush* brush) override; + + void StrokeGeometry(IGeometry* geometry, IBrush* brush, float width) override; + void FillGeometry(IGeometry* geometry, IBrush* brush) override; + + void DrawText(const Point& offset, ITextLayout* text_layout, + IBrush* brush) override; + + void DrawImage(const Point& offset, IImage* image) override; + + void PushLayer(const Rect& bounds) override; + void PopLayer() override; + + void PushState() override; + void PopState() override; + + void EndDraw() override final; + + protected: + virtual void DoEndDraw() = 0; + + private: + bool IsValid() { return is_drawing_; } + void CheckValidation(); + + private: + ID2D1DeviceContext1* device_context_; + + std::vector> layers_; + std::vector> + drawing_state_stack_; + + bool is_drawing_ = true; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Painter.hpp b/include/cru/win/graphics/direct/Painter.hpp deleted file mode 100644 index 57a59357..00000000 --- a/include/cru/win/graphics/direct/Painter.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once -#include "ComResource.hpp" -#include "Resource.hpp" - -#include "cru/platform/graphics/Painter.hpp" - -#include - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API D2DDeviceContextPainter - : public DirectResource, - public virtual IPainter, - public virtual IComResource { - public: - explicit D2DDeviceContextPainter(ID2D1DeviceContext1* device_context); - - CRU_DELETE_COPY(D2DDeviceContextPainter) - CRU_DELETE_MOVE(D2DDeviceContextPainter) - - ~D2DDeviceContextPainter() override = default; - - public: - ID2D1DeviceContext1* GetComInterface() const override { - return device_context_; - } - - public: - Matrix GetTransform() override; - void SetTransform(const platform::Matrix& matrix) override; - void ConcatTransform(const Matrix& matrix) override; - - void Clear(const Color& color) override; - - void DrawLine(const Point& start, const Point& end, IBrush* brush, - float width) override; - void StrokeRectangle(const Rect& rectangle, IBrush* brush, - float width) override; - void FillRectangle(const Rect& rectangle, IBrush* brush) override; - void StrokeEllipse(const Rect& outline_rect, IBrush* brush, - float width) override; - void FillEllipse(const Rect& outline_rect, IBrush* brush) override; - - void StrokeGeometry(IGeometry* geometry, IBrush* brush, float width) override; - void FillGeometry(IGeometry* geometry, IBrush* brush) override; - - void DrawText(const Point& offset, ITextLayout* text_layout, - IBrush* brush) override; - - void DrawImage(const Point& offset, IImage* image) override; - - void PushLayer(const Rect& bounds) override; - void PopLayer() override; - - void PushState() override; - void PopState() override; - - void EndDraw() override final; - - protected: - virtual void DoEndDraw() = 0; - - private: - bool IsValid() { return is_drawing_; } - void CheckValidation(); - - private: - ID2D1DeviceContext1* device_context_; - - std::vector> layers_; - std::vector> - drawing_state_stack_; - - bool is_drawing_ = true; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Resource.h b/include/cru/win/graphics/direct/Resource.h new file mode 100644 index 00000000..df558686 --- /dev/null +++ b/include/cru/win/graphics/direct/Resource.h @@ -0,0 +1,52 @@ +#pragma once +#include "Base.h" + +#include "cru/platform/graphics/Resource.h" + +#include + +namespace cru::platform::graphics::win::direct { +class DirectGraphicsFactory; + +class CRU_WIN_GRAPHICS_DIRECT_API DirectResource + : public Object, + public virtual IPlatformResource { + public: + static String kPlatformId; + + protected: + DirectResource() = default; + + public: + CRU_DELETE_COPY(DirectResource) + CRU_DELETE_MOVE(DirectResource) + + ~DirectResource() override = default; + + public: + String GetPlatformId() const final { return kPlatformId; } +}; + +class CRU_WIN_GRAPHICS_DIRECT_API DirectGraphicsResource + : public DirectResource, + public virtual IGraphicsResource { + protected: + // Param factory can't be null. + explicit DirectGraphicsResource(DirectGraphicsFactory* factory); + + public: + CRU_DELETE_COPY(DirectGraphicsResource) + CRU_DELETE_MOVE(DirectGraphicsResource) + + ~DirectGraphicsResource() override = default; + + public: + IGraphicsFactory* GetGraphicsFactory() final; + + public: + DirectGraphicsFactory* GetDirectFactory() const { return factory_; } + + private: + DirectGraphicsFactory* factory_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/Resource.hpp b/include/cru/win/graphics/direct/Resource.hpp deleted file mode 100644 index 112af26f..00000000 --- a/include/cru/win/graphics/direct/Resource.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/platform/graphics/Resource.hpp" - -#include - -namespace cru::platform::graphics::win::direct { -class DirectGraphicsFactory; - -class CRU_WIN_GRAPHICS_DIRECT_API DirectResource - : public Object, - public virtual IPlatformResource { - public: - static String kPlatformId; - - protected: - DirectResource() = default; - - public: - CRU_DELETE_COPY(DirectResource) - CRU_DELETE_MOVE(DirectResource) - - ~DirectResource() override = default; - - public: - String GetPlatformId() const final { return kPlatformId; } -}; - -class CRU_WIN_GRAPHICS_DIRECT_API DirectGraphicsResource - : public DirectResource, - public virtual IGraphicsResource { - protected: - // Param factory can't be null. - explicit DirectGraphicsResource(DirectGraphicsFactory* factory); - - public: - CRU_DELETE_COPY(DirectGraphicsResource) - CRU_DELETE_MOVE(DirectGraphicsResource) - - ~DirectGraphicsResource() override = default; - - public: - IGraphicsFactory* GetGraphicsFactory() final; - - public: - DirectGraphicsFactory* GetDirectFactory() const { return factory_; } - - private: - DirectGraphicsFactory* factory_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/TextLayout.h b/include/cru/win/graphics/direct/TextLayout.h new file mode 100644 index 00000000..fca5d68f --- /dev/null +++ b/include/cru/win/graphics/direct/TextLayout.h @@ -0,0 +1,63 @@ +#pragma once +#include "ComResource.h" +#include "Resource.h" + +#include "cru/platform/graphics/TextLayout.h" + +#include +#include + +namespace cru::platform::graphics::win::direct { +class DWriteFont; + +class CRU_WIN_GRAPHICS_DIRECT_API DWriteTextLayout + : public DirectGraphicsResource, + public virtual ITextLayout, + public virtual IComResource { + public: + DWriteTextLayout(DirectGraphicsFactory* factory, std::shared_ptr font, + String text); + + CRU_DELETE_COPY(DWriteTextLayout) + CRU_DELETE_MOVE(DWriteTextLayout) + + ~DWriteTextLayout() override; + + public: + IDWriteTextLayout* GetComInterface() const override { + return text_layout_.Get(); + } + + public: + String GetText() override; + void SetText(String new_text) override; + + std::shared_ptr GetFont() override; + void SetFont(std::shared_ptr font) override; + + void SetMaxWidth(float max_width) override; + void SetMaxHeight(float max_height) override; + + bool IsEditMode() override; + void SetEditMode(bool enable) override; + + Index GetLineIndexFromCharIndex(Index char_index) override; + float GetLineHeight(Index line_index) override; + Index GetLineCount() override; + + Rect GetTextBounds(bool includingTrailingSpace = false) override; + // Return empty vector if text_range.count is 0. Text range could be in + // reverse direction, it should be normalized first in implementation. + std::vector TextRangeRect(const TextRange& text_range) override; + Rect TextSinglePoint(Index position, bool trailing) override; + TextHitTestResult HitTest(const Point& point) override; + + private: + bool edit_mode_ = false; + String text_; + std::shared_ptr font_; + float max_width_ = std::numeric_limits::max(); + float max_height_ = std::numeric_limits::max(); + Microsoft::WRL::ComPtr text_layout_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/TextLayout.hpp b/include/cru/win/graphics/direct/TextLayout.hpp deleted file mode 100644 index 41698862..00000000 --- a/include/cru/win/graphics/direct/TextLayout.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include "ComResource.hpp" -#include "Resource.hpp" - -#include "cru/platform/graphics/TextLayout.hpp" - -#include -#include - -namespace cru::platform::graphics::win::direct { -class DWriteFont; - -class CRU_WIN_GRAPHICS_DIRECT_API DWriteTextLayout - : public DirectGraphicsResource, - public virtual ITextLayout, - public virtual IComResource { - public: - DWriteTextLayout(DirectGraphicsFactory* factory, std::shared_ptr font, - String text); - - CRU_DELETE_COPY(DWriteTextLayout) - CRU_DELETE_MOVE(DWriteTextLayout) - - ~DWriteTextLayout() override; - - public: - IDWriteTextLayout* GetComInterface() const override { - return text_layout_.Get(); - } - - public: - String GetText() override; - void SetText(String new_text) override; - - std::shared_ptr GetFont() override; - void SetFont(std::shared_ptr font) override; - - void SetMaxWidth(float max_width) override; - void SetMaxHeight(float max_height) override; - - bool IsEditMode() override; - void SetEditMode(bool enable) override; - - Index GetLineIndexFromCharIndex(Index char_index) override; - float GetLineHeight(Index line_index) override; - Index GetLineCount() override; - - Rect GetTextBounds(bool includingTrailingSpace = false) override; - // Return empty vector if text_range.count is 0. Text range could be in - // reverse direction, it should be normalized first in implementation. - std::vector TextRangeRect(const TextRange& text_range) override; - Rect TextSinglePoint(Index position, bool trailing) override; - TextHitTestResult HitTest(const Point& point) override; - - private: - bool edit_mode_ = false; - String text_; - std::shared_ptr font_; - float max_width_ = std::numeric_limits::max(); - float max_height_ = std::numeric_limits::max(); - Microsoft::WRL::ComPtr text_layout_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/WindowPainter.h b/include/cru/win/graphics/direct/WindowPainter.h new file mode 100644 index 00000000..67ff91e1 --- /dev/null +++ b/include/cru/win/graphics/direct/WindowPainter.h @@ -0,0 +1,22 @@ +#pragma once +#include "Painter.h" +#include "WindowRenderTarget.h" + +namespace cru::platform::graphics::win::direct { +class CRU_WIN_GRAPHICS_DIRECT_API D2DWindowPainter + : public graphics::win::direct::D2DDeviceContextPainter { + public: + explicit D2DWindowPainter(D2DWindowRenderTarget* window); + + CRU_DELETE_COPY(D2DWindowPainter) + CRU_DELETE_MOVE(D2DWindowPainter) + + ~D2DWindowPainter() override; + + protected: + void DoEndDraw() override; + + private: + D2DWindowRenderTarget* render_target_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/WindowPainter.hpp b/include/cru/win/graphics/direct/WindowPainter.hpp deleted file mode 100644 index 3d66bc2e..00000000 --- a/include/cru/win/graphics/direct/WindowPainter.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "Painter.hpp" -#include "WindowRenderTarget.hpp" - -namespace cru::platform::graphics::win::direct { -class CRU_WIN_GRAPHICS_DIRECT_API D2DWindowPainter - : public graphics::win::direct::D2DDeviceContextPainter { - public: - explicit D2DWindowPainter(D2DWindowRenderTarget* window); - - CRU_DELETE_COPY(D2DWindowPainter) - CRU_DELETE_MOVE(D2DWindowPainter) - - ~D2DWindowPainter() override; - - protected: - void DoEndDraw() override; - - private: - D2DWindowRenderTarget* render_target_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/WindowRenderTarget.h b/include/cru/win/graphics/direct/WindowRenderTarget.h new file mode 100644 index 00000000..c588f261 --- /dev/null +++ b/include/cru/win/graphics/direct/WindowRenderTarget.h @@ -0,0 +1,43 @@ +#pragma once +#include "Factory.h" + +namespace cru::platform::graphics::win::direct { +// Represents a window render target. +class CRU_WIN_GRAPHICS_DIRECT_API D2DWindowRenderTarget : public Object { + public: + D2DWindowRenderTarget(gsl::not_null factory, + HWND hwnd); + + CRU_DELETE_COPY(D2DWindowRenderTarget) + CRU_DELETE_MOVE(D2DWindowRenderTarget) + + ~D2DWindowRenderTarget() override = default; + + public: + graphics::win::direct::DirectGraphicsFactory* GetDirectFactory() const { + return factory_; + } + + ID2D1DeviceContext1* GetD2D1DeviceContext() { + return d2d1_device_context_.Get(); + } + + void SetDpi(float x, float y); + + // Resize the underlying buffer. + void ResizeBuffer(int width, int height); + + // Present the data of the underlying buffer to the window. + void Present(); + + private: + void CreateTargetBitmap(); + + private: + DirectGraphicsFactory* factory_; + HWND hwnd_; + Microsoft::WRL::ComPtr d2d1_device_context_; + Microsoft::WRL::ComPtr dxgi_swap_chain_; + Microsoft::WRL::ComPtr target_bitmap_; +}; +} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/graphics/direct/WindowRenderTarget.hpp b/include/cru/win/graphics/direct/WindowRenderTarget.hpp deleted file mode 100644 index 6b775241..00000000 --- a/include/cru/win/graphics/direct/WindowRenderTarget.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "Factory.hpp" - -namespace cru::platform::graphics::win::direct { -// Represents a window render target. -class CRU_WIN_GRAPHICS_DIRECT_API D2DWindowRenderTarget : public Object { - public: - D2DWindowRenderTarget(gsl::not_null factory, - HWND hwnd); - - CRU_DELETE_COPY(D2DWindowRenderTarget) - CRU_DELETE_MOVE(D2DWindowRenderTarget) - - ~D2DWindowRenderTarget() override = default; - - public: - graphics::win::direct::DirectGraphicsFactory* GetDirectFactory() const { - return factory_; - } - - ID2D1DeviceContext1* GetD2D1DeviceContext() { - return d2d1_device_context_.Get(); - } - - void SetDpi(float x, float y); - - // Resize the underlying buffer. - void ResizeBuffer(int width, int height); - - // Present the data of the underlying buffer to the window. - void Present(); - - private: - void CreateTargetBitmap(); - - private: - DirectGraphicsFactory* factory_; - HWND hwnd_; - Microsoft::WRL::ComPtr d2d1_device_context_; - Microsoft::WRL::ComPtr dxgi_swap_chain_; - Microsoft::WRL::ComPtr target_bitmap_; -}; -} // namespace cru::platform::graphics::win::direct diff --git a/include/cru/win/gui/Base.h b/include/cru/win/gui/Base.h new file mode 100644 index 00000000..ab915c57 --- /dev/null +++ b/include/cru/win/gui/Base.h @@ -0,0 +1,27 @@ +#pragma once +#include "../WinPreConfig.h" + +#include "cru/common/Base.h" + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_WIN_GUI_EXPORT_API +#define CRU_WIN_GUI_API __declspec(dllexport) +#else +#define CRU_WIN_GUI_API __declspec(dllimport) +#endif +#else +#define CRU_WIN_GUI_API +#endif + +namespace cru::platform::gui::win { +class GodWindow; +class TimerManager; +class WinCursor; +class WinCursorManager; +class WindowClass; +class WindowManager; +class WinNativeWindow; +class WinUiApplication; +class WinInputMethodContext; +class WinClipboard; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Base.hpp b/include/cru/win/gui/Base.hpp deleted file mode 100644 index 2a0d0247..00000000 --- a/include/cru/win/gui/Base.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "../WinPreConfig.hpp" - -#include "cru/common/Base.hpp" - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_WIN_GUI_EXPORT_API -#define CRU_WIN_GUI_API __declspec(dllexport) -#else -#define CRU_WIN_GUI_API __declspec(dllimport) -#endif -#else -#define CRU_WIN_GUI_API -#endif - -namespace cru::platform::gui::win { -class GodWindow; -class TimerManager; -class WinCursor; -class WinCursorManager; -class WindowClass; -class WindowManager; -class WinNativeWindow; -class WinUiApplication; -class WinInputMethodContext; -class WinClipboard; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Clipboard.h b/include/cru/win/gui/Clipboard.h new file mode 100644 index 00000000..7580642b --- /dev/null +++ b/include/cru/win/gui/Clipboard.h @@ -0,0 +1,24 @@ +#pragma once +#include "Resource.h" +#include "cru/common/Base.h" +#include "cru/platform/gui/Clipboard.h" +#include "cru/win/gui/Base.h" + +namespace cru::platform::gui::win { +class WinClipboard : public WinNativeResource, public virtual IClipboard { + public: + explicit WinClipboard(WinUiApplication* application); + + CRU_DELETE_COPY(WinClipboard) + CRU_DELETE_MOVE(WinClipboard) + + ~WinClipboard() override; + + public: + String GetText() override; + void SetText(String text) override; + + private: + WinUiApplication* application_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Clipboard.hpp b/include/cru/win/gui/Clipboard.hpp deleted file mode 100644 index 63d4906a..00000000 --- a/include/cru/win/gui/Clipboard.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Resource.hpp" -#include "cru/common/Base.hpp" -#include "cru/platform/gui/Clipboard.hpp" -#include "cru/win/gui/Base.hpp" - -namespace cru::platform::gui::win { -class WinClipboard : public WinNativeResource, public virtual IClipboard { - public: - explicit WinClipboard(WinUiApplication* application); - - CRU_DELETE_COPY(WinClipboard) - CRU_DELETE_MOVE(WinClipboard) - - ~WinClipboard() override; - - public: - String GetText() override; - void SetText(String text) override; - - private: - WinUiApplication* application_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Cursor.h b/include/cru/win/gui/Cursor.h new file mode 100644 index 00000000..7a9a2198 --- /dev/null +++ b/include/cru/win/gui/Cursor.h @@ -0,0 +1,51 @@ +#pragma once +#include "Resource.h" + +#include "cru/platform/gui/Cursor.h" + +#include + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API WinCursor : public WinNativeResource, + public virtual ICursor { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinCursor") + + public: + WinCursor(HCURSOR handle, bool auto_destroy); + + CRU_DELETE_COPY(WinCursor) + CRU_DELETE_MOVE(WinCursor) + + ~WinCursor() override; + + public: + HCURSOR GetHandle() const { return handle_; } + + private: + HCURSOR handle_; + bool auto_destroy_; +}; + +class WinCursorManager : public WinNativeResource, + public virtual ICursorManager { + public: + WinCursorManager(); + + CRU_DELETE_COPY(WinCursorManager) + CRU_DELETE_MOVE(WinCursorManager) + + ~WinCursorManager() override = default; + + public: + std::shared_ptr GetSystemWinCursor(SystemCursorType type); + + std::shared_ptr GetSystemCursor(SystemCursorType type) override { + return std::static_pointer_cast(GetSystemWinCursor(type)); + } + + private: + std::shared_ptr sys_arrow_; + std::shared_ptr sys_hand_; + std::shared_ptr sys_ibeam_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Cursor.hpp b/include/cru/win/gui/Cursor.hpp deleted file mode 100644 index 89f61db9..00000000 --- a/include/cru/win/gui/Cursor.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "cru/platform/gui/Cursor.hpp" - -#include - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API WinCursor : public WinNativeResource, - public virtual ICursor { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinCursor") - - public: - WinCursor(HCURSOR handle, bool auto_destroy); - - CRU_DELETE_COPY(WinCursor) - CRU_DELETE_MOVE(WinCursor) - - ~WinCursor() override; - - public: - HCURSOR GetHandle() const { return handle_; } - - private: - HCURSOR handle_; - bool auto_destroy_; -}; - -class WinCursorManager : public WinNativeResource, - public virtual ICursorManager { - public: - WinCursorManager(); - - CRU_DELETE_COPY(WinCursorManager) - CRU_DELETE_MOVE(WinCursorManager) - - ~WinCursorManager() override = default; - - public: - std::shared_ptr GetSystemWinCursor(SystemCursorType type); - - std::shared_ptr GetSystemCursor(SystemCursorType type) override { - return std::static_pointer_cast(GetSystemWinCursor(type)); - } - - private: - std::shared_ptr sys_arrow_; - std::shared_ptr sys_hand_; - std::shared_ptr sys_ibeam_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Exception.h b/include/cru/win/gui/Exception.h new file mode 100644 index 00000000..99ed5863 --- /dev/null +++ b/include/cru/win/gui/Exception.h @@ -0,0 +1,7 @@ +#pragma once +#include "../Exception.h" + +namespace cru::platform::gui::win { +using platform::win::Win32Error; +using platform::win::HResultError; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Exception.hpp b/include/cru/win/gui/Exception.hpp deleted file mode 100644 index 895e6c14..00000000 --- a/include/cru/win/gui/Exception.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "../Exception.hpp" - -namespace cru::platform::gui::win { -using platform::win::Win32Error; -using platform::win::HResultError; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/GodWindow.h b/include/cru/win/gui/GodWindow.h new file mode 100644 index 00000000..63051245 --- /dev/null +++ b/include/cru/win/gui/GodWindow.h @@ -0,0 +1,39 @@ +#pragma once +#include "Base.h" + +#include "WindowNativeMessageEventArgs.h" +#include "cru/common/Event.h" +#include "cru/common/String.h" + +#include + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API GodWindow : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::GodWindow") + + public: + explicit GodWindow(WinUiApplication* application); + + CRU_DELETE_COPY(GodWindow) + CRU_DELETE_MOVE(GodWindow) + + ~GodWindow() override; + + HWND GetHandle() const { return hwnd_; } + + bool HandleGodWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, + LPARAM l_param, LRESULT* result); + + IEvent* MessageEvent() { + return &message_event_; + } + + private: + WinUiApplication* application_; + + std::unique_ptr god_window_class_; + HWND hwnd_; + + Event message_event_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/GodWindow.hpp b/include/cru/win/gui/GodWindow.hpp deleted file mode 100644 index fa69cb84..00000000 --- a/include/cru/win/gui/GodWindow.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "WindowNativeMessageEventArgs.hpp" -#include "cru/common/Event.hpp" -#include "cru/common/String.hpp" - -#include - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API GodWindow : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::GodWindow") - - public: - explicit GodWindow(WinUiApplication* application); - - CRU_DELETE_COPY(GodWindow) - CRU_DELETE_MOVE(GodWindow) - - ~GodWindow() override; - - HWND GetHandle() const { return hwnd_; } - - bool HandleGodWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, - LPARAM l_param, LRESULT* result); - - IEvent* MessageEvent() { - return &message_event_; - } - - private: - WinUiApplication* application_; - - std::unique_ptr god_window_class_; - HWND hwnd_; - - Event message_event_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/InputMethod.h b/include/cru/win/gui/InputMethod.h new file mode 100644 index 00000000..27a621be --- /dev/null +++ b/include/cru/win/gui/InputMethod.h @@ -0,0 +1,88 @@ +// Some useful information can be found from chromium code: +// https://chromium.googlesource.com/chromium/chromium/+/refs/heads/master/ui/base/win/ime_input.h +// https://chromium.googlesource.com/chromium/chromium/+/refs/heads/master/ui/base/win/ime_input.cc + +#pragma once +#include "Resource.h" + +#include "WindowNativeMessageEventArgs.h" +#include "cru/platform/gui/InputMethod.h" + +#include + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API AutoHIMC : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::AutoHIMC") + + public: + explicit AutoHIMC(HWND hwnd); + + CRU_DELETE_COPY(AutoHIMC) + + AutoHIMC(AutoHIMC&& other); + AutoHIMC& operator=(AutoHIMC&& other); + + ~AutoHIMC() override; + + HWND GetHwnd() const { return hwnd_; } + + HIMC Get() const { return handle_; } + + private: + HWND hwnd_; + HIMC handle_; +}; + +class CRU_WIN_GUI_API WinInputMethodContext + : public WinNativeResource, + public virtual IInputMethodContext { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinInputMethodContext") + + public: + WinInputMethodContext(gsl::not_null window); + + CRU_DELETE_COPY(WinInputMethodContext) + CRU_DELETE_MOVE(WinInputMethodContext) + + ~WinInputMethodContext() override; + + bool ShouldManuallyDrawCompositionText() override { return true; } + + void EnableIME() override; + + void DisableIME() override; + + void CompleteComposition() override; + + void CancelComposition() override; + + CompositionText GetCompositionText() override; + + void SetCandidateWindowPosition(const Point& point) override; + + IEvent* CompositionStartEvent() override; + + IEvent* CompositionEndEvent() override; + + IEvent* CompositionEvent() override; + + IEvent* TextEvent() override; + + private: + void OnWindowNativeMessage(WindowNativeMessageEventArgs& args); + + String GetResultString(); + + AutoHIMC GetHIMC(); + + private: + WinNativeWindow* native_window_; + + EventRevokerListGuard event_guard_; + + Event composition_start_event_; + Event composition_end_event_; + Event composition_event_; + Event text_event_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/InputMethod.hpp b/include/cru/win/gui/InputMethod.hpp deleted file mode 100644 index 0f50c0aa..00000000 --- a/include/cru/win/gui/InputMethod.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// Some useful information can be found from chromium code: -// https://chromium.googlesource.com/chromium/chromium/+/refs/heads/master/ui/base/win/ime_input.h -// https://chromium.googlesource.com/chromium/chromium/+/refs/heads/master/ui/base/win/ime_input.cc - -#pragma once -#include "Resource.hpp" - -#include "WindowNativeMessageEventArgs.hpp" -#include "cru/platform/gui/InputMethod.hpp" - -#include - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API AutoHIMC : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::AutoHIMC") - - public: - explicit AutoHIMC(HWND hwnd); - - CRU_DELETE_COPY(AutoHIMC) - - AutoHIMC(AutoHIMC&& other); - AutoHIMC& operator=(AutoHIMC&& other); - - ~AutoHIMC() override; - - HWND GetHwnd() const { return hwnd_; } - - HIMC Get() const { return handle_; } - - private: - HWND hwnd_; - HIMC handle_; -}; - -class CRU_WIN_GUI_API WinInputMethodContext - : public WinNativeResource, - public virtual IInputMethodContext { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinInputMethodContext") - - public: - WinInputMethodContext(gsl::not_null window); - - CRU_DELETE_COPY(WinInputMethodContext) - CRU_DELETE_MOVE(WinInputMethodContext) - - ~WinInputMethodContext() override; - - bool ShouldManuallyDrawCompositionText() override { return true; } - - void EnableIME() override; - - void DisableIME() override; - - void CompleteComposition() override; - - void CancelComposition() override; - - CompositionText GetCompositionText() override; - - void SetCandidateWindowPosition(const Point& point) override; - - IEvent* CompositionStartEvent() override; - - IEvent* CompositionEndEvent() override; - - IEvent* CompositionEvent() override; - - IEvent* TextEvent() override; - - private: - void OnWindowNativeMessage(WindowNativeMessageEventArgs& args); - - String GetResultString(); - - AutoHIMC GetHIMC(); - - private: - WinNativeWindow* native_window_; - - EventRevokerListGuard event_guard_; - - Event composition_start_event_; - Event composition_end_event_; - Event composition_event_; - Event text_event_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Keyboard.h b/include/cru/win/gui/Keyboard.h new file mode 100644 index 00000000..18b37b60 --- /dev/null +++ b/include/cru/win/gui/Keyboard.h @@ -0,0 +1,9 @@ +#pragma once +#include "Base.h" + +#include "cru/platform/gui/Keyboard.h" + +namespace cru::platform::gui::win { +KeyCode CRU_WIN_GUI_API VirtualKeyToKeyCode(int virtual_key); +KeyModifier CRU_WIN_GUI_API RetrieveKeyMofifier(); +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Keyboard.hpp b/include/cru/win/gui/Keyboard.hpp deleted file mode 100644 index d736966a..00000000 --- a/include/cru/win/gui/Keyboard.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/platform/gui/Keyboard.hpp" - -namespace cru::platform::gui::win { -KeyCode CRU_WIN_GUI_API VirtualKeyToKeyCode(int virtual_key); -KeyModifier CRU_WIN_GUI_API RetrieveKeyMofifier(); -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Resource.h b/include/cru/win/gui/Resource.h new file mode 100644 index 00000000..ed43bec3 --- /dev/null +++ b/include/cru/win/gui/Resource.h @@ -0,0 +1,24 @@ +#pragma once +#include "Base.h" + +#include "cru/platform/Resource.h" + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API WinNativeResource : public Object, + public virtual IPlatformResource { + public: + static String kPlatformId; + + protected: + WinNativeResource() = default; + + public: + CRU_DELETE_COPY(WinNativeResource) + CRU_DELETE_MOVE(WinNativeResource) + + ~WinNativeResource() override = default; + + public: + String GetPlatformId() const final { return kPlatformId; } +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Resource.hpp b/include/cru/win/gui/Resource.hpp deleted file mode 100644 index 34c4fc1b..00000000 --- a/include/cru/win/gui/Resource.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/platform/Resource.hpp" - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API WinNativeResource : public Object, - public virtual IPlatformResource { - public: - static String kPlatformId; - - protected: - WinNativeResource() = default; - - public: - CRU_DELETE_COPY(WinNativeResource) - CRU_DELETE_MOVE(WinNativeResource) - - ~WinNativeResource() override = default; - - public: - String GetPlatformId() const final { return kPlatformId; } -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/UiApplication.h b/include/cru/win/gui/UiApplication.h new file mode 100644 index 00000000..a4dfcf3d --- /dev/null +++ b/include/cru/win/gui/UiApplication.h @@ -0,0 +1,87 @@ +#pragma once +#include "Resource.h" + +#include "cru/platform/gui/Base.h" +#include "cru/platform/gui/UiApplication.h" + +#include + +namespace cru::platform::graphics::win::direct { +class DirectGraphicsFactory; +} + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API WinUiApplication : public WinNativeResource, + public virtual IUiApplication { + public: + static WinUiApplication* GetInstance() { return instance; } + + private: + static WinUiApplication* instance; + + public: + WinUiApplication(); + + CRU_DELETE_COPY(WinUiApplication) + CRU_DELETE_MOVE(WinUiApplication) + + ~WinUiApplication() override; + + public: + int Run() override; + void RequestQuit(int quit_code) override; + + void AddOnQuitHandler(std::function handler) override; + + bool IsQuitOnAllWindowClosed() override { + return is_quit_on_all_window_closed_; + } + void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) override { + is_quit_on_all_window_closed_ = quit_on_all_window_closed; + } + + long long SetImmediate(std::function action) override; + long long SetTimeout(std::chrono::milliseconds milliseconds, + std::function action) override; + long long SetInterval(std::chrono::milliseconds milliseconds, + std::function action) override; + void CancelTimer(long long id) override; + + std::vector GetAllWindow() override; + INativeWindow* CreateWindow() override; + + cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override; + + cru::platform::graphics::win::direct::DirectGraphicsFactory* + GetDirectFactory() { + return graph_factory_.get(); + } + + ICursorManager* GetCursorManager() override; + + IClipboard* GetClipboard() override; + + HINSTANCE GetInstanceHandle() const { return instance_handle_; } + + GodWindow* GetGodWindow() const { return god_window_.get(); } + TimerManager* GetTimerManager() const { return timer_manager_.get(); } + WindowManager* GetWindowManager() const { return window_manager_.get(); } + + private: + HINSTANCE instance_handle_; + + bool is_quit_on_all_window_closed_ = true; + + std::unique_ptr + graph_factory_; + + std::unique_ptr god_window_; + std::unique_ptr timer_manager_; + std::unique_ptr window_manager_; + + std::unique_ptr cursor_manager_; + std::unique_ptr clipboard_; + + std::vector> quit_handlers_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/UiApplication.hpp b/include/cru/win/gui/UiApplication.hpp deleted file mode 100644 index 1280e7a6..00000000 --- a/include/cru/win/gui/UiApplication.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "cru/platform/gui/Base.hpp" -#include "cru/platform/gui/UiApplication.hpp" - -#include - -namespace cru::platform::graphics::win::direct { -class DirectGraphicsFactory; -} - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API WinUiApplication : public WinNativeResource, - public virtual IUiApplication { - public: - static WinUiApplication* GetInstance() { return instance; } - - private: - static WinUiApplication* instance; - - public: - WinUiApplication(); - - CRU_DELETE_COPY(WinUiApplication) - CRU_DELETE_MOVE(WinUiApplication) - - ~WinUiApplication() override; - - public: - int Run() override; - void RequestQuit(int quit_code) override; - - void AddOnQuitHandler(std::function handler) override; - - bool IsQuitOnAllWindowClosed() override { - return is_quit_on_all_window_closed_; - } - void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) override { - is_quit_on_all_window_closed_ = quit_on_all_window_closed; - } - - long long SetImmediate(std::function action) override; - long long SetTimeout(std::chrono::milliseconds milliseconds, - std::function action) override; - long long SetInterval(std::chrono::milliseconds milliseconds, - std::function action) override; - void CancelTimer(long long id) override; - - std::vector GetAllWindow() override; - INativeWindow* CreateWindow() override; - - cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override; - - cru::platform::graphics::win::direct::DirectGraphicsFactory* - GetDirectFactory() { - return graph_factory_.get(); - } - - ICursorManager* GetCursorManager() override; - - IClipboard* GetClipboard() override; - - HINSTANCE GetInstanceHandle() const { return instance_handle_; } - - GodWindow* GetGodWindow() const { return god_window_.get(); } - TimerManager* GetTimerManager() const { return timer_manager_.get(); } - WindowManager* GetWindowManager() const { return window_manager_.get(); } - - private: - HINSTANCE instance_handle_; - - bool is_quit_on_all_window_closed_ = true; - - std::unique_ptr - graph_factory_; - - std::unique_ptr god_window_; - std::unique_ptr timer_manager_; - std::unique_ptr window_manager_; - - std::unique_ptr cursor_manager_; - std::unique_ptr clipboard_; - - std::vector> quit_handlers_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Window.h b/include/cru/win/gui/Window.h new file mode 100644 index 00000000..fcbe1dbd --- /dev/null +++ b/include/cru/win/gui/Window.h @@ -0,0 +1,217 @@ +#pragma once +#include "Resource.h" + +#include "WindowNativeMessageEventArgs.h" +#include "cru/platform/gui/Base.h" +#include "cru/platform/gui/Window.h" +#include "cru/win/graphics/direct/WindowRenderTarget.h" + +#include + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API WinNativeWindow : public WinNativeResource, + public virtual INativeWindow { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinNativeWindow") + + public: + explicit WinNativeWindow(WinUiApplication* application); + + CRU_DELETE_COPY(WinNativeWindow) + CRU_DELETE_MOVE(WinNativeWindow) + + ~WinNativeWindow() override; + + public: + void Close() override; + + WinNativeWindow* GetParent() override { return parent_window_; } + void SetParent(INativeWindow* parent) override; + + WindowStyleFlag GetStyleFlag() override { return style_flag_; } + void SetStyleFlag(WindowStyleFlag flag) override; + + String GetTitle() override; + void SetTitle(String title) override; + + WindowVisibilityType GetVisibility() override { return visibility_; } + void SetVisibility(WindowVisibilityType visibility) override; + + Size GetClientSize() override; + void SetClientSize(const Size& size) override; + + Rect GetClientRect() override; + void SetClientRect(const Rect& rect) override; + + // Get the rect of the window containing frame. + // The lefttop of the rect is relative to screen lefttop. + Rect GetWindowRect() override; + + // Set the rect of the window containing frame. + // The lefttop of the rect is relative to screen lefttop. + void SetWindowRect(const Rect& rect) override; + + bool RequestFocus() override; + + Point GetMousePosition() override; + + bool CaptureMouse() override; + bool ReleaseMouse() override; + + void RequestRepaint() override; + std::unique_ptr BeginPaint() override; + + void SetCursor(std::shared_ptr cursor) override; + + void SetToForeground() override; + + IEvent* CreateEvent() override { return &create_event_; } + IEvent* DestroyEvent() override { return &destroy_event_; } + IEvent* PaintEvent() override { return &paint_event_; } + IEvent* VisibilityChangeEvent() override { + return &visibility_change_event_; + } + IEvent* ResizeEvent() override { return &resize_event_; } + IEvent* FocusEvent() override { return &focus_event_; } + IEvent* MouseEnterLeaveEvent() override { + return &mouse_enter_leave_event_; + } + IEvent* MouseMoveEvent() override { return &mouse_move_event_; } + IEvent* MouseDownEvent() override { + return &mouse_down_event_; + } + IEvent* MouseUpEvent() override { + return &mouse_up_event_; + } + IEvent* MouseWheelEvent() override { + return &mouse_wheel_event_; + } + + IEvent* KeyDownEvent() override { + return &key_down_event_; + } + IEvent* KeyUpEvent() override { + return &key_up_event_; + } + + IEvent* NativeMessageEvent() { + return &native_message_event_; + } + + IInputMethodContext* GetInputMethodContext() override; + + // Get the handle of the window. Return null if window is invalid. + HWND GetWindowHandle() const { return hwnd_; } + + bool HandleNativeWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, + LPARAM l_param, LRESULT* result); + + graphics::win::direct::D2DWindowRenderTarget* GetWindowRenderTarget() const { + return window_render_target_.get(); + } + + //*************** region: dpi *************** + float GetDpi() const { return dpi_; } + + inline int DipToPixel(const float dip) { + return static_cast(dip * GetDpi() / 96.0f); + } + + inline POINT DipToPixel(const Point& dip_point) { + POINT result; + result.x = DipToPixel(dip_point.x); + result.y = DipToPixel(dip_point.y); + return result; + } + + inline RECT DipToPixel(const Rect& dip_rect) { + RECT result; + result.left = DipToPixel(dip_rect.left); + result.top = DipToPixel(dip_rect.top); + result.right = DipToPixel(dip_rect.GetRight()); + result.bottom = DipToPixel(dip_rect.GetBottom()); + return result; + } + + inline float PixelToDip(const int pixel) { + return static_cast(pixel) * 96.0f / GetDpi(); + } + + inline Point PixelToDip(const POINT& pi_point) { + return Point(PixelToDip(pi_point.x), PixelToDip(pi_point.y)); + } + + inline Rect PixelToDip(const RECT& pi_rect) { + return Rect::FromVertices(PixelToDip(pi_rect.left), PixelToDip(pi_rect.top), + PixelToDip(pi_rect.right), + PixelToDip(pi_rect.bottom)); + } + + private: + // Get the client rect in pixel. + RECT GetClientRectPixel(); + + void RecreateWindow(); + + //*************** region: native messages *************** + + void OnCreateInternal(); + void OnDestroyInternal(); + void OnPaintInternal(); + void OnMoveInternal(int new_left, int new_top); + void OnResizeInternal(int new_width, int new_height); + + void OnSetFocusInternal(); + void OnKillFocusInternal(); + + void OnMouseMoveInternal(POINT point); + void OnMouseLeaveInternal(); + void OnMouseDownInternal(platform::gui::MouseButton button, POINT point); + void OnMouseUpInternal(platform::gui::MouseButton button, POINT point); + + void OnMouseWheelInternal(short delta, POINT point); + void OnKeyDownInternal(int virtual_code); + void OnKeyUpInternal(int virtual_code); + + void OnActivatedInternal(); + void OnDeactivatedInternal(); + + private: + WinUiApplication* application_; + + WindowStyleFlag style_flag_{}; + WindowVisibilityType visibility_ = WindowVisibilityType::Hide; + Rect client_rect_{100, 100, 400, 300}; + String title_; + + HWND hwnd_ = nullptr; + WinNativeWindow* parent_window_ = nullptr; + + float dpi_; + + bool has_focus_ = false; + bool is_mouse_in_ = false; + + std::unique_ptr + window_render_target_; + + std::shared_ptr cursor_; + + std::unique_ptr input_method_context_; + + Event create_event_; + Event destroy_event_; + Event paint_event_; + Event resize_event_; + Event visibility_change_event_; + Event focus_event_; + Event mouse_enter_leave_event_; + Event mouse_move_event_; + Event mouse_down_event_; + Event mouse_up_event_; + Event mouse_wheel_event_; + Event key_down_event_; + Event key_up_event_; + + Event native_message_event_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/Window.hpp b/include/cru/win/gui/Window.hpp deleted file mode 100644 index 75530596..00000000 --- a/include/cru/win/gui/Window.hpp +++ /dev/null @@ -1,217 +0,0 @@ -#pragma once -#include "Resource.hpp" - -#include "WindowNativeMessageEventArgs.hpp" -#include "cru/platform/gui/Base.hpp" -#include "cru/platform/gui/Window.hpp" -#include "cru/win/graphics/direct/WindowRenderTarget.hpp" - -#include - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API WinNativeWindow : public WinNativeResource, - public virtual INativeWindow { - CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinNativeWindow") - - public: - explicit WinNativeWindow(WinUiApplication* application); - - CRU_DELETE_COPY(WinNativeWindow) - CRU_DELETE_MOVE(WinNativeWindow) - - ~WinNativeWindow() override; - - public: - void Close() override; - - WinNativeWindow* GetParent() override { return parent_window_; } - void SetParent(INativeWindow* parent) override; - - WindowStyleFlag GetStyleFlag() override { return style_flag_; } - void SetStyleFlag(WindowStyleFlag flag) override; - - String GetTitle() override; - void SetTitle(String title) override; - - WindowVisibilityType GetVisibility() override { return visibility_; } - void SetVisibility(WindowVisibilityType visibility) override; - - Size GetClientSize() override; - void SetClientSize(const Size& size) override; - - Rect GetClientRect() override; - void SetClientRect(const Rect& rect) override; - - // Get the rect of the window containing frame. - // The lefttop of the rect is relative to screen lefttop. - Rect GetWindowRect() override; - - // Set the rect of the window containing frame. - // The lefttop of the rect is relative to screen lefttop. - void SetWindowRect(const Rect& rect) override; - - bool RequestFocus() override; - - Point GetMousePosition() override; - - bool CaptureMouse() override; - bool ReleaseMouse() override; - - void RequestRepaint() override; - std::unique_ptr BeginPaint() override; - - void SetCursor(std::shared_ptr cursor) override; - - void SetToForeground() override; - - IEvent* CreateEvent() override { return &create_event_; } - IEvent* DestroyEvent() override { return &destroy_event_; } - IEvent* PaintEvent() override { return &paint_event_; } - IEvent* VisibilityChangeEvent() override { - return &visibility_change_event_; - } - IEvent* ResizeEvent() override { return &resize_event_; } - IEvent* FocusEvent() override { return &focus_event_; } - IEvent* MouseEnterLeaveEvent() override { - return &mouse_enter_leave_event_; - } - IEvent* MouseMoveEvent() override { return &mouse_move_event_; } - IEvent* MouseDownEvent() override { - return &mouse_down_event_; - } - IEvent* MouseUpEvent() override { - return &mouse_up_event_; - } - IEvent* MouseWheelEvent() override { - return &mouse_wheel_event_; - } - - IEvent* KeyDownEvent() override { - return &key_down_event_; - } - IEvent* KeyUpEvent() override { - return &key_up_event_; - } - - IEvent* NativeMessageEvent() { - return &native_message_event_; - } - - IInputMethodContext* GetInputMethodContext() override; - - // Get the handle of the window. Return null if window is invalid. - HWND GetWindowHandle() const { return hwnd_; } - - bool HandleNativeWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, - LPARAM l_param, LRESULT* result); - - graphics::win::direct::D2DWindowRenderTarget* GetWindowRenderTarget() const { - return window_render_target_.get(); - } - - //*************** region: dpi *************** - float GetDpi() const { return dpi_; } - - inline int DipToPixel(const float dip) { - return static_cast(dip * GetDpi() / 96.0f); - } - - inline POINT DipToPixel(const Point& dip_point) { - POINT result; - result.x = DipToPixel(dip_point.x); - result.y = DipToPixel(dip_point.y); - return result; - } - - inline RECT DipToPixel(const Rect& dip_rect) { - RECT result; - result.left = DipToPixel(dip_rect.left); - result.top = DipToPixel(dip_rect.top); - result.right = DipToPixel(dip_rect.GetRight()); - result.bottom = DipToPixel(dip_rect.GetBottom()); - return result; - } - - inline float PixelToDip(const int pixel) { - return static_cast(pixel) * 96.0f / GetDpi(); - } - - inline Point PixelToDip(const POINT& pi_point) { - return Point(PixelToDip(pi_point.x), PixelToDip(pi_point.y)); - } - - inline Rect PixelToDip(const RECT& pi_rect) { - return Rect::FromVertices(PixelToDip(pi_rect.left), PixelToDip(pi_rect.top), - PixelToDip(pi_rect.right), - PixelToDip(pi_rect.bottom)); - } - - private: - // Get the client rect in pixel. - RECT GetClientRectPixel(); - - void RecreateWindow(); - - //*************** region: native messages *************** - - void OnCreateInternal(); - void OnDestroyInternal(); - void OnPaintInternal(); - void OnMoveInternal(int new_left, int new_top); - void OnResizeInternal(int new_width, int new_height); - - void OnSetFocusInternal(); - void OnKillFocusInternal(); - - void OnMouseMoveInternal(POINT point); - void OnMouseLeaveInternal(); - void OnMouseDownInternal(platform::gui::MouseButton button, POINT point); - void OnMouseUpInternal(platform::gui::MouseButton button, POINT point); - - void OnMouseWheelInternal(short delta, POINT point); - void OnKeyDownInternal(int virtual_code); - void OnKeyUpInternal(int virtual_code); - - void OnActivatedInternal(); - void OnDeactivatedInternal(); - - private: - WinUiApplication* application_; - - WindowStyleFlag style_flag_{}; - WindowVisibilityType visibility_ = WindowVisibilityType::Hide; - Rect client_rect_{100, 100, 400, 300}; - String title_; - - HWND hwnd_ = nullptr; - WinNativeWindow* parent_window_ = nullptr; - - float dpi_; - - bool has_focus_ = false; - bool is_mouse_in_ = false; - - std::unique_ptr - window_render_target_; - - std::shared_ptr cursor_; - - std::unique_ptr input_method_context_; - - Event create_event_; - Event destroy_event_; - Event paint_event_; - Event resize_event_; - Event visibility_change_event_; - Event focus_event_; - Event mouse_enter_leave_event_; - Event mouse_move_event_; - Event mouse_down_event_; - Event mouse_up_event_; - Event mouse_wheel_event_; - Event key_down_event_; - Event key_up_event_; - - Event native_message_event_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/WindowClass.h b/include/cru/win/gui/WindowClass.h new file mode 100644 index 00000000..50729887 --- /dev/null +++ b/include/cru/win/gui/WindowClass.h @@ -0,0 +1,24 @@ +#pragma once +#include "Base.h" + +#include + +namespace cru::platform::gui::win { +class CRU_WIN_GUI_API WindowClass : public Object { + public: + WindowClass(std::wstring name, WNDPROC window_proc, HINSTANCE h_instance); + + CRU_DELETE_COPY(WindowClass) + CRU_DELETE_MOVE(WindowClass) + + ~WindowClass() override = default; + + const wchar_t* GetName() const { return name_.c_str(); } + + ATOM GetAtom() const { return atom_; } + + private: + std::wstring name_; + ATOM atom_; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/WindowClass.hpp b/include/cru/win/gui/WindowClass.hpp deleted file mode 100644 index ab55b214..00000000 --- a/include/cru/win/gui/WindowClass.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include - -namespace cru::platform::gui::win { -class CRU_WIN_GUI_API WindowClass : public Object { - public: - WindowClass(std::wstring name, WNDPROC window_proc, HINSTANCE h_instance); - - CRU_DELETE_COPY(WindowClass) - CRU_DELETE_MOVE(WindowClass) - - ~WindowClass() override = default; - - const wchar_t* GetName() const { return name_.c_str(); } - - ATOM GetAtom() const { return atom_; } - - private: - std::wstring name_; - ATOM atom_; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/WindowNativeMessageEventArgs.h b/include/cru/win/gui/WindowNativeMessageEventArgs.h new file mode 100644 index 00000000..bc85a597 --- /dev/null +++ b/include/cru/win/gui/WindowNativeMessageEventArgs.h @@ -0,0 +1,40 @@ +#pragma once +#include "Base.h" + +#include "cru/common/Base.h" + +namespace cru::platform::gui::win { +struct CRU_WIN_GUI_API WindowNativeMessage { + HWND hwnd; + UINT msg; + WPARAM w_param; + LPARAM l_param; +}; + +class CRU_WIN_GUI_API WindowNativeMessageEventArgs : public Object { + public: + WindowNativeMessageEventArgs(const WindowNativeMessage& message) + : message_(message) {} + CRU_DEFAULT_COPY(WindowNativeMessageEventArgs) + CRU_DEFAULT_MOVE(WindowNativeMessageEventArgs) + ~WindowNativeMessageEventArgs() override = default; + + const WindowNativeMessage& GetWindowMessage() const { return message_; } + + LRESULT GetResult() const { return result_; } + void SetResult(LRESULT result) { result_ = result; } + + bool IsHandled() const { return handled_; } + void SetHandled(bool handled) { handled_ = handled; } + + void HandleWithResult(LRESULT result) { + handled_ = true; + result_ = result; + } + + private: + WindowNativeMessage message_; + LRESULT result_; + bool handled_ = false; +}; +} // namespace cru::platform::gui::win diff --git a/include/cru/win/gui/WindowNativeMessageEventArgs.hpp b/include/cru/win/gui/WindowNativeMessageEventArgs.hpp deleted file mode 100644 index 7e62c19d..00000000 --- a/include/cru/win/gui/WindowNativeMessageEventArgs.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "cru/common/Base.hpp" - -namespace cru::platform::gui::win { -struct CRU_WIN_GUI_API WindowNativeMessage { - HWND hwnd; - UINT msg; - WPARAM w_param; - LPARAM l_param; -}; - -class CRU_WIN_GUI_API WindowNativeMessageEventArgs : public Object { - public: - WindowNativeMessageEventArgs(const WindowNativeMessage& message) - : message_(message) {} - CRU_DEFAULT_COPY(WindowNativeMessageEventArgs) - CRU_DEFAULT_MOVE(WindowNativeMessageEventArgs) - ~WindowNativeMessageEventArgs() override = default; - - const WindowNativeMessage& GetWindowMessage() const { return message_; } - - LRESULT GetResult() const { return result_; } - void SetResult(LRESULT result) { result_ = result; } - - bool IsHandled() const { return handled_; } - void SetHandled(bool handled) { handled_ = handled; } - - void HandleWithResult(LRESULT result) { - handled_ = true; - result_ = result; - } - - private: - WindowNativeMessage message_; - LRESULT result_; - bool handled_ = false; -}; -} // namespace cru::platform::gui::win diff --git a/include/cru/xml/Base.h b/include/cru/xml/Base.h new file mode 100644 index 00000000..5d6fe144 --- /dev/null +++ b/include/cru/xml/Base.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_XML_EXPORT_API +#define CRU_XML_API __declspec(dllexport) +#else +#define CRU_XML_API __declspec(dllimport) +#endif +#else +#define CRU_XML_API +#endif diff --git a/include/cru/xml/Base.hpp b/include/cru/xml/Base.hpp deleted file mode 100644 index 5d6fe144..00000000 --- a/include/cru/xml/Base.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_XML_EXPORT_API -#define CRU_XML_API __declspec(dllexport) -#else -#define CRU_XML_API __declspec(dllimport) -#endif -#else -#define CRU_XML_API -#endif diff --git a/include/cru/xml/XmlNode.h b/include/cru/xml/XmlNode.h new file mode 100644 index 00000000..737a2d87 --- /dev/null +++ b/include/cru/xml/XmlNode.h @@ -0,0 +1,135 @@ +#pragma once + +#include "Base.h" + +#include "cru/common/String.h" + +#include +#include +#include +#include + +namespace cru::xml { +class XmlElementNode; +class XmlTextNode; + +class CRU_XML_API XmlNode { + friend XmlElementNode; + + public: + enum class Type { Text, Element }; + + protected: + explicit XmlNode(Type type) : type_(type) {} + + public: + CRU_DELETE_COPY(XmlNode) + CRU_DELETE_MOVE(XmlNode) + + virtual ~XmlNode() = default; + + Type GetType() const { return type_; } + XmlElementNode* GetParent() const { return parent_; } + + virtual XmlNode* Clone() const = 0; + + bool IsTextNode() const { return type_ == Type::Text; } + bool IsElementNode() const { return type_ == Type::Element; } + + XmlElementNode* AsElement(); + XmlTextNode* AsText(); + const XmlElementNode* AsElement() const; + const XmlTextNode* AsText() const; + + private: + const Type type_; + XmlElementNode* parent_ = nullptr; +}; + +class CRU_XML_API XmlTextNode : public XmlNode { + public: + XmlTextNode() : XmlNode(Type::Text) {} + explicit XmlTextNode(String text) + : XmlNode(Type::Text), text_(std::move(text)) {} + + CRU_DELETE_COPY(XmlTextNode) + CRU_DELETE_MOVE(XmlTextNode) + + ~XmlTextNode() override = default; + + public: + String GetText() const { return text_; } + void SetText(String text) { text_ = std::move(text); } + + XmlNode* Clone() const override { return new XmlTextNode(text_); } + + private: + String text_; +}; + +class CRU_XML_API XmlElementNode : public XmlNode { + public: + XmlElementNode() : XmlNode(Type::Element) {} + explicit XmlElementNode(String tag, + std::unordered_map attributes = {}) + : XmlNode(Type::Element), + tag_(std::move(tag)), + attributes_(std::move(attributes)) {} + + CRU_DELETE_COPY(XmlElementNode) + CRU_DELETE_MOVE(XmlElementNode) + + ~XmlElementNode() override; + + public: + String GetTag() const { return tag_; } + void SetTag(String tag) { tag_ = std::move(tag); } + const std::unordered_map& GetAttributes() const { + return attributes_; + } + void SetAttributes(std::unordered_map attributes) { + attributes_ = std::move(attributes); + } + const std::vector GetChildren() const { return children_; } + + Index GetChildCount() const { return children_.size(); } + String GetAttribute(const String& key) const { return attributes_.at(key); } + String GetAttributeCaseInsensitive(const String& key) const { + return *GetOptionalAttributeCaseInsensitive(key); + } + std::optional GetOptionalAttribute(const String& key) const { + auto it = attributes_.find(key); + if (it == attributes_.end()) { + return std::nullopt; + } + + return it->second; + } + std::optional GetOptionalAttributeCaseInsensitive( + const String& key) const { + for (auto it = attributes_.begin(); it != attributes_.end(); ++it) { + if (it->first.CaseInsensitiveCompare(key) == 0) { + return it->second; + } + } + + return std::nullopt; + } + + XmlNode* GetChildAt(Index index) const { return children_[index]; } + + void AddAttribute(String key, String value); + void AddChild(XmlNode* child); + + Index GetChildElementCount() const; + XmlElementNode* GetFirstChildElement() const; + + XmlNode* Clone() const override; + + private: + String tag_; + std::unordered_map attributes_; + std::vector children_; +}; + +} // namespace cru::xml diff --git a/include/cru/xml/XmlNode.hpp b/include/cru/xml/XmlNode.hpp deleted file mode 100644 index cfe6e155..00000000 --- a/include/cru/xml/XmlNode.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include "Base.hpp" - -#include "cru/common/String.hpp" - -#include -#include -#include -#include - -namespace cru::xml { -class XmlElementNode; -class XmlTextNode; - -class CRU_XML_API XmlNode { - friend XmlElementNode; - - public: - enum class Type { Text, Element }; - - protected: - explicit XmlNode(Type type) : type_(type) {} - - public: - CRU_DELETE_COPY(XmlNode) - CRU_DELETE_MOVE(XmlNode) - - virtual ~XmlNode() = default; - - Type GetType() const { return type_; } - XmlElementNode* GetParent() const { return parent_; } - - virtual XmlNode* Clone() const = 0; - - bool IsTextNode() const { return type_ == Type::Text; } - bool IsElementNode() const { return type_ == Type::Element; } - - XmlElementNode* AsElement(); - XmlTextNode* AsText(); - const XmlElementNode* AsElement() const; - const XmlTextNode* AsText() const; - - private: - const Type type_; - XmlElementNode* parent_ = nullptr; -}; - -class CRU_XML_API XmlTextNode : public XmlNode { - public: - XmlTextNode() : XmlNode(Type::Text) {} - explicit XmlTextNode(String text) - : XmlNode(Type::Text), text_(std::move(text)) {} - - CRU_DELETE_COPY(XmlTextNode) - CRU_DELETE_MOVE(XmlTextNode) - - ~XmlTextNode() override = default; - - public: - String GetText() const { return text_; } - void SetText(String text) { text_ = std::move(text); } - - XmlNode* Clone() const override { return new XmlTextNode(text_); } - - private: - String text_; -}; - -class CRU_XML_API XmlElementNode : public XmlNode { - public: - XmlElementNode() : XmlNode(Type::Element) {} - explicit XmlElementNode(String tag, - std::unordered_map attributes = {}) - : XmlNode(Type::Element), - tag_(std::move(tag)), - attributes_(std::move(attributes)) {} - - CRU_DELETE_COPY(XmlElementNode) - CRU_DELETE_MOVE(XmlElementNode) - - ~XmlElementNode() override; - - public: - String GetTag() const { return tag_; } - void SetTag(String tag) { tag_ = std::move(tag); } - const std::unordered_map& GetAttributes() const { - return attributes_; - } - void SetAttributes(std::unordered_map attributes) { - attributes_ = std::move(attributes); - } - const std::vector GetChildren() const { return children_; } - - Index GetChildCount() const { return children_.size(); } - String GetAttribute(const String& key) const { return attributes_.at(key); } - String GetAttributeCaseInsensitive(const String& key) const { - return *GetOptionalAttributeCaseInsensitive(key); - } - std::optional GetOptionalAttribute(const String& key) const { - auto it = attributes_.find(key); - if (it == attributes_.end()) { - return std::nullopt; - } - - return it->second; - } - std::optional GetOptionalAttributeCaseInsensitive( - const String& key) const { - for (auto it = attributes_.begin(); it != attributes_.end(); ++it) { - if (it->first.CaseInsensitiveCompare(key) == 0) { - return it->second; - } - } - - return std::nullopt; - } - - XmlNode* GetChildAt(Index index) const { return children_[index]; } - - void AddAttribute(String key, String value); - void AddChild(XmlNode* child); - - Index GetChildElementCount() const; - XmlElementNode* GetFirstChildElement() const; - - XmlNode* Clone() const override; - - private: - String tag_; - std::unordered_map attributes_; - std::vector children_; -}; - -} // namespace cru::xml diff --git a/include/cru/xml/XmlParser.h b/include/cru/xml/XmlParser.h new file mode 100644 index 00000000..75664ce3 --- /dev/null +++ b/include/cru/xml/XmlParser.h @@ -0,0 +1,47 @@ +#pragma once + +#include "XmlNode.h" + +#include "cru/common/Exception.h" +#include "cru/common/String.h" + +#include + +namespace cru::xml { +class CRU_XML_API XmlParsingException : public Exception { + public: + using Exception::Exception; +}; + +class CRU_XML_API XmlParser { + public: + explicit XmlParser(String xml); + + CRU_DELETE_COPY(XmlParser) + CRU_DELETE_MOVE(XmlParser) + + ~XmlParser(); + + XmlElementNode* Parse(); + + private: + XmlElementNode* DoParse(); + + char16_t Read1(); + String ReadWithoutAdvance(int count = 1); + void ReadSpacesAndDiscard(); + String ReadSpaces(); + String ReadIdenitifier(); + String ReadAttributeString(); + + private: + String xml_; + + XmlElementNode* cache_ = nullptr; + + // Consider the while file enclosed by a single tag called $root. + XmlElementNode* pseudo_root_node_ = new XmlElementNode(u"$root"); + XmlElementNode* current_ = pseudo_root_node_; + int current_position_ = 0; +}; +} // namespace cru::xml diff --git a/include/cru/xml/XmlParser.hpp b/include/cru/xml/XmlParser.hpp deleted file mode 100644 index e916cc53..00000000 --- a/include/cru/xml/XmlParser.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "XmlNode.hpp" - -#include "cru/common/Exception.hpp" -#include "cru/common/String.hpp" - -#include - -namespace cru::xml { -class CRU_XML_API XmlParsingException : public Exception { - public: - using Exception::Exception; -}; - -class CRU_XML_API XmlParser { - public: - explicit XmlParser(String xml); - - CRU_DELETE_COPY(XmlParser) - CRU_DELETE_MOVE(XmlParser) - - ~XmlParser(); - - XmlElementNode* Parse(); - - private: - XmlElementNode* DoParse(); - - char16_t Read1(); - String ReadWithoutAdvance(int count = 1); - void ReadSpacesAndDiscard(); - String ReadSpaces(); - String ReadIdenitifier(); - String ReadAttributeString(); - - private: - String xml_; - - XmlElementNode* cache_ = nullptr; - - // Consider the while file enclosed by a single tag called $root. - XmlElementNode* pseudo_root_node_ = new XmlElementNode(u"$root"); - XmlElementNode* current_ = pseudo_root_node_; - int current_position_ = 0; -}; -} // namespace cru::xml -- cgit v1.2.3