diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c5f5a33d..b9fd33416 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,7 +43,6 @@ include(${SCRIPTS_CMAKE_DIR}/googletest.cmake)
include(${SCRIPTS_CMAKE_DIR}/manifests.cmake)
include(${SCRIPTS_CMAKE_DIR}/docker.cmake)
include(${SCRIPTS_CMAKE_DIR}/lua.cmake)
-include(${SCRIPTS_CMAKE_DIR}/ui.cmake)
include(${SCRIPTS_CMAKE_DIR}/macros.cmake)
include(${SCRIPTS_CMAKE_DIR}/pack.cmake)
include(CPack)
@@ -58,7 +57,6 @@ option(VOXEDIT "Builds voxedit" ON)
option(THUMBNAILER "Builds thumbnailer" ON)
option(VOXCONVERT "Builds voxconvert" ON)
option(MAPVIEW "Builds mapview" ON)
-option(NOISETOOL "Builds noisetool" ON)
option(USE_CCACHE "Use ccache" ON)
option(USE_GPROF "Use gprof - will become slow" OFF)
option(USE_GCOV "Use gcov - will become slow" OFF)
diff --git a/Makefile b/Makefile
index 1f346ba7e..770f85006 100644
--- a/Makefile
+++ b/Makefile
@@ -78,7 +78,6 @@ update-stb:
cp $(UPDATEDIR)/stb.sync/stb_image.h src/modules/image/stb_image.h
cp $(UPDATEDIR)/stb.sync/stb_image_write.h src/modules/image/stb_image_write.h
cp $(UPDATEDIR)/stb.sync/stb_truetype.h src/modules/voxelfont/stb_truetype.h
- cp $(UPDATEDIR)/stb.sync/stb_truetype.h src/modules/ui/turbobadger/tb/thirdparty
update-googletest:
$(call UPDATE_GIT,googletest,https://github.com/google/googletest.git)
diff --git a/cmake/ui.cmake b/cmake/ui.cmake
deleted file mode 100644
index 4c1c1dcb5..000000000
--- a/cmake/ui.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-macro(check_ui_turbobadger TARGET)
- if (NOT CMAKE_CROSS_COMPILING)
- set(_files ${ARGN})
- set(_workingdir "${DATA_DIR}/${TARGET}")
- foreach(_file ${_files})
- get_filename_component(_filename ${_file} NAME)
- add_custom_target(
- ${TARGET}-${_filename}
- COMMAND uitool ../${_file}
- DEPENDS uitool ${DATA_DIR}/${_file}
- WORKING_DIRECTORY ${_workingdir}
- SOURCES ${DATA_DIR}/${_file}
- )
- add_dependencies(${TARGET} ${TARGET}-${_filename})
- endforeach()
- endif()
-endmacro()
diff --git a/data/noisetool/ui/lang/en.tb.txt b/data/noisetool/ui/lang/en.tb.txt
deleted file mode 100644
index 82b27ff6f..000000000
--- a/data/noisetool/ui/lang/en.tb.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-cut Cut
-copy Copy
-paste Paste
-delete Delete
-selectall Select all
-TBMessageWindow.ok Ok
-TBMessageWindow.cancel Cancel
-TBMessageWindow.yes Yes
-TBMessageWindow.no No
-TBList.header Showing %d of %d
diff --git a/data/noisetool/ui/skin/noisetool-skin.tb.txt b/data/noisetool/ui/skin/noisetool-skin.tb.txt
deleted file mode 100644
index cbbb8724d..000000000
--- a/data/noisetool/ui/skin/noisetool-skin.tb.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-elements
- node-mover
- text-color #b8b8b8
- node-header
- bitmap window_mover_bg_tile.png
- type Tile
- expand -1
- padding 3 16
- node
- bitmap window.png
- cut 16
- expand 12
- padding 2
diff --git a/data/noisetool/ui/widget/noisetool-noisedata-item.tb.txt b/data/noisetool/ui/widget/noisetool-noisedata-item.tb.txt
deleted file mode 100644
index 60259f537..000000000
--- a/data/noisetool/ui/widget/noisetool-noisedata-item.tb.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-TBLayout: axis: y, position: left, spacing: 3, position: left top
- TBLayout: axis: x, spacing: 10, position: left, distribution: gravity, ignore-input: 1
- TBTextField: id: name
- font: size: 28px
- TBTextField: id: frequency
- TBTextField: id: octaves
- TBTextField: id: gain
- TBTextField: id: lacunarity
- TBTextField: id: millis
- TBWidget: gravity: left right
- ImageWidget: id: graph, ignore-input: 1
- TBSection: value: 0, text: "2D noise"
- TBLayout: position: left top
- ImageWidget: id: noise
-
-TBButton: id: delete, skin: TBWindow.close
diff --git a/data/noisetool/ui/widget/noisetool-noisedata-list.tb.txt b/data/noisetool/ui/widget/noisetool-noisedata-list.tb.txt
deleted file mode 100644
index be87022ec..000000000
--- a/data/noisetool/ui/widget/noisetool-noisedata-list.tb.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-TBLayout
- distribution gravity
- TBEditField
- id filter
- gravity left right
- placeholder Search
- type search
-TBSelectList
- id list
- gravity all
diff --git a/data/noisetool/ui/widget/noisetool-noisedata-node.tb.txt b/data/noisetool/ui/widget/noisetool-noisedata-node.tb.txt
deleted file mode 100644
index fbce72195..000000000
--- a/data/noisetool/ui/widget/noisetool-noisedata-node.tb.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-TBMover: axis: y, position: left, spacing: 3, position: left top, gravity: all, skin: node
- TBLayout: axis: y, spacing: 2, position: left, distribution: gravity, ignore-input: 1, gravity: all
- TBTextField: id: name, skin: node-header
- TBLayout: axis: y
- TBTextField: id: frequency
- font: size: 8px
- TBTextField: id: octaves
- font: size: 8px
- TBTextField: id: gain
- font: size: 8px
- TBTextField: id: lacunarity
- font: size: 8px
diff --git a/data/noisetool/ui/window/noisetool-main.tb.txt b/data/noisetool/ui/window/noisetool-main.tb.txt
deleted file mode 100644
index e3e9dad85..000000000
--- a/data/noisetool/ui/window/noisetool-main.tb.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-definitions
- layoutparamsx
- axis x
- distribution gravity
- position left
- layoutparamsy
- axis y
- distribution available
- gravity all
- position left
-
-WindowInfo
- title Noise generator
- fullscreen 1
-
-definitions
- menubutton
- lp: height: 28
- skin TBButton.flat
-
-TBLayout: distribution: gravity, axis: y
- TBContainer: gravity: all, id: maincontainer
- TBLayout: distribution: gravity, axis: y
- TBLayout: distribution: gravity
- TBContainer: skin: container, gravity: left right
- TBLayout: distribution: gravity
- TBButton: gravity: left, @include: definitions>menubutton, text: Generate, id: ok, autofocus: 1
- TBSkinImage: skin: noisetool-generate
- TBSelectDropdown
- lp: width: 280
- gravity left right
- id type
- TBButton: gravity: left, @include: definitions>menubutton, text: All, id: all
- TBSkinImage: skin: noisetool-generate
- TBButton: gravity: left, @include: definitions>menubutton, text: Nodes, id: nodes
- TBSkinImage: skin: noisetool-nodes
- TBLayout: gravity: left right
- TBWidget
-
- TBLayout: distribution: gravity, position: top
- TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom, skin: container
- TBLayout: position: left top, axis: y
- TBClickLabel: text: Frequency
- TBEditField: id: frequency, type: number, text: 0.01
- TBClickLabel: text: Offset
- TBEditField: id: offset, type: number, text: 1.0
- TBClickLabel: text: Octaves
- TBEditField: id: octaves, type: number, text: 4
- TBClickLabel: text: Gain
- TBEditField: id: gain, type: number, text: 0.5
- TBClickLabel: text: Lacunarity
- TBEditField: id: lacunarity, type: number, text: 2.0
- TBSection: value: 1, text: "Poisson Disk Distribution", is-group-root: 1
- TBLayout: position: left top, axis: y
- TBClickLabel: text: Separation
- TBEditField: id: separation, type: number, text: 5.0
- TBSection: value: 1, text: "Ridged noise", is-group-root: 1
- TBLayout: position: left top, axis: y
- TBClickLabel: text: Ridged Offset
- TBEditField: id: ridgedoffset, type: number, text: 1.0
- TBSection: value: 1, text: "Voronoi", is-group-root: 1
- TBLayout: position: left top, axis: y
- TBClickLabel: text: Distance
- TBCheckBox: id: enabledistance
- TBWidget: gravity: top bottom
-
- TBLayout: distribution: gravity, axis: y
- NoiseDataList
-
- TBLayout: distribution: gravity
- TBContainer: skin: container, gravity: left right
- TBLayout: distribution: gravity
- TBLayout: gravity: left right
- TBWidget
- TBButton: @include: definitions>menubutton, text: Quit, id: quit
- TBSkinImage: skin: voxedit-quit
-
diff --git a/data/noisetool/ui/window/noisetool-nodes.tb.txt b/data/noisetool/ui/window/noisetool-nodes.tb.txt
deleted file mode 100644
index b229ae7b8..000000000
--- a/data/noisetool/ui/window/noisetool-nodes.tb.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-WindowInfo
- title Noise data
- position 770 50
- size 600 600
-TBLayout
- axis y
- distribution gravity
- gravity all
- id nodes
diff --git a/data/shared/ui/font/DejaVuSansMono.ttf b/data/shared/ui/font/DejaVuSansMono.ttf
deleted file mode 100644
index f5786022f..000000000
Binary files a/data/shared/ui/font/DejaVuSansMono.ttf and /dev/null differ
diff --git a/data/shared/ui/font/font.tb.txt b/data/shared/ui/font/font.tb.txt
deleted file mode 100644
index b15c81f81..000000000
--- a/data/shared/ui/font/font.tb.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-info
- glyph_str !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
- name Segoe
-size 14
- bitmap font_14.png
- ascent 15
- descent 5
- advance_delta -3
- space_advance 5
-size 28
- bitmap font_28.png
- ascent 31
- descent 10
- advance_delta -7
- space_advance 10
diff --git a/data/shared/ui/font/font_14.png b/data/shared/ui/font/font_14.png
deleted file mode 100644
index 95f90947d..000000000
Binary files a/data/shared/ui/font/font_14.png and /dev/null differ
diff --git a/data/shared/ui/font/font_28.png b/data/shared/ui/font/font_28.png
deleted file mode 100644
index ff7c56c8e..000000000
Binary files a/data/shared/ui/font/font_28.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_down.png b/data/shared/ui/skin/arrow_down.png
deleted file mode 100644
index 589c9fc10..000000000
Binary files a/data/shared/ui/skin/arrow_down.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_down@288.png b/data/shared/ui/skin/arrow_down@288.png
deleted file mode 100644
index 10548c859..000000000
Binary files a/data/shared/ui/skin/arrow_down@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_left.png b/data/shared/ui/skin/arrow_left.png
deleted file mode 100644
index 7f5447b68..000000000
Binary files a/data/shared/ui/skin/arrow_left.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_left@288.png b/data/shared/ui/skin/arrow_left@288.png
deleted file mode 100644
index 4d62c84fc..000000000
Binary files a/data/shared/ui/skin/arrow_left@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_right.png b/data/shared/ui/skin/arrow_right.png
deleted file mode 100644
index fce7cf397..000000000
Binary files a/data/shared/ui/skin/arrow_right.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_right@288.png b/data/shared/ui/skin/arrow_right@288.png
deleted file mode 100644
index 3bbf7a065..000000000
Binary files a/data/shared/ui/skin/arrow_right@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_up.png b/data/shared/ui/skin/arrow_up.png
deleted file mode 100644
index a07789fc7..000000000
Binary files a/data/shared/ui/skin/arrow_up.png and /dev/null differ
diff --git a/data/shared/ui/skin/arrow_up@288.png b/data/shared/ui/skin/arrow_up@288.png
deleted file mode 100644
index c1bad6fca..000000000
Binary files a/data/shared/ui/skin/arrow_up@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button.png b/data/shared/ui/skin/button.png
deleted file mode 100644
index 6516534fc..000000000
Binary files a/data/shared/ui/skin/button.png and /dev/null differ
diff --git a/data/shared/ui/skin/button@288.png b/data/shared/ui/skin/button@288.png
deleted file mode 100644
index c9f4ac6b1..000000000
Binary files a/data/shared/ui/skin/button@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_flat_outline.png b/data/shared/ui/skin/button_flat_outline.png
deleted file mode 100644
index ba3e2b704..000000000
Binary files a/data/shared/ui/skin/button_flat_outline.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_flat_outline@288.png b/data/shared/ui/skin/button_flat_outline@288.png
deleted file mode 100644
index 9cee66e41..000000000
Binary files a/data/shared/ui/skin/button_flat_outline@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_flat_pressed.png b/data/shared/ui/skin/button_flat_pressed.png
deleted file mode 100644
index ee7e65677..000000000
Binary files a/data/shared/ui/skin/button_flat_pressed.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_flat_pressed@288.png b/data/shared/ui/skin/button_flat_pressed@288.png
deleted file mode 100644
index a61982fde..000000000
Binary files a/data/shared/ui/skin/button_flat_pressed@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_first_down.png b/data/shared/ui/skin/button_grouped_x_first_down.png
deleted file mode 100644
index ace624e01..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_first_down.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_first_down@288.png b/data/shared/ui/skin/button_grouped_x_first_down@288.png
deleted file mode 100644
index e2412ab23..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_first_down@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_first_up.png b/data/shared/ui/skin/button_grouped_x_first_up.png
deleted file mode 100644
index 525841117..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_first_up.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_first_up@288.png b/data/shared/ui/skin/button_grouped_x_first_up@288.png
deleted file mode 100644
index 20e0592f9..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_first_up@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_last_down.png b/data/shared/ui/skin/button_grouped_x_last_down.png
deleted file mode 100644
index b12dc5b23..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_last_down.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_last_down@288.png b/data/shared/ui/skin/button_grouped_x_last_down@288.png
deleted file mode 100644
index 82bea402f..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_last_down@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_last_up.png b/data/shared/ui/skin/button_grouped_x_last_up.png
deleted file mode 100644
index f9ea08f34..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_last_up.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_last_up@288.png b/data/shared/ui/skin/button_grouped_x_last_up@288.png
deleted file mode 100644
index 1ed599527..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_last_up@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_middle_down.png b/data/shared/ui/skin/button_grouped_x_middle_down.png
deleted file mode 100644
index 922d1dd30..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_middle_down.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_middle_down@288.png b/data/shared/ui/skin/button_grouped_x_middle_down@288.png
deleted file mode 100644
index 012c25189..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_middle_down@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_middle_up.png b/data/shared/ui/skin/button_grouped_x_middle_up.png
deleted file mode 100644
index acac147d7..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_middle_up.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_grouped_x_middle_up@288.png b/data/shared/ui/skin/button_grouped_x_middle_up@288.png
deleted file mode 100644
index a7dd3e9dd..000000000
Binary files a/data/shared/ui/skin/button_grouped_x_middle_up@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_pressed.png b/data/shared/ui/skin/button_pressed.png
deleted file mode 100644
index 56cecfb3e..000000000
Binary files a/data/shared/ui/skin/button_pressed.png and /dev/null differ
diff --git a/data/shared/ui/skin/button_pressed@288.png b/data/shared/ui/skin/button_pressed@288.png
deleted file mode 100644
index c3e861956..000000000
Binary files a/data/shared/ui/skin/button_pressed@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/checkbox.png b/data/shared/ui/skin/checkbox.png
deleted file mode 100644
index 532d647c8..000000000
Binary files a/data/shared/ui/skin/checkbox.png and /dev/null differ
diff --git a/data/shared/ui/skin/checkbox@288.png b/data/shared/ui/skin/checkbox@288.png
deleted file mode 100644
index 769ae9478..000000000
Binary files a/data/shared/ui/skin/checkbox@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/checkbox_mark.png b/data/shared/ui/skin/checkbox_mark.png
deleted file mode 100644
index ed217d582..000000000
Binary files a/data/shared/ui/skin/checkbox_mark.png and /dev/null differ
diff --git a/data/shared/ui/skin/checkbox_mark@288.png b/data/shared/ui/skin/checkbox_mark@288.png
deleted file mode 100644
index 8b2bcb1f5..000000000
Binary files a/data/shared/ui/skin/checkbox_mark@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/checkbox_pressed.png b/data/shared/ui/skin/checkbox_pressed.png
deleted file mode 100644
index a490b9004..000000000
Binary files a/data/shared/ui/skin/checkbox_pressed.png and /dev/null differ
diff --git a/data/shared/ui/skin/checkbox_pressed@288.png b/data/shared/ui/skin/checkbox_pressed@288.png
deleted file mode 100644
index e86430329..000000000
Binary files a/data/shared/ui/skin/checkbox_pressed@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/container.png b/data/shared/ui/skin/container.png
deleted file mode 100644
index b37f936b6..000000000
Binary files a/data/shared/ui/skin/container.png and /dev/null differ
diff --git a/data/shared/ui/skin/container@288.png b/data/shared/ui/skin/container@288.png
deleted file mode 100644
index fc690485f..000000000
Binary files a/data/shared/ui/skin/container@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/editfield.png b/data/shared/ui/skin/editfield.png
deleted file mode 100644
index 09e6be55a..000000000
Binary files a/data/shared/ui/skin/editfield.png and /dev/null differ
diff --git a/data/shared/ui/skin/editfield@288.png b/data/shared/ui/skin/editfield@288.png
deleted file mode 100644
index e3c80dc82..000000000
Binary files a/data/shared/ui/skin/editfield@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/fadeout_x.png b/data/shared/ui/skin/fadeout_x.png
deleted file mode 100644
index 830c6db0b..000000000
Binary files a/data/shared/ui/skin/fadeout_x.png and /dev/null differ
diff --git a/data/shared/ui/skin/fadeout_x@288.png b/data/shared/ui/skin/fadeout_x@288.png
deleted file mode 100644
index d9e906e9b..000000000
Binary files a/data/shared/ui/skin/fadeout_x@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/fadeout_y.png b/data/shared/ui/skin/fadeout_y.png
deleted file mode 100644
index 085b6a2a8..000000000
Binary files a/data/shared/ui/skin/fadeout_y.png and /dev/null differ
diff --git a/data/shared/ui/skin/fadeout_y@288.png b/data/shared/ui/skin/fadeout_y@288.png
deleted file mode 100644
index c68d17c53..000000000
Binary files a/data/shared/ui/skin/fadeout_y@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/filedialog-dir.png b/data/shared/ui/skin/filedialog-dir.png
deleted file mode 100644
index f29e19d7f..000000000
Binary files a/data/shared/ui/skin/filedialog-dir.png and /dev/null differ
diff --git a/data/shared/ui/skin/filedialog-dir@288.png b/data/shared/ui/skin/filedialog-dir@288.png
deleted file mode 100644
index 3a1d3bf94..000000000
Binary files a/data/shared/ui/skin/filedialog-dir@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/filedialog-file.png b/data/shared/ui/skin/filedialog-file.png
deleted file mode 100644
index 2ca2630cb..000000000
Binary files a/data/shared/ui/skin/filedialog-file.png and /dev/null differ
diff --git a/data/shared/ui/skin/filedialog-file@288.png b/data/shared/ui/skin/filedialog-file@288.png
deleted file mode 100644
index 986257252..000000000
Binary files a/data/shared/ui/skin/filedialog-file@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/focus_r4.png b/data/shared/ui/skin/focus_r4.png
deleted file mode 100644
index 82c1e63e1..000000000
Binary files a/data/shared/ui/skin/focus_r4.png and /dev/null differ
diff --git a/data/shared/ui/skin/focus_r4@288.png b/data/shared/ui/skin/focus_r4@288.png
deleted file mode 100644
index 4e765b1b1..000000000
Binary files a/data/shared/ui/skin/focus_r4@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/focus_tabbutton_left.png b/data/shared/ui/skin/focus_tabbutton_left.png
deleted file mode 100644
index 1b445fec6..000000000
Binary files a/data/shared/ui/skin/focus_tabbutton_left.png and /dev/null differ
diff --git a/data/shared/ui/skin/focus_tabbutton_left@288.png b/data/shared/ui/skin/focus_tabbutton_left@288.png
deleted file mode 100644
index 6793df096..000000000
Binary files a/data/shared/ui/skin/focus_tabbutton_left@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/focus_tabbutton_top.png b/data/shared/ui/skin/focus_tabbutton_top.png
deleted file mode 100644
index db015e236..000000000
Binary files a/data/shared/ui/skin/focus_tabbutton_top.png and /dev/null differ
diff --git a/data/shared/ui/skin/focus_tabbutton_top@288.png b/data/shared/ui/skin/focus_tabbutton_top@288.png
deleted file mode 100644
index ea2bf41c8..000000000
Binary files a/data/shared/ui/skin/focus_tabbutton_top@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_hover.png b/data/shared/ui/skin/item_hover.png
deleted file mode 100644
index 90a6e723c..000000000
Binary files a/data/shared/ui/skin/item_hover.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_hover@288.png b/data/shared/ui/skin/item_hover@288.png
deleted file mode 100644
index b11195c06..000000000
Binary files a/data/shared/ui/skin/item_hover@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_selected.png b/data/shared/ui/skin/item_selected.png
deleted file mode 100644
index cf5dd472d..000000000
Binary files a/data/shared/ui/skin/item_selected.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_selected@288.png b/data/shared/ui/skin/item_selected@288.png
deleted file mode 100644
index 5a3cc031a..000000000
Binary files a/data/shared/ui/skin/item_selected@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_separator_x.png b/data/shared/ui/skin/item_separator_x.png
deleted file mode 100644
index 19073e907..000000000
Binary files a/data/shared/ui/skin/item_separator_x.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_separator_x@288.png b/data/shared/ui/skin/item_separator_x@288.png
deleted file mode 100644
index b2c6b4bee..000000000
Binary files a/data/shared/ui/skin/item_separator_x@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_separator_y.png b/data/shared/ui/skin/item_separator_y.png
deleted file mode 100644
index baf7f51bf..000000000
Binary files a/data/shared/ui/skin/item_separator_y.png and /dev/null differ
diff --git a/data/shared/ui/skin/item_separator_y@288.png b/data/shared/ui/skin/item_separator_y@288.png
deleted file mode 100644
index 7b5eb7ccd..000000000
Binary files a/data/shared/ui/skin/item_separator_y@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/progress_spinner_strip.png b/data/shared/ui/skin/progress_spinner_strip.png
deleted file mode 100644
index 212a10629..000000000
Binary files a/data/shared/ui/skin/progress_spinner_strip.png and /dev/null differ
diff --git a/data/shared/ui/skin/progress_spinner_strip@288.png b/data/shared/ui/skin/progress_spinner_strip@288.png
deleted file mode 100644
index 180eac8c5..000000000
Binary files a/data/shared/ui/skin/progress_spinner_strip@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/radio.png b/data/shared/ui/skin/radio.png
deleted file mode 100644
index bfff79668..000000000
Binary files a/data/shared/ui/skin/radio.png and /dev/null differ
diff --git a/data/shared/ui/skin/radio@288.png b/data/shared/ui/skin/radio@288.png
deleted file mode 100644
index accbc38d3..000000000
Binary files a/data/shared/ui/skin/radio@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/radio_mark.png b/data/shared/ui/skin/radio_mark.png
deleted file mode 100644
index 570f48ad8..000000000
Binary files a/data/shared/ui/skin/radio_mark.png and /dev/null differ
diff --git a/data/shared/ui/skin/radio_mark@288.png b/data/shared/ui/skin/radio_mark@288.png
deleted file mode 100644
index 3bb4ec0be..000000000
Binary files a/data/shared/ui/skin/radio_mark@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/radio_pressed.png b/data/shared/ui/skin/radio_pressed.png
deleted file mode 100644
index a9836185e..000000000
Binary files a/data/shared/ui/skin/radio_pressed.png and /dev/null differ
diff --git a/data/shared/ui/skin/radio_pressed@288.png b/data/shared/ui/skin/radio_pressed@288.png
deleted file mode 100644
index e98c52a9a..000000000
Binary files a/data/shared/ui/skin/radio_pressed@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/remove.png b/data/shared/ui/skin/remove.png
deleted file mode 100644
index 80412d782..000000000
Binary files a/data/shared/ui/skin/remove.png and /dev/null differ
diff --git a/data/shared/ui/skin/remove@288.png b/data/shared/ui/skin/remove@288.png
deleted file mode 100644
index 9b6a3304c..000000000
Binary files a/data/shared/ui/skin/remove@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/resizer.png b/data/shared/ui/skin/resizer.png
deleted file mode 100644
index 5918a7b20..000000000
Binary files a/data/shared/ui/skin/resizer.png and /dev/null differ
diff --git a/data/shared/ui/skin/resizer@288.png b/data/shared/ui/skin/resizer@288.png
deleted file mode 100644
index f6654b034..000000000
Binary files a/data/shared/ui/skin/resizer@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_bg_x.png b/data/shared/ui/skin/scroll_bg_x.png
deleted file mode 100644
index fc2eb5df9..000000000
Binary files a/data/shared/ui/skin/scroll_bg_x.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_bg_x@288.png b/data/shared/ui/skin/scroll_bg_x@288.png
deleted file mode 100644
index e6abf5e56..000000000
Binary files a/data/shared/ui/skin/scroll_bg_x@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_bg_y.png b/data/shared/ui/skin/scroll_bg_y.png
deleted file mode 100644
index 2775e3b43..000000000
Binary files a/data/shared/ui/skin/scroll_bg_y.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_bg_y@288.png b/data/shared/ui/skin/scroll_bg_y@288.png
deleted file mode 100644
index ecb61d10b..000000000
Binary files a/data/shared/ui/skin/scroll_bg_y@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_fg_x.png b/data/shared/ui/skin/scroll_fg_x.png
deleted file mode 100644
index 6bc8a5a10..000000000
Binary files a/data/shared/ui/skin/scroll_fg_x.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_fg_x@288.png b/data/shared/ui/skin/scroll_fg_x@288.png
deleted file mode 100644
index 0f1ad31d4..000000000
Binary files a/data/shared/ui/skin/scroll_fg_x@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_fg_y.png b/data/shared/ui/skin/scroll_fg_y.png
deleted file mode 100644
index 861e1bdf0..000000000
Binary files a/data/shared/ui/skin/scroll_fg_y.png and /dev/null differ
diff --git a/data/shared/ui/skin/scroll_fg_y@288.png b/data/shared/ui/skin/scroll_fg_y@288.png
deleted file mode 100644
index c99e3a3eb..000000000
Binary files a/data/shared/ui/skin/scroll_fg_y@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/search.png b/data/shared/ui/skin/search.png
deleted file mode 100644
index 79cd11f14..000000000
Binary files a/data/shared/ui/skin/search.png and /dev/null differ
diff --git a/data/shared/ui/skin/search@288.png b/data/shared/ui/skin/search@288.png
deleted file mode 100644
index 027e8918e..000000000
Binary files a/data/shared/ui/skin/search@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/section_container.png b/data/shared/ui/skin/section_container.png
deleted file mode 100644
index 331a3f555..000000000
Binary files a/data/shared/ui/skin/section_container.png and /dev/null differ
diff --git a/data/shared/ui/skin/section_container@288.png b/data/shared/ui/skin/section_container@288.png
deleted file mode 100644
index a107ccb70..000000000
Binary files a/data/shared/ui/skin/section_container@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/selection.png b/data/shared/ui/skin/selection.png
deleted file mode 100644
index 541c02a23..000000000
Binary files a/data/shared/ui/skin/selection.png and /dev/null differ
diff --git a/data/shared/ui/skin/selection@288.png b/data/shared/ui/skin/selection@288.png
deleted file mode 100644
index b728e06d9..000000000
Binary files a/data/shared/ui/skin/selection@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/skin.tb.txt b/data/shared/ui/skin/skin.tb.txt
deleted file mode 100644
index c41518ada..000000000
--- a/data/shared/ui/skin/skin.tb.txt
+++ /dev/null
@@ -1,517 +0,0 @@
-# This is the default skin of Turbo Badger
-# The license of the skin is Public Domain.
-#
-# For more information about Turbo Badger and its license,
-# see tb_core.h.
-description
- name Turbo Badger Default skin
- # Dimensions in dp (the default unit for padding and such) and bitmaps are specified for this DPI.
- base-dpi 96
- # The skin also has graphics available in these DPI modes
- supported-dpi 96 288
-defaults
- spacing 0
- text-color #fefefe
- placeholder
- opacity 0.2
- disabled
- opacity 0.3
-elements
- TBButton
- text-color #fefefe
- bitmap button.png
- cut 17
- expand 7
- padding 6 8
- overrides
- element TBButtonInGroup
- condition: target: parent, property: skin, value: button_group
- condition: target: parent, property: axis, value: x
- element TBButton.pressed
- state pressed
- TBButton.pressed
- text-color #fefefe
- bitmap button_pressed.png
- cut 17
- expand 7
- content-ofs-x 1
- content-ofs-y 1
-
- TBButton.flat
- text-color #fefefe
- padding 6 8
- children
- element TBButton.flat.hovered
- state hovered
- element TBButton.flat.pressed
- state pressed
- TBButton.flat.hovered
- bitmap button_flat_outline.png
- cut 15
- expand 6
- TBButton.flat.pressed
- bitmap button_flat_pressed.png
- cut 8
-
- # == TBButtonInGroup is not a widget. It's only used as override for TBButton under a "button_group" ====
- TBButtonInGroup
- bitmap button_grouped_x_middle_up.png
- cut 17
- expand 7
- padding 6 8
- overrides
- element TBButtonInGroup.first
- condition: target: prev sibling, property: skin, value: TBButton, test: !=
- element TBButtonInGroup.last
- condition: target: next sibling, property: skin, value: TBButton, test: !=
- element TBButtonInGroup.pressed
- state pressed
- TBButtonInGroup.pressed
- clone TBButtonInGroup
- bitmap button_grouped_x_middle_down.png
- content-ofs-x 1
- content-ofs-y 1
- overrides
- TBButtonInGroup.first
- clone TBButtonInGroup
- bitmap button_grouped_x_first_up.png
- overrides
- element TBButtonInGroup.first.pressed
- state pressed
- TBButtonInGroup.first.pressed
- clone TBButtonInGroup.pressed
- bitmap button_grouped_x_first_down.png
- overrides
- TBButtonInGroup.last
- clone TBButtonInGroup
- bitmap button_grouped_x_last_up.png
- overrides
- element TBButtonInGroup.last.pressed
- state pressed
- TBButtonInGroup.last.pressed
- clone TBButtonInGroup.pressed
- bitmap button_grouped_x_last_down.png
- overrides
-
- # == button_group is not a widget. It's specified on widgets that should group TBButton =======
- button_group
- spacing -1px
-
- # == TBSection skins ==========================================================================
- TBSection.layout
- spacing -1px
- TBSection.container
- bitmap section_container.png
- type StretchBorder
- cut 11
- expand 6
- padding 2
- TBSectionHeader
- bitmap window_mover_bg_tile.png
- type Tile
- expand -1
- padding 3 16
- children
- element TBSectionHeader.icon_0
- condition: target: this, property: value, value: 0
- condition: target: this, property: capture, test: !=
- element TBSectionHeader.icon_1
- condition: target: this, property: value, value: 1
- condition: target: this, property: capture, test: !=
- element TBSectionHeader.icon_pressed
- condition: target: this, property: capture
- overlays
- element TBSectionHeader.overlay
- state all
- TBSectionHeader.overlay
- bitmap window_mover_overlay.png
- type StretchBorder
- cut 16
- expand 3
- TBSectionHeader.icon_0
- bitmap toggle_section_icon_up.png
- type Image
- img-position-x 0
- img-ofs-x 4
- TBSectionHeader.icon_1
- bitmap toggle_section_icon_down.png
- type Image
- img-position-x 0
- img-ofs-x 4
- TBSectionHeader.icon_pressed
- bitmap toggle_section_icon_middle.png
- type Image
- img-position-x 0
- img-ofs-x 4
-
- Header
- bitmap window_mover_bg_tile.png
- type Tile
- expand -1
- padding 3 16
- overlays
- element Header.overlay
- state all
- Header.overlay
- bitmap window_mover_overlay.png
- type StretchBorder
- cut 16
- expand 3
-
- # == TBTabContainer skins - Create strong overrides for the tab buttons four alignments ============
- TBTabContainer.rootlayout
- spacing -1px
- TBTabContainer.tablayout_x
- padding 0 10
- TBTabContainer.tablayout_y
- padding 10 0
- TBTabContainer.container
- clone TBContainer
- TBTabContainer.tab
- strong-overrides
- element TBTabContainer.tab_top
- condition: target: ancestors, property: align, value: top
- element TBTabContainer.tab_bottom
- condition: target: ancestors, property: align, value: bottom
- element TBTabContainer.tab_left
- condition: target: ancestors, property: align, value: left
- element TBTabContainer.tab_right
- condition: target: ancestors, property: align, value: right
- # == Top tab button =============================
- TBTabContainer.tab_top
- bitmap tab_button_top_inactive.png
- cut 12
- expand 6
- padding 6 6 3 6
- min-width 50
- overrides
- element TBTabContainer.tab_top.pressed
- state pressed
- children
- element tab_top_focus
- state focused
- tab_top_focus
- type StretchBorder
- bitmap focus_tabbutton_top.png
- cut 12
- expand 6
- TBTabContainer.tab_top.pressed
- bitmap tab_button_top_active.png
- cut 13
- expand 6
- # == Bottom tab button =============================
- TBTabContainer.tab_bottom
- bitmap tab_button_bottom_inactive.png
- cut 12
- expand 6
- padding 3 6 6 6
- min-width 50
- overrides
- element TBTabContainer.tab_bottom.pressed
- state pressed
- children
- element tab_bottom_focus
- state focused
- tab_bottom_focus
- clone tab_top_focus
- flip-y 1
- TBTabContainer.tab_bottom.pressed
- bitmap tab_button_bottom_active.png
- cut 13
- expand 6
- # == Left tab button =============================
- TBTabContainer.tab_left
- bitmap tab_button_left_inactive.png
- cut 12
- expand 6
- padding 6 3 6 6
- min-width 50
- overrides
- element TBTabContainer.tab_left.pressed
- state pressed
- children
- element tab_left_focus
- state focused
- tab_left_focus
- type StretchBorder
- bitmap focus_tabbutton_left.png
- cut 12
- expand 6
- TBTabContainer.tab_left.pressed
- bitmap tab_button_left_active.png
- cut 13
- expand 6
- # == Right tab button =============================
- TBTabContainer.tab_right
- bitmap tab_button_right_inactive.png
- cut 12
- expand 6
- padding 6 6 6 3
- min-width 50
- overrides
- element TBTabContainer.tab_right.pressed
- state pressed
- children
- element tab_right_focus
- state focused
- tab_right_focus
- clone tab_left_focus
- flip-x 1
- TBTabContainer.tab_right.pressed
- bitmap tab_button_right_active.png
- cut 13
- expand 6
-
- # == TBEditField skin. Create strong overrides for the search type to add magnifier glass icon =====
- TBEditField.selection
- cut 2
- bitmap selection.png
- TBEditField
- bitmap editfield.png
- cut 12
- expand 4
- padding 4
- strong-overrides
- element TBEditField.search
- condition: target: this, property: edit-type, value: "search"
-
- TBEditField.search
- clone TBEditField
- padding 4 4 4 24
- min-width 50
- children
- element TBEditField.search.icon
- TBEditField.search.icon
- bitmap search.png
- type Image
- img-position-x 0
- img-ofs-x 5
-
- # == TBWindow skin =================================================================================
- TBWindow
- bitmap window.png
- cut 16
- expand 12
- padding 0
- overrides
- element TBWindow.selected
- state selected
- TBWindow.selected
- bitmap window_active.png
- cut 16
- expand 12
- TBWindow.close
- bitmap window_close.png
- type Image
- children
- element TBWindow.close.pressed
- state pressed
- TBWindow.close.pressed
- bitmap window_close_pressed.png
- type Image
- TBWindow.mover
- text-color #b8b8b8
- bitmap window_mover_bg_tile.png
- type Tile
- expand -1
- padding 4
- overrides
- element TBWindow.mover.active
- state selected
- children
- element TBWindow.mover.overlay
- state all
- TBWindow.mover.overlay
- bitmap window_mover_overlay.png
- cut 12
- expand 3
- TBWindow.mover.active
- clone TBWindow.mover
- text-color #fefefe
- overrides
- overlays
- children
-
- # == Misc skins ====================================================================================
- TBContainer
- bitmap container.png
- type StretchBorder
- cut 12
- expand 6
- padding 0
- TBCheckBox
- bitmap checkbox.png
- cut 19
- expand 7
- children
- element TBCheckBox.selected
- state selected
- element TBCheckBox.pressed
- state pressed
- TBCheckBox.selected
- bitmap checkbox_mark.png
- type Image
- expand 7
- TBCheckBox.pressed
- bitmap checkbox_pressed.png
- type Image
- TBRadioButton
- bitmap radio.png
- cut 19
- expand 7
- children
- element TBRadioButton.selected
- state selected
- element TBRadioButton.pressed
- state pressed
- TBRadioButton.selected
- bitmap radio_mark.png
- type Image
- expand 7
- TBRadioButton.pressed
- bitmap radio_pressed.png
- type Image
- expand 7
- TBLayout.fadeout_x
- bitmap fadeout_x.png
- TBLayout.fadeout_y
- bitmap fadeout_y.png
- TBSelectList
- clone TBEditField
- padding 2
- TBSelectDropdown
- clone TBButton
- TBSelectDropdown.arrow
- clone arrow.down
- TBSelectDropdown.window
- clone TBPopupWindow
- TBPopupWindow
- clone TBWindow
- padding 2
- TBMenuWindow
- clone TBPopupWindow
- TBSelectItem
- padding 4 10
- children
- element TBSelectItem.hovered
- state hovered
- element TBSelectItem.selected
- state selected
- TBSelectItem.selected
- cut 7
- bitmap item_selected.png
- TBSelectItem.hovered
- cut 7
- bitmap item_hover.png
- TBSelectItem.separator
- clone TBSeparator
-
- TBSeparator
- bitmap item_separator_x.png
- type Stretch Image
- overrides
- element TBSeparator.y
- condition: target: parent, property: axis, value: x
- TBSeparator.y
- bitmap item_separator_y.png
- type Stretch Image
-
- TBScrollBarBgX
- bitmap scroll_bg_x.png
- cut 11
- expand 5
- TBScrollBarFgX
- bitmap scroll_fg_x.png
- cut 11
- expand 5
- TBScrollBarBgY
- bitmap scroll_bg_y.png
- cut 11
- expand 5
- TBScrollBarFgY
- bitmap scroll_fg_y.png
- cut 11
- expand 5
-
- TBSliderBgX
- bitmap slider_bg_x.png
- cut 9
- min-height 19
- max-height 19
- min-width 50
- TBSliderFgX
- bitmap slider_handle.png
- expand 5
-
- TBSliderBgY
- bitmap slider_bg_y.png
- cut 9
- min-width 19
- max-width 19
- min-height 50
- TBSliderFgY
- clone TBSliderFgX
-
- TBResizer
- bitmap resizer.png
- TBInlineSelect
- max-width 110
- TBDimmer
- background-color #00000088
-
- TBProgressSpinner
- min-width 28
- min-height 28
- TBProgressSpinner.fg
- bitmap progress_spinner_strip.png
-
- # The TBList header is always disabled, thus gets slightly less opacity default.
- TBList.header
-
- arrow.left: type: Image, bitmap: arrow_left.png, min-width: 5, min-height: 10
- arrow.right: type: Image, bitmap: arrow_right.png, min-width: 5, min-height: 10
- arrow.up: type: Image, bitmap: arrow_up.png, min-width: 10, min-height: 5
- arrow.down: type: Image, bitmap: arrow_down.png, min-width: 10, min-height: 5
- generic_focus
- bitmap focus_r4.png
- cut 11
- expand 4
-
- image_caption
- background-color #00000088
-
- button_remove
- bitmap remove.png
- type Image
- padding 5
-
- accent_color
- text-color #001111
-
- no-padding-container
- type StretchBox
- bitmap window.png
- cut 16
- expand 12
- padding 0
-
- container
- type StretchBox
- bitmap window.png
- cut 16
- expand 12
- padding 6
-
- separator
- bitmap item_separator_x.png
- type Stretch Image
-
- icon-filedialog-file
- bitmap filedialog-file.png
- type Image
- padding 5
-
- icon-filedialog-dir
- bitmap filedialog-dir.png
- type Image
- padding 5
diff --git a/data/shared/ui/skin/slider_bg_x.png b/data/shared/ui/skin/slider_bg_x.png
deleted file mode 100644
index 71c31634b..000000000
Binary files a/data/shared/ui/skin/slider_bg_x.png and /dev/null differ
diff --git a/data/shared/ui/skin/slider_bg_x@288.png b/data/shared/ui/skin/slider_bg_x@288.png
deleted file mode 100644
index 943c440af..000000000
Binary files a/data/shared/ui/skin/slider_bg_x@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/slider_bg_y.png b/data/shared/ui/skin/slider_bg_y.png
deleted file mode 100644
index d756e841a..000000000
Binary files a/data/shared/ui/skin/slider_bg_y.png and /dev/null differ
diff --git a/data/shared/ui/skin/slider_bg_y@288.png b/data/shared/ui/skin/slider_bg_y@288.png
deleted file mode 100644
index 4fab0890d..000000000
Binary files a/data/shared/ui/skin/slider_bg_y@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/slider_handle.png b/data/shared/ui/skin/slider_handle.png
deleted file mode 100644
index 94489a013..000000000
Binary files a/data/shared/ui/skin/slider_handle.png and /dev/null differ
diff --git a/data/shared/ui/skin/slider_handle@288.png b/data/shared/ui/skin/slider_handle@288.png
deleted file mode 100644
index 8b28ce1b9..000000000
Binary files a/data/shared/ui/skin/slider_handle@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_bottom_active.png b/data/shared/ui/skin/tab_button_bottom_active.png
deleted file mode 100644
index 77ee097db..000000000
Binary files a/data/shared/ui/skin/tab_button_bottom_active.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_bottom_active@288.png b/data/shared/ui/skin/tab_button_bottom_active@288.png
deleted file mode 100644
index 0dbf119ea..000000000
Binary files a/data/shared/ui/skin/tab_button_bottom_active@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_bottom_inactive.png b/data/shared/ui/skin/tab_button_bottom_inactive.png
deleted file mode 100644
index 99d3c9062..000000000
Binary files a/data/shared/ui/skin/tab_button_bottom_inactive.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_bottom_inactive@288.png b/data/shared/ui/skin/tab_button_bottom_inactive@288.png
deleted file mode 100644
index ab5d043fb..000000000
Binary files a/data/shared/ui/skin/tab_button_bottom_inactive@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_left_active.png b/data/shared/ui/skin/tab_button_left_active.png
deleted file mode 100644
index ed6f4620c..000000000
Binary files a/data/shared/ui/skin/tab_button_left_active.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_left_active@288.png b/data/shared/ui/skin/tab_button_left_active@288.png
deleted file mode 100644
index 5310f792f..000000000
Binary files a/data/shared/ui/skin/tab_button_left_active@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_left_inactive.png b/data/shared/ui/skin/tab_button_left_inactive.png
deleted file mode 100644
index d2e207909..000000000
Binary files a/data/shared/ui/skin/tab_button_left_inactive.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_left_inactive@288.png b/data/shared/ui/skin/tab_button_left_inactive@288.png
deleted file mode 100644
index 94a206761..000000000
Binary files a/data/shared/ui/skin/tab_button_left_inactive@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_right_active.png b/data/shared/ui/skin/tab_button_right_active.png
deleted file mode 100644
index 276d23f79..000000000
Binary files a/data/shared/ui/skin/tab_button_right_active.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_right_active@288.png b/data/shared/ui/skin/tab_button_right_active@288.png
deleted file mode 100644
index 2bab17ee2..000000000
Binary files a/data/shared/ui/skin/tab_button_right_active@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_right_inactive.png b/data/shared/ui/skin/tab_button_right_inactive.png
deleted file mode 100644
index 47f4def72..000000000
Binary files a/data/shared/ui/skin/tab_button_right_inactive.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_right_inactive@288.png b/data/shared/ui/skin/tab_button_right_inactive@288.png
deleted file mode 100644
index 67c81150c..000000000
Binary files a/data/shared/ui/skin/tab_button_right_inactive@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_top_active.png b/data/shared/ui/skin/tab_button_top_active.png
deleted file mode 100644
index 271b679f0..000000000
Binary files a/data/shared/ui/skin/tab_button_top_active.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_top_active@288.png b/data/shared/ui/skin/tab_button_top_active@288.png
deleted file mode 100644
index 04de8e142..000000000
Binary files a/data/shared/ui/skin/tab_button_top_active@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_top_inactive.png b/data/shared/ui/skin/tab_button_top_inactive.png
deleted file mode 100644
index 16023b187..000000000
Binary files a/data/shared/ui/skin/tab_button_top_inactive.png and /dev/null differ
diff --git a/data/shared/ui/skin/tab_button_top_inactive@288.png b/data/shared/ui/skin/tab_button_top_inactive@288.png
deleted file mode 100644
index 0c3141075..000000000
Binary files a/data/shared/ui/skin/tab_button_top_inactive@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/toggle_section_icon_down.png b/data/shared/ui/skin/toggle_section_icon_down.png
deleted file mode 100644
index 23bb510d6..000000000
Binary files a/data/shared/ui/skin/toggle_section_icon_down.png and /dev/null differ
diff --git a/data/shared/ui/skin/toggle_section_icon_down@288.png b/data/shared/ui/skin/toggle_section_icon_down@288.png
deleted file mode 100644
index ea0cf4060..000000000
Binary files a/data/shared/ui/skin/toggle_section_icon_down@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/toggle_section_icon_middle.png b/data/shared/ui/skin/toggle_section_icon_middle.png
deleted file mode 100644
index 919848274..000000000
Binary files a/data/shared/ui/skin/toggle_section_icon_middle.png and /dev/null differ
diff --git a/data/shared/ui/skin/toggle_section_icon_middle@288.png b/data/shared/ui/skin/toggle_section_icon_middle@288.png
deleted file mode 100644
index fcb7e700e..000000000
Binary files a/data/shared/ui/skin/toggle_section_icon_middle@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/toggle_section_icon_up.png b/data/shared/ui/skin/toggle_section_icon_up.png
deleted file mode 100644
index e9bdf693a..000000000
Binary files a/data/shared/ui/skin/toggle_section_icon_up.png and /dev/null differ
diff --git a/data/shared/ui/skin/toggle_section_icon_up@288.png b/data/shared/ui/skin/toggle_section_icon_up@288.png
deleted file mode 100644
index 8db5cee2a..000000000
Binary files a/data/shared/ui/skin/toggle_section_icon_up@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/window.png b/data/shared/ui/skin/window.png
deleted file mode 100644
index 93ffeccaf..000000000
Binary files a/data/shared/ui/skin/window.png and /dev/null differ
diff --git a/data/shared/ui/skin/window@288.png b/data/shared/ui/skin/window@288.png
deleted file mode 100644
index 29b793848..000000000
Binary files a/data/shared/ui/skin/window@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_active.png b/data/shared/ui/skin/window_active.png
deleted file mode 100644
index 20232c3fd..000000000
Binary files a/data/shared/ui/skin/window_active.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_active@288.png b/data/shared/ui/skin/window_active@288.png
deleted file mode 100644
index 0f18a6735..000000000
Binary files a/data/shared/ui/skin/window_active@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_close.png b/data/shared/ui/skin/window_close.png
deleted file mode 100644
index 810045118..000000000
Binary files a/data/shared/ui/skin/window_close.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_close@288.png b/data/shared/ui/skin/window_close@288.png
deleted file mode 100644
index 20e5defb8..000000000
Binary files a/data/shared/ui/skin/window_close@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_close_pressed.png b/data/shared/ui/skin/window_close_pressed.png
deleted file mode 100644
index 91e2166cf..000000000
Binary files a/data/shared/ui/skin/window_close_pressed.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_close_pressed@288.png b/data/shared/ui/skin/window_close_pressed@288.png
deleted file mode 100644
index f04cb49d7..000000000
Binary files a/data/shared/ui/skin/window_close_pressed@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_mover_bg_tile.png b/data/shared/ui/skin/window_mover_bg_tile.png
deleted file mode 100644
index 5d00a2562..000000000
Binary files a/data/shared/ui/skin/window_mover_bg_tile.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_mover_bg_tile@288.png b/data/shared/ui/skin/window_mover_bg_tile@288.png
deleted file mode 100644
index 621f2724f..000000000
Binary files a/data/shared/ui/skin/window_mover_bg_tile@288.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_mover_overlay.png b/data/shared/ui/skin/window_mover_overlay.png
deleted file mode 100644
index 2490d5c13..000000000
Binary files a/data/shared/ui/skin/window_mover_overlay.png and /dev/null differ
diff --git a/data/shared/ui/skin/window_mover_overlay@288.png b/data/shared/ui/skin/window_mover_overlay@288.png
deleted file mode 100644
index 625ae8e73..000000000
Binary files a/data/shared/ui/skin/window_mover_overlay@288.png and /dev/null differ
diff --git a/data/shared/ui/window/filedialog.tb.txt b/data/shared/ui/window/filedialog.tb.txt
deleted file mode 100644
index d148cc285..000000000
--- a/data/shared/ui/window/filedialog.tb.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-WindowInfo
- title File dialog
- size 800 500
-
-TBLayout: distribution: gravity, axis: x, size: available
- TBLayout: distribution: gravity, axis: y
- TBSelectList
- id dirs
- gravity all
-
- TBLayout: distribution: gravity, axis: y, size: available
- TBEditField
- id input
- autofocus 1
-
- TBSeparator: gravity: left right, skin: separator
- TBSelectList
- id files
- gravity all
-
- TBSeparator: gravity: left right, skin: separator
- TBLayout: distribution: gravity, axis: x
- TBButton: text: Ok, id: ok, autofocus: 1, gravity: left right, size: gravity
- TBButton: text: Cancel, id: cancel, gravity: left right, size: gravity
- TBSelectDropdown: id: filter
diff --git a/data/shared/ui/window/filedialog_dir.tb.txt b/data/shared/ui/window/filedialog_dir.tb.txt
deleted file mode 100644
index 1ad7730ed..000000000
--- a/data/shared/ui/window/filedialog_dir.tb.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-TBSkinImage: id: icon, skin: icon-filedialog-dir, ignore-input: 1
-TBTextField: id: name, text-align: left, ignore-input: 1
diff --git a/data/shared/ui/window/filedialog_file.tb.txt b/data/shared/ui/window/filedialog_file.tb.txt
deleted file mode 100644
index accb78912..000000000
--- a/data/shared/ui/window/filedialog_file.tb.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-TBSkinImage: id: icon, skin: icon-filedialog-file, ignore-input: 1
-TBTextField: id: name, text-align: left, ignore-input: 1
diff --git a/data/testturbobadger/demo01/images/image_1.png b/data/testturbobadger/demo01/images/image_1.png
deleted file mode 100644
index 1e9ce2efe..000000000
Binary files a/data/testturbobadger/demo01/images/image_1.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_2.png b/data/testturbobadger/demo01/images/image_2.png
deleted file mode 100644
index c784af65c..000000000
Binary files a/data/testturbobadger/demo01/images/image_2.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_3.png b/data/testturbobadger/demo01/images/image_3.png
deleted file mode 100644
index 95b0ed5ed..000000000
Binary files a/data/testturbobadger/demo01/images/image_3.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_4.png b/data/testturbobadger/demo01/images/image_4.png
deleted file mode 100644
index fcfbb81b4..000000000
Binary files a/data/testturbobadger/demo01/images/image_4.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_5.png b/data/testturbobadger/demo01/images/image_5.png
deleted file mode 100644
index 7a7a36df7..000000000
Binary files a/data/testturbobadger/demo01/images/image_5.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_6.png b/data/testturbobadger/demo01/images/image_6.png
deleted file mode 100644
index e363a8dc0..000000000
Binary files a/data/testturbobadger/demo01/images/image_6.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_7.png b/data/testturbobadger/demo01/images/image_7.png
deleted file mode 100644
index adbbec037..000000000
Binary files a/data/testturbobadger/demo01/images/image_7.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_8.png b/data/testturbobadger/demo01/images/image_8.png
deleted file mode 100644
index 79dba923f..000000000
Binary files a/data/testturbobadger/demo01/images/image_8.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/images/image_9.png b/data/testturbobadger/demo01/images/image_9.png
deleted file mode 100644
index ba59ceb67..000000000
Binary files a/data/testturbobadger/demo01/images/image_9.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/language/lng_en.tb.txt b/data/testturbobadger/demo01/language/lng_en.tb.txt
deleted file mode 100644
index 046301bfd..000000000
--- a/data/testturbobadger/demo01/language/lng_en.tb.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-cut Cut
-copy Copy
-paste Paste
-delete Delete
-selectall Select all
-undo Undo
-redo Redo
-TBMessageWindow.ok Ok
-TBMessageWindow.cancel Cancel
-TBMessageWindow.yes Yes
-TBMessageWindow.no No
-TBList.header Showing %d of %d
-new New
-save Save
-close Close
-search Search
diff --git a/data/testturbobadger/demo01/language/lng_sv.tb.txt b/data/testturbobadger/demo01/language/lng_sv.tb.txt
deleted file mode 100644
index be22d2649..000000000
--- a/data/testturbobadger/demo01/language/lng_sv.tb.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-cut Klipp ut
-copy Kopiera
-paste Klistra in
-delete Ta bort
-selectall Markera all
-undo Ångra
-redo Gör om
-TBMessageWindow.ok Ok
-TBMessageWindow.cancel Avbryt
-TBMessageWindow.yes Ja
-TBMessageWindow.no Nej
-TBList.header Visar %d av %d
-new Ny
-save Spara
-close Stäng
-search Sök
diff --git a/data/testturbobadger/demo01/skin/bg_tile.png b/data/testturbobadger/demo01/skin/bg_tile.png
deleted file mode 100644
index 36c3fca41..000000000
Binary files a/data/testturbobadger/demo01/skin/bg_tile.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/focus_r8.png b/data/testturbobadger/demo01/skin/focus_r8.png
deleted file mode 100644
index bbd923bbc..000000000
Binary files a/data/testturbobadger/demo01/skin/focus_r8.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/icon128.png b/data/testturbobadger/demo01/skin/icon128.png
deleted file mode 100644
index 02797f3b6..000000000
Binary files a/data/testturbobadger/demo01/skin/icon128.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/icon16.png b/data/testturbobadger/demo01/skin/icon16.png
deleted file mode 100644
index ddaa54fe6..000000000
Binary files a/data/testturbobadger/demo01/skin/icon16.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/icon48.png b/data/testturbobadger/demo01/skin/icon48.png
deleted file mode 100644
index a113662f8..000000000
Binary files a/data/testturbobadger/demo01/skin/icon48.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/image_frame.png b/data/testturbobadger/demo01/skin/image_frame.png
deleted file mode 100644
index af92850e1..000000000
Binary files a/data/testturbobadger/demo01/skin/image_frame.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/remove.png b/data/testturbobadger/demo01/skin/remove.png
deleted file mode 100644
index 0cc7abca5..000000000
Binary files a/data/testturbobadger/demo01/skin/remove.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/special_button.png b/data/testturbobadger/demo01/skin/special_button.png
deleted file mode 100644
index db759f8ff..000000000
Binary files a/data/testturbobadger/demo01/skin/special_button.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/special_button_pressed.png b/data/testturbobadger/demo01/skin/special_button_pressed.png
deleted file mode 100644
index 96235c324..000000000
Binary files a/data/testturbobadger/demo01/skin/special_button_pressed.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gold.png b/data/testturbobadger/demo01/skin/star_gold.png
deleted file mode 100644
index 1c4bebac9..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gold.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gold@192.png b/data/testturbobadger/demo01/skin/star_gold@192.png
deleted file mode 100644
index 4591227bb..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gold@192.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gold@288.png b/data/testturbobadger/demo01/skin/star_gold@288.png
deleted file mode 100644
index 0941e68b8..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gold@288.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gold@384.png b/data/testturbobadger/demo01/skin/star_gold@384.png
deleted file mode 100644
index 3ec2fdb52..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gold@384.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gray.png b/data/testturbobadger/demo01/skin/star_gray.png
deleted file mode 100644
index 2266b33f8..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gray.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gray@192.png b/data/testturbobadger/demo01/skin/star_gray@192.png
deleted file mode 100644
index 95a5d4537..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gray@192.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gray@288.png b/data/testturbobadger/demo01/skin/star_gray@288.png
deleted file mode 100644
index 119f88a29..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gray@288.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/star_gray@384.png b/data/testturbobadger/demo01/skin/star_gray@384.png
deleted file mode 100644
index a6bc66ad2..000000000
Binary files a/data/testturbobadger/demo01/skin/star_gray@384.png and /dev/null differ
diff --git a/data/testturbobadger/demo01/skin/testturbobadger-skin.tb.txt b/data/testturbobadger/demo01/skin/testturbobadger-skin.tb.txt
deleted file mode 100644
index 4ab3a753a..000000000
--- a/data/testturbobadger/demo01/skin/testturbobadger-skin.tb.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-# Demo skin override (contains some additions for the demo)
-description
- name Turbo Badger Default skin
- # Dimensions in dp (the default unit for padding and such) and bitmaps are specified for this DPI.
- base-dpi 96
- # The skin also has graphics available in these DPI modes
- supported-dpi 96 288
-elements
- Icon16
- bitmap icon16.png
- min-width 16
- min-height 16
- Icon48
- bitmap icon48.png
- cut 4
- min-width 20
- min-height 20
- Icon128
- bitmap icon128.png
- background
- bitmap bg_tile.png
- type Tile
- background_solid
- background-color #3b3b3b
- padding 10
- SpecialButton
- bitmap special_button.png
- cut 17
- expand 7
- padding 6 8
- overrides
- element SpecialButton.pressed
- state pressed
- overlays
- element generic_focus_r8
- state focused
- element Star
- condition: target: ancestors, property: skin, value: "Starry buttons"
- SpecialButton.pressed
- bitmap special_button_pressed.png
- cut 17
- expand 7
- content-ofs-x 1
- content-ofs-y 1
- ImageCaption
- background-color #00000066
- ImageFrame
- overlays
- element ImageFrame.overlay
- state all
- ImageFrame.overlay
- bitmap image_frame.png
- cut 22
- expand 15
- Remove
- bitmap remove.png
- type Image
- padding 5
- Star
- bitmap star_gray.png
- type Image
- img-position-x 0
- img-position-y 0
- img-ofs-x -8
- img-ofs-y -12
- overrides
- element Star.active
- condition: target: this, property: "window active"
- condition: target: parent, property: hover
- Star.active
- bitmap star_gold.png
- type Image
- img-position-x 0
- img-position-y 0
- img-ofs-x -10
- img-ofs-y -14
- generic_focus_r8
- bitmap focus_r8.png
- cut 14
- expand 4
diff --git a/data/testturbobadger/demo01/ui_resources/resource_edit_test.tb.txt b/data/testturbobadger/demo01/ui_resources/resource_edit_test.tb.txt
deleted file mode 100644
index 8370807b1..000000000
--- a/data/testturbobadger/demo01/ui_resources/resource_edit_test.tb.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-TBLayout
- distribution available
- axis y
- TBLayout
- TBButton
- text Button 1
- TBRadioButton
- TBCheckBox
- @if 1
- TBContainer
- TBLayout
- TBSlider
- value 0.5
- TBScrollBar
- TBEditField
- multiline 1
- readonly 1
- TBEditField
- text Hello world\nHello world
- adapt-to-content 1
- multiline 1
diff --git a/data/testturbobadger/demo01/ui_resources/resource_edit_window.tb.txt b/data/testturbobadger/demo01/ui_resources/resource_edit_window.tb.txt
deleted file mode 100644
index 87b84c9a3..000000000
--- a/data/testturbobadger/demo01/ui_resources/resource_edit_window.tb.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-TBLayout
- distribution gravity
- size available
- TBLayout
- gravity top bottom
- distribution available
- distribution-position top left
- size available
- axis y
- TBLayout
- distribution available
- TBButton
- text @new
- state disabled
- TBButton
- text @save
- state disabled
- TBButton
- text Test
- id test
- TBEditField
- placeholder @search
- type search
- id widget_list_search
- TBSelectList
- id widget_list
- TBLayout
- distribution available
- TBEditField
- id source_edit
- multiline 1
- gravity all
- TBLayout: axis: y, distribution: available, position: left
- TBScrollContainer
- id scroll_container
- gravity all
- TBClickLabel: text: "Adapt to container"
- TBCheckBox: id: "constrained"
diff --git a/data/testturbobadger/demo01/ui_resources/test_animations.tb.txt b/data/testturbobadger/demo01/ui_resources/test_animations.tb.txt
deleted file mode 100644
index e0bc8f5e4..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_animations.tb.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-WindowInfo
- title Animations
-TBLayout: axis: y
- TBTextField: text: "Duration (in milliseconds):"
- TBInlineSelect: id: "duration", min: 0, max: 100000, value: 500
- TBTextField: text: "Curve:"
- TBSelectList: id: "curve", value: 1
- items
- item: text: "Linear"
- item: text: "Slow down"
- item: text: "Speed up"
- item: text: "Bezier"
- item: text: "Smooth"
- TBClickLabel: text: Fade
- TBCheckBox: id: fade, value: 1
- TBButton: text: "Animate!", id: "Animate!", skin: "SpecialButton"
diff --git a/data/testturbobadger/demo01/ui_resources/test_batching01.tb.txt b/data/testturbobadger/demo01/ui_resources/test_batching01.tb.txt
deleted file mode 100644
index 134368d0d..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_batching01.tb.txt
+++ /dev/null
@@ -1,381 +0,0 @@
-TBLayout
- axis y
- TBTextField: text: "For enabling \"Continuous repaint\" and test batching speed.
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
- TBLayout
- TBButton: text: "A"
- TBButton: text: "B"
- TBButton: text: "C"
- TBButton: text: "D"
- TBButton: text: "E"
- TBButton: text: "F"
- TBButton: text: "G"
- TBButton: text: "H"
- TBButton: text: "I"
- TBButton: text: "J"
- TBButton: text: "K"
- TBButton: text: "L"
- TBButton: text: "M"
- TBButton: text: "N"
- TBButton: text: "O"
- TBButton: text: "P"
- TBButton: text: "Q"
- TBButton: text: "R"
- TBButton: text: "S"
- TBButton: text: "T"
- TBButton: text: "U"
- TBButton: text: "V"
- TBButton: text: "W"
- TBButton: text: "X"
- TBButton: text: "Y"
- TBButton: text: "Z"
diff --git a/data/testturbobadger/demo01/ui_resources/test_connections.tb.txt b/data/testturbobadger/demo01/ui_resources/test_connections.tb.txt
deleted file mode 100644
index 80ce79862..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_connections.tb.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-WindowInfo
- title TBWidgetValue connections
-TBLayout
- axis y
- TBTextField
- text Numeric widgets sharing a connection
- TBContainer
- gravity all
- TBLayout
- TBInlineSelect
- connection master-volume
- min 0
- max 100
- TBSlider
- connection master-volume
- min 0
- max 100
- TBSlider
- axis y
- connection master-volume
- min 0
- max 100
- TBButton
- text Reset
- id reset-master-volume
- TBTextField
- text Text widgets sharing a connection
- TBContainer
- gravity all
- TBLayout
- TBEditField
- placeholder User name
- connection user-name
- min 0
- max 100
- TBEditField
- placeholder User name
- connection user-name
- min 0
- max 100
- TBButton
- text Reset
- id reset-user-name
diff --git a/data/testturbobadger/demo01/ui_resources/test_image_widget.tb.txt b/data/testturbobadger/demo01/ui_resources/test_image_widget.tb.txt
deleted file mode 100644
index cee787d87..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_image_widget.tb.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-WindowInfo
- title TBImageWidget
- size 350 500
-TBScrollContainer
- adapt-content 1
- TBLayout
- axis y
- spacing 20
- TBEditField: gravity: all, skin: 0, multiline: 1, readonly: 1, adapt-to-content: 1
- text: "Some images shown by TBImageWidget. This test requires enabling TB_IMAGE (see tb_config.h).\n" \
- "Images are unloaded when all references are removed (this window is closed)."
- TBImageWidget: filename: "Demo/demo01/images/image_1.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBImageWidget: filename: "Demo/demo01/images/image_2.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBImageWidget: filename: "Demo/demo01/images/image_3.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBImageWidget: filename: "Demo/demo01/images/image_4.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBImageWidget: filename: "Demo/demo01/images/image_5.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBImageWidget: filename: "Demo/demo01/images/image_6.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBTextField: skin: "ImageCaption", text: "Öland", gravity: bottom left right
- TBImageWidget: filename: "Demo/demo01/images/image_7.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBTextField: skin: "ImageCaption", text: "Öland", gravity: bottom left right
- TBImageWidget: filename: "Demo/demo01/images/image_8.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBTextField: skin: "ImageCaption", text: "Örebro", gravity: bottom left right
- TBImageWidget: filename: "Demo/demo01/images/image_9.png", skin: ImageFrame
- TBButton: skin: "Remove", id: "remove", gravity: right
- TBTextField: skin: "ImageCaption", text: "Stockholm", gravity: bottom left right
diff --git a/data/testturbobadger/demo01/ui_resources/test_layout01.tb.txt b/data/testturbobadger/demo01/ui_resources/test_layout01.tb.txt
deleted file mode 100644
index 4dc9c7a2c..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_layout01.tb.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-WindowInfo
- title TBLayout size & gravity
-# Declare a branch of layout nodes that is included in all three containers below.
-test_layout_content
- TBLayout
- TBButton
- text Default
- TBCheckBox
- value 1
- TBButton
- axis y
- text Foo Bar
- TBSkinImage
- skin Icon16
- TBButton
- gravity all
- text Gravity all
- TBButton
- gravity top
- text Gravity top
- TBButton
- gravity bottom
- text Gravity bottom
-TBLayout
- axis y
- TBLayout
- TBSelectDropdown
- text Select position
- id select position
- items
- item: text: "LAYOUT_POSITION_CENTER"
- item: text: "LAYOUT_POSITION_LEFT_TOP"
- item: text: "LAYOUT_POSITION_RIGHT_BOTTOM"
- item: text: "LAYOUT_POSITION_GRAVITY"
- TBButton
- text Toggle axis
- id toggle axis
- TBLayout
- id switch_layout
- axis y
- TBTextField: text: "size: preferred"
- TBContainer
- @include test_layout_content
- size preferred
- id 1
- TBTextField: text: "size: available"
- TBContainer
- @include test_layout_content
- size available
- id 2
- TBTextField: text: "size: gravity"
- TBContainer
- @include test_layout_content
- size gravity
- id 3
diff --git a/data/testturbobadger/demo01/ui_resources/test_layout02.tb.txt b/data/testturbobadger/demo01/ui_resources/test_layout02.tb.txt
deleted file mode 100644
index 31e0adc87..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_layout02.tb.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-WindowInfo
- title TBLayout distribution
-TBLayout: position: left top, axis: y
- TBTextField: text: "distribution: preferred"
- TBLayout: distribution: preferred
- TBButton: text: tab 1
- TBButton: text: tab 2
- TBButton: text: tab 3
- TBButton: text: tab 4
- TBEditField: placeholder: @search, gravity: left right, type: "search"
- TBTextField: text: "distribution: available"
- TBLayout: distribution: available
- TBButton: text: tab 1
- TBButton: text: tab 2
- TBButton: text: tab 3
- TBButton: text: tab 4
- TBEditField: placeholder: @search, gravity: left right, type: "search"
- TBTextField: text: "distribution: gravity"
- TBLayout: distribution: gravity
- TBButton: text: tab 1
- TBButton: text: tab 2
- TBButton: text: tab 3
- TBButton: text: tab 4
- TBEditField: placeholder: @search, gravity: left right, type: "search"
- TBTextField: text: gravity + trailing layout for right align
- TBLayout: distribution: gravity
- TBButton: text: tab 1
- TBButton: text: tab 2
- TBButton: text: tab 3
- TBButton: text: tab 4
- TBLayout: gravity: left right, distribution-position: right bottom
- TBEditField: placeholder: @search, type: "search"
- TBTextField: text: "gravity + mixed gravity"
- TBLayout: distribution: gravity
- TBButton: text: tab 1
- TBEditField: placeholder: @search, gravity: left right, type: "search"
- TBButton: text: tab 3
- TBButton: text: tab 4
- TBEditField: placeholder: @search, gravity: left right, type: "search"
diff --git a/data/testturbobadger/demo01/ui_resources/test_layout03.tb.txt b/data/testturbobadger/demo01/ui_resources/test_layout03.tb.txt
deleted file mode 100644
index 590ead2dd..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_layout03.tb.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-WindowInfo
- title Default TBWidget positioning
- size 350 350
-TBLayout: axis: y, distribution: gravity
- TBLayout: distribution: available, gravity: left right
- TBEditField: gravity: all, skin: 0, multiline: 1, readonly: 1
- text: "Any widget may contain children and by default applies basic gravity positioning.\n" \
- "To achieve more advanced layout, you would normally wrap a layouting " \
- "widget (f.ex TBLayout) but sometimes the default is enough.\n" \
- "The default preferred size is calculated to the largest child " \
- "(or the skin if there are no children)."
- TBContainer: gravity: all
- TBTextField: text: "all", gravity: all
- TBTextField: text: "top, left, right", gravity: top left right
- TBTextField: text: "bottom, left, right", gravity: bottom left right
- TBTextField: text: "left, top, bottom", gravity: left top bottom
- TBTextField: text: "right, top, bottom", gravity: right top bottom
- TBButton: text: Upper left
- TBButton: text: Upper right, gravity: right
- TBButton: text: Lower left, gravity: bottom
- TBButton: text: Lower right, gravity: bottom right
diff --git a/data/testturbobadger/demo01/ui_resources/test_list_item.tb.txt b/data/testturbobadger/demo01/ui_resources/test_list_item.tb.txt
deleted file mode 100644
index 65ae1a1bb..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_list_item.tb.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-TBCheckBox: id: check
-TBSkinImage: id: icon, skin: Icon48, ignore-input: 1
-TBLayout: axis: y, position: left, spacing: 0, ignore-input: 1, size: available, position: left top
- TBTextField: id: name, text-align: left
- TBTextField: id: info, text-align: left, state: disabled
-TBButton: id: delete, skin: TBWindow.close
\ No newline at end of file
diff --git a/data/testturbobadger/demo01/ui_resources/test_radio_checkbox.tb.txt b/data/testturbobadger/demo01/ui_resources/test_radio_checkbox.tb.txt
deleted file mode 100644
index f9ef455ca..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_radio_checkbox.tb.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-WindowInfo
- title Radiobutton & checkbox
-TBLayout: position: left top, axis: y
- TBTextField: text: "Radiobuttons, anonymous group:"
- TBLayout: distribution: preferred
- TBRadioButton
- TBRadioButton
- TBRadioButton: state: disabled
- TBTextField: text: "Radiobuttons, group-id: 'R1'":
- TBLayout: distribution: preferred
- TBRadioButton: group-id: R1
- TBRadioButton: group-id: R1
- TBRadioButton: group-id: R1, state: disabled
- TBTextField: text: "Radiobuttons, group-id: 'R2' value set":
- TBLayout: distribution: preferred
- TBRadioButton: group-id: R2, value: 1
- TBRadioButton: group-id: R2
- TBRadioButton: group-id: R2, state: disabled
- TBTextField: text: "Checkboxes"
- TBLayout: distribution: preferred
- TBCheckBox
- TBCheckBox: value: 1
- TBCheckBox: state: disabled
- TBCheckBox: state: disabled, value: 1
- TBTextField: text: "TBClickLabel with radio & check"
- TBClickLabel: text: Some text to click
- TBCheckBox
- TBClickLabel: text: Some text to click
- TBRadioButton
- TBClickLabel: text: Some text to click, state: disabled
- TBCheckBox
- TBClickLabel: text: Some text to click, state: disabled
- TBRadioButton
- TBTextField: text: "Regular buttons with group-id: 'R3'":
- TBLayout: distribution: preferred
- TBButton: text: "A", group-id: "R3", value: 1
- TBButton: text: "B", group-id: "R3"
- TBButton: text: "C", group-id: "R3"
diff --git a/data/testturbobadger/demo01/ui_resources/test_scrollcontainer.tb.txt b/data/testturbobadger/demo01/ui_resources/test_scrollcontainer.tb.txt
deleted file mode 100644
index 4b97c3d90..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_scrollcontainer.tb.txt
+++ /dev/null
@@ -1,123 +0,0 @@
-WindowInfo
- title TBScrollContainer with misc widgets
- size 500 500
-TBLayout
- gravity all
- distribution available
- axis y
- TBScrollContainer
- TBLayout
- position left top
- axis y
- TBTextField: text: Buttons with different fonts:
- TBLayout
- TBButton
- text: "Orange"
- font: name: Orange
- TBButton
- text: "Segoe 14"
- font: size: 14px
- TBButton
- text: "Segoe 28"
- font: size: 28px
- TBTextField: text: TBButton containing TBSkinImage:
- TBLayout
- TBButton
- text Click for image!
- id add img
- TBSkinImage
- skin Icon16
- TBButton
- axis y
- text Click for image!
- id add img
- TBSkinImage
- skin Icon16
- TBTextField: text: "TBButton containing TBEditField:"
- TBLayout
- TBButton
- TBEditField: gravity: all, skin: 0, multiline: 1, readonly: 1, adapt-to-content: 1, styling: 1
- text: "A TBButton with styled text that is able to wrap to multiple lines."
- TBTextField: text: "Showing menu manually, and TBSelectDropdown:"
- TBLayout
- TBButton
- text Give me a popup menu!
- id showpopupmenu1
- TBSelectDropdown
- text Dropdown
- id name dropdown
- TBSelectDropdown
- text Customized items in Dropdown
- id advanced dropdown
- TBLayout
- overflow scroll
- TBRadioButton
- TBCheckBox
- value 1
- TBSkinImage
- skin Icon16
- TBSkinImage
- skin Icon48
- TBButton
- TBButton: toggle-mode: 1
- TBTextField: text: "TBEditField:"
- TBLayout
- TBEditField
- text Edit type text
- TBEditField
- type search
- text Edit type search
- TBEditField
- type password
- text pwd goes here
- TBEditField
- text In this field, multiple lines are enabled.
- multiline 1
- TBTextField: text: "TBSlider:"
- TBLayout
- TBSlider
- TBSlider
- min 100
- max 200
- value 150
- TBSlider
- axis y
- min 0
- max 100
- connection master-volume
- TBTextField: text: "TBScrollbar:"
- TBLayout
- TBScrollBar
- TBScrollBar
- axis y
- TBTextField: text: Horizontal layout:
- TBLayout
- id horizontal_layout
- TBButton
- text "1 new button"
- id new buttons
- data 1
- TBButton
- text "100 new buttons!"
- id new buttons
- data 100
- TBButton
- text "10 new with delay!"
- id new buttons delayed
- data 10
- TBTextField: text: Vertical layout:
- TBLayout
- id vertical_layout
- axis y
- TBButton
- text "1 new button"
- id new buttons
- data 1
- TBButton
- text "100 new buttons!"
- id new buttons
- data 100
- TBButton
- text "10 new with delay!"
- id new buttons delayed
- data 10
diff --git a/data/testturbobadger/demo01/ui_resources/test_scroller_snap.tb.txt b/data/testturbobadger/demo01/ui_resources/test_scroller_snap.tb.txt
deleted file mode 100644
index 1ced50c0f..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_scroller_snap.tb.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-WindowInfo
- title TBScrollerSnapListener
-definitions
- pagesize
- lp: width: 200, height: 300
-TBScrollContainer: id: "page-scroller"
- @include definitions>pagesize
- scroll-mode off
- TBLayout
- spacing 0
- TBContainer
- @include definitions>pagesize
- TBTextField: text: "One - Swipe to next page"
- TBContainer
- @include definitions>pagesize
- TBTextField: text: "Two"
- TBContainer
- @include definitions>pagesize
- TBTextField: text: "Three"
- TBContainer
- @include definitions>pagesize
- TBTextField: text: "Four"
- TBContainer
- @include definitions>pagesize
- TBTextField: text: "Five - Last page"
diff --git a/data/testturbobadger/demo01/ui_resources/test_select.tb.txt b/data/testturbobadger/demo01/ui_resources/test_select.tb.txt
deleted file mode 100644
index d0028516f..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_select.tb.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-WindowInfo
- title List and filter
- position 1100 50
-TBLayout
- axis y
- distribution gravity
- gravity all
- TBEditField
- id filter
- gravity left right
- placeholder @search
- type search
- TBSelectList
- id list
- gravity all
diff --git a/data/testturbobadger/demo01/ui_resources/test_select_advanced.tb.txt b/data/testturbobadger/demo01/ui_resources/test_select_advanced.tb.txt
deleted file mode 100644
index 6f73dc795..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_select_advanced.tb.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-WindowInfo
- title Customized list items
- position 770 50
- size 300 300
-TBLayout
- axis y
- distribution gravity
- gravity all
- TBLayout
- distribution gravity
- TBEditField
- id filter
- gravity left right
- placeholder @search
- type search
- TBSelectList
- id list
- gravity all
- TBLayout
- distribution gravity
- TBEditField
- id add_name
- gravity left right
- placeholder Name
- TBButton
- id add
- text Add
- TBButton
- id delete all
- text Delete all
diff --git a/data/testturbobadger/demo01/ui_resources/test_skin_conditions01.tb.txt b/data/testturbobadger/demo01/ui_resources/test_skin_conditions01.tb.txt
deleted file mode 100644
index 4439ddf47..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_skin_conditions01.tb.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-WindowInfo
- title Skin conditions
- position 200 170
-TBLayout: axis: y
- TBTextField: text: Normal layout with buttons:
- TBContainer
- TBLayout
- TBButton: text: " A ", skin: "SpecialButton"
- TBButton: text: " B ", skin: "SpecialButton"
- TBButton: text: " C ", skin: "SpecialButton"
- TBTextField: text: Layout with skin "Starry buttons":
- TBContainer
- TBLayout: skin: Starry buttons
- TBButton: text: " A ", skin: "SpecialButton"
- TBButton: text: " B ", skin: "SpecialButton"
- TBButton: text: " C ", skin: "SpecialButton"
- TBEditField: gravity: all, skin: 0, multiline: 1, readonly: 1, adapt-to-content: 1
- text The skin has a condition to show a upper left positioned overlay "Star" if placed under a ancestor widget with skin "Starry buttons". The Star skin has conditions to change bitmap if the window is active and the parent widget or any child to it is hovered.
diff --git a/data/testturbobadger/demo01/ui_resources/test_skin_conditions02.tb.txt b/data/testturbobadger/demo01/ui_resources/test_skin_conditions02.tb.txt
deleted file mode 100644
index f249ae93f..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_skin_conditions02.tb.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-WindowInfo
- title Skin conditions
- position 500 170
-TBLayout
- axis y
- TBEditField: gravity: all, skin: 0, multiline: 1, readonly: 1, adapt-to-content: 1
- text The TBButton skin has a condition to show a different skin when placed under a parent widget with skin "button_group". There is also conditions to use a different skin for the first and last button.
- TBLayout
- TBLayout: skin: button_group
- TBButton
- text <
- TBButton
- text >
- TBLayout: skin: button_group
- TBButton
- text 1
- TBButton
- text 2
- TBButton
- text 3
- TBLayout: skin: button_group
- TBButton
- text A
- TBButton
- text B
- TBButton
- text C
- TBLayout: skin: button_group
- TBButton
- text Hello
- TBButton
- text World!
- TBEditField: gravity: all, skin: 0, multiline: 1, readonly: 1, adapt-to-content: 1
- text The "button_group" skin overrides default layout spacing. It can also be overridden in the UI resource.
- TBLayout: skin: button_group
- spacing 2
- TBButton
- text Group
- TBButton
- text with
- TBButton
- text spacing
- TBButton
- text 2
diff --git a/data/testturbobadger/demo01/ui_resources/test_tabcontainer01.tb.txt b/data/testturbobadger/demo01/ui_resources/test_tabcontainer01.tb.txt
deleted file mode 100644
index fa7b50a1f..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_tabcontainer01.tb.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-WindowInfo
- title TBTabContainer & misc tests
- position 770 430
-TBTabContainer
- gravity all
- id tabcontainer
- tabs
- TBButton: text: "Tab with long text"
- TBButton: text: "Skin"
- TBButton: text: "Spinner"
- TBSkinImage: skin: Icon16
- TBLayout: axis: y
- TBTextField: text: "Tab alignment:"
- TBLayout
- TBClickLabel: text: Left
- TBRadioButton: group-id: set_align, id: set_align, data: 0
- TBClickLabel: text: Up
- TBRadioButton: group-id: set_align, id: set_align, data: 1, value: 1
- TBClickLabel: text: Right
- TBRadioButton: group-id: set_align, id: set_align, data: 2
- TBClickLabel: text: Bottom
- TBRadioButton: group-id: set_align, id: set_align, data: 3
- TBButton
- text Toggle tab axis
- id toggle_tab_axis
- TBLayout
- TBLayout: axis: y, position: right bottom
- TBButton: text: Normal button
- TBButton: text: Overridden skin, skin: SpecialButton
- TBButton: text: Disabled button, state: disabled
- TBEditField
- text TBEditField
- multiline 1
- TBLayout
- axis y
- TBButton: id: start_spinner, text: Start spinner
- TBButton: id: stop_spinner, text: Stop spinner
- TBProgressSpinner: id: spinner
diff --git a/data/testturbobadger/demo01/ui_resources/test_textwindow.tb.txt b/data/testturbobadger/demo01/ui_resources/test_textwindow.tb.txt
deleted file mode 100644
index 680499f2b..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_textwindow.tb.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-WindowInfo
- title Text editing
- position 280 50
- size 450 630
-TBLayout: axis: y, distribution: available
- TBLayout: distribution: gravity
- TBButton: id: undo
- TBSkinImage: skin: arrow.left
- TBButton: id: redo
- TBSkinImage: skin: arrow.right
- TBButton: text: Clear, id: clear
- TBLayout
- gravity left right
- distribution-position right bottom
- TBTextField: id: info
- TBButton: id: menu
- TBSkinImage: skin: arrow.down
- TBTextField: text: Menu
- skin TBButton.flat
- TBEditField: multiline: 1, styling: 1, gravity: all, id: editfield, autofocus: 1
- text: "Turbo Badger - Fast UI toolkit\n\n" \
- "Test zone\n" \
- "The menu to the left spawns some examples of features in turbo badger.\n\n" \
- "The code in Demo/* is more like a developers test zone than organized tutorial-like samples. " \
- "This would be good to fix of course (help is welcome! ;)\n\n" \
- "Some things to try out\n" \
- " • All layouts provide panning of content automatically when squashed below the minimal size, so try resizing windows and pan.\n" \
- " • Lines starting with a bullet sequence (like this one) should wrap in a smart way.\n" \
- " • Message windows whose target is removed, are automatically removed. Close the menu window with open messages.\n" \
- " • Keyboard navigation using tab.\n" \
- " • Underline, Red, Green, Blue\n\n" \
- "Good to know\n" \
- " • The text widget handles styling and embedded content (Example: ), but does not handle editing of those fully. Those features are only ment for read-only text widgets for now.\n" \
- " • You can emulate touch input by holding down shift, ctrl or alt. Touch input behaves differently in some widgets (f.ex long click to open context menu in textfields), and only invoke movement when down.\n" \
- " • All resources are UTF-8.\n"
diff --git a/data/testturbobadger/demo01/ui_resources/test_toggle_containers.tb.txt b/data/testturbobadger/demo01/ui_resources/test_toggle_containers.tb.txt
deleted file mode 100644
index 7bd1f05cb..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_toggle_containers.tb.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-WindowInfo
- title TBToggleContainer
-TBLayout: axis: y
- TBEditField: gravity: all, adapt-to-content: 1, multiline: 1, readonly: 1, skin: 0, virtual-width: 400
- text: "TBToggleContainer used with TBWidgetValue connections to automatically toggle a group of items (no programming needed)."
-
- TBLayout: position: top left
- TBContainer
- TBLayout: axis: y
- TBClickLabel: text: "Check to enable stuff:"
- TBCheckBox: connection: toggle_demo_1
-
- # == Toggle enabled =====================================================
- TBToggleContainer: connection: toggle_demo_1, toggle: enabled
- TBLayout: axis: y
- TBClickLabel: text: "Option 1"
- TBRadioButton: group-id: group1, value: 1
- TBClickLabel: text: "Option 2"
- TBRadioButton: group-id: group1
-
- TBClickLabel: text: "Check to disable stuff:"
- TBCheckBox: connection: toggle_demo_2
-
- # == Toggle enabled, with the invert flag set ===========================
- TBToggleContainer: connection: toggle_demo_2, toggle: enabled, invert: 1
- TBLayout: axis: y
- TBClickLabel: text: "Option 1"
- TBRadioButton: group-id: group2, value: 1
- TBClickLabel: text: "Option 2"
- TBRadioButton: group-id: group2
-
- TBContainer
- TBLayout: axis: y
- TBClickLabel: text: "Check to show stuff:"
- TBCheckBox: connection: toggle_demo_3
-
- # == Toggle opacity =====================================================
- TBToggleContainer: connection: toggle_demo_3, toggle: opacity
- TBLayout: axis: y
- TBClickLabel: text: "Option 1"
- TBRadioButton: group-id: group3, value: 1
- TBClickLabel: text: "Option 2"
- TBRadioButton: group-id: group3
-
- TBClickLabel: text: "Check to expand stuff:"
- TBCheckBox: connection: toggle_demo_4
-
- # == Toggle expand ======================================================
- TBToggleContainer: connection: toggle_demo_4, toggle: expanded
- TBLayout: axis: y
- TBClickLabel: text: "Option 1"
- TBRadioButton: group-id: group4, value: 1
- TBClickLabel: text: "Option 2"
- TBRadioButton: group-id: group4
diff --git a/data/testturbobadger/demo01/ui_resources/test_ui.tb.txt b/data/testturbobadger/demo01/ui_resources/test_ui.tb.txt
deleted file mode 100644
index 944012b4d..000000000
--- a/data/testturbobadger/demo01/ui_resources/test_ui.tb.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-WindowInfo
- title Turbo Badger
- position 10 50
- size 250 630
-
-TBLayout: axis: y, distribution-position: "left top", distribution: "available"
-
- TBSection: value: 1, text: "Misc features"
- TBLayout: axis: y, spacing: 0, size: available
- TBButton: skin: "TBButton.flat", text: "Radiobutton & Checkbox"
- id: "test-layout"
- data: "test_radio_checkbox.tb.txt"
- TBButton: skin: "TBButton.flat", text: "TBSelectList", id: "test-list"
- TBButton: skin: "TBButton.flat", text: "ScrollContainer & misc.", id: "test-scroll-container"
- TBButton: skin: "TBButton.flat", text: "TBWidgetValue connections", id: "test-connections"
- TBButton: skin: "TBButton.flat", text: "TBImage", id: "test-image"
- TBButton: skin: "TBButton.flat", text: "TBScrollerSnapListener", id: "test-page"
- TBButton: skin: "TBButton.flat", text: "Animations", id: "test-animations"
- TBButton: skin: "TBButton.flat", text: "Skin conditions", id: "test-skin-conditions"
- TBButton: skin: "TBButton.flat", text: "TBToggleContainer"
- id: "test-layout"
- data: "test_toggle_containers.tb.txt"
- TBButton: skin: "TBButton.flat", text: "Close with dim & alert", id: "TBWindow.close"
- TBButton: skin: "TBButton.flat", text: "ResourceEditWindow", id: "test-resource-edit"
-
- TBSection: value: 0, text: "Layout tests"
- TBLayout: axis: y, spacing: 0, size: available
- TBButton: skin: "TBButton.flat", text: "Size, gravity, position"
- id: "test-layout"
- data: "test_layout01.tb.txt"
- TBButton: skin: "TBButton.flat", text: "Distribution"
- id: "test-layout"
- data: "test_layout02.tb.txt"
- TBButton: skin: "TBButton.flat", text: "TBWidget default"
- id: "test-layout"
- data: "test_layout03.tb.txt"
-
- TBSection: value: 0, text: "Graphics tests"
- TBLayout: axis: y, spacing: 0, size: available
- TBClickLabel: text: "Continous repaint"
- lp: max-width: 0
- TBCheckBox: connection: continous-repaint
- TBButton: skin: "TBButton.flat", text: "Reload skin bitmaps", id: "reload skin bitmaps"
- TBButton: skin: "TBButton.flat", text: "Context lost & restore", id: "test context lost"
-
- TBSection: value: 0, text: "Message tests"
- TBLayout: axis: y, spacing: 0, size: available
- TBButton: skin: "TBButton.flat", text: "PostMessage", id: "msg"
- TBButton: skin: "TBButton.flat", text: "PostMessageDelayed", id: "delayedmsg"
- TBClickLabel: text: "Busy message loop"
- lp: max-width: 0
- TBCheckBox: id: "busymsg"
-
- # We want the debug button at the bottom if there is space over,
- # so use an trailing layout which may expand a lot.
- TBLayout: axis: y, distribution-position: bottom
- lp: max-height: 10000
- TBButton: id: "debug settings", text: "Runtime debug settings..."
diff --git a/data/voxedit-ui/ui/lang/en.tb.txt b/data/voxedit-ui/ui/lang/en.tb.txt
deleted file mode 100644
index 0bf40fa50..000000000
--- a/data/voxedit-ui/ui/lang/en.tb.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-cut Cut
-copy Copy
-paste Paste
-delete Delete
-selectall Select all
-TBMessageWindow.ok Ok
-TBMessageWindow.cancel Cancel
-TBMessageWindow.yes Yes
-TBMessageWindow.no No
-TBList.header Showing %d of %d
-ok Ok
-cancel Cancel
-error Error
diff --git a/data/voxedit-ui/ui/skin/voxedit-add.png b/data/voxedit-ui/ui/skin/voxedit-add.png
deleted file mode 100644
index bceea08db..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-add.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-add@288.png b/data/voxedit-ui/ui/skin/voxedit-add@288.png
deleted file mode 100644
index a0cb22e71..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-add@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-anim-play-selected.png b/data/voxedit-ui/ui/skin/voxedit-anim-play-selected.png
deleted file mode 100644
index d222c7ff9..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-anim-play-selected.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-anim-play-selected@288.png b/data/voxedit-ui/ui/skin/voxedit-anim-play-selected@288.png
deleted file mode 100644
index a41d3ab70..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-anim-play-selected@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-anim-play.png b/data/voxedit-ui/ui/skin/voxedit-anim-play.png
deleted file mode 100644
index 51c20a98a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-anim-play.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-anim-play@288.png b/data/voxedit-ui/ui/skin/voxedit-anim-play@288.png
deleted file mode 100644
index 70fc96361..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-anim-play@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-animation-selected.png b/data/voxedit-ui/ui/skin/voxedit-animation-selected.png
deleted file mode 100644
index 99da90847..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-animation-selected.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-animation-selected@288.png b/data/voxedit-ui/ui/skin/voxedit-animation-selected@288.png
deleted file mode 100644
index a8ce3ec95..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-animation-selected@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-animation.png b/data/voxedit-ui/ui/skin/voxedit-animation.png
deleted file mode 100644
index 7faa5349f..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-animation.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-animation@288.png b/data/voxedit-ui/ui/skin/voxedit-animation@288.png
deleted file mode 100644
index e07509b4e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-animation@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-axis-x.png b/data/voxedit-ui/ui/skin/voxedit-axis-x.png
deleted file mode 100644
index 86eb0446c..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-axis-x.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-axis-x@288.png b/data/voxedit-ui/ui/skin/voxedit-axis-x@288.png
deleted file mode 100644
index de8cc77ff..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-axis-x@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-axis-y.png b/data/voxedit-ui/ui/skin/voxedit-axis-y.png
deleted file mode 100644
index 9fde72f9f..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-axis-y.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-axis-y@288.png b/data/voxedit-ui/ui/skin/voxedit-axis-y@288.png
deleted file mode 100644
index 9dc622dc5..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-axis-y@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-axis-z.png b/data/voxedit-ui/ui/skin/voxedit-axis-z.png
deleted file mode 100644
index eaff6ef84..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-axis-z.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-axis-z@288.png b/data/voxedit-ui/ui/skin/voxedit-axis-z@288.png
deleted file mode 100644
index 3e56542b4..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-axis-z@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-color-picker.png b/data/voxedit-ui/ui/skin/voxedit-color-picker.png
deleted file mode 100644
index ca2f656cf..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-color-picker.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-color-picker@288.png b/data/voxedit-ui/ui/skin/voxedit-color-picker@288.png
deleted file mode 100644
index 662270a80..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-color-picker@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-color.png b/data/voxedit-ui/ui/skin/voxedit-color.png
deleted file mode 100644
index 0c8166618..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-color.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-color@288.png b/data/voxedit-ui/ui/skin/voxedit-color@288.png
deleted file mode 100644
index 25138ad48..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-color@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-colors.png b/data/voxedit-ui/ui/skin/voxedit-colors.png
deleted file mode 100644
index 40fc13a97..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-colors.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-colors@288.png b/data/voxedit-ui/ui/skin/voxedit-colors@288.png
deleted file mode 100644
index 966f60fe1..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-colors@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-crop.png b/data/voxedit-ui/ui/skin/voxedit-crop.png
deleted file mode 100644
index a1a50d138..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-crop.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-crop@288.png b/data/voxedit-ui/ui/skin/voxedit-crop@288.png
deleted file mode 100644
index 492b04af9..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-crop@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-delete.png b/data/voxedit-ui/ui/skin/voxedit-delete.png
deleted file mode 100644
index a8170625e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-delete.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-delete@288.png b/data/voxedit-ui/ui/skin/voxedit-delete@288.png
deleted file mode 100644
index 2cda07d62..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-delete@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-export.png b/data/voxedit-ui/ui/skin/voxedit-export.png
deleted file mode 100644
index 3b5f85505..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-export.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-export@288.png b/data/voxedit-ui/ui/skin/voxedit-export@288.png
deleted file mode 100644
index 3a2289e73..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-export@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-extend.png b/data/voxedit-ui/ui/skin/voxedit-extend.png
deleted file mode 100644
index ac1141790..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-extend.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-extend@288.png b/data/voxedit-ui/ui/skin/voxedit-extend@288.png
deleted file mode 100644
index 7f6e6129e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-extend@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-flip-horizontal.png b/data/voxedit-ui/ui/skin/voxedit-flip-horizontal.png
deleted file mode 100644
index 1c815dd39..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-flip-horizontal.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-flip-horizontal@288.png b/data/voxedit-ui/ui/skin/voxedit-flip-horizontal@288.png
deleted file mode 100644
index dd3ca5719..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-flip-horizontal@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-flip-vertical.png b/data/voxedit-ui/ui/skin/voxedit-flip-vertical.png
deleted file mode 100644
index bc3907d92..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-flip-vertical.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-flip-vertical@288.png b/data/voxedit-ui/ui/skin/voxedit-flip-vertical@288.png
deleted file mode 100644
index c1ff6e698..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-flip-vertical@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-import-palette.png b/data/voxedit-ui/ui/skin/voxedit-import-palette.png
deleted file mode 100644
index cfa391970..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-import-palette.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-import-palette@288.png b/data/voxedit-ui/ui/skin/voxedit-import-palette@288.png
deleted file mode 100644
index 9f0b320de..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-import-palette@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-load.png b/data/voxedit-ui/ui/skin/voxedit-load.png
deleted file mode 100644
index 3a6064ecb..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-load.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-load@288.png b/data/voxedit-ui/ui/skin/voxedit-load@288.png
deleted file mode 100644
index 0ff62389e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-load@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-lock-layer-selected.png b/data/voxedit-ui/ui/skin/voxedit-lock-layer-selected.png
deleted file mode 100644
index d661e2a43..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-lock-layer-selected.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-lock-layer-selected@288.png b/data/voxedit-ui/ui/skin/voxedit-lock-layer-selected@288.png
deleted file mode 100644
index a9bc50258..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-lock-layer-selected@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-lock-layer.png b/data/voxedit-ui/ui/skin/voxedit-lock-layer.png
deleted file mode 100644
index af9c0ed51..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-lock-layer.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-lock-layer@288.png b/data/voxedit-ui/ui/skin/voxedit-lock-layer@288.png
deleted file mode 100644
index e4a13702f..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-lock-layer@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-move.png b/data/voxedit-ui/ui/skin/voxedit-move.png
deleted file mode 100644
index 83f485970..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-move.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-move@288.png b/data/voxedit-ui/ui/skin/voxedit-move@288.png
deleted file mode 100644
index 811572c6e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-move@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-new.png b/data/voxedit-ui/ui/skin/voxedit-new.png
deleted file mode 100644
index 45eafb50a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-new.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-new@288.png b/data/voxedit-ui/ui/skin/voxedit-new@288.png
deleted file mode 100644
index 69090ffb4..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-new@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-options.png b/data/voxedit-ui/ui/skin/voxedit-options.png
deleted file mode 100644
index 169b97695..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-options.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-options@288.png b/data/voxedit-ui/ui/skin/voxedit-options@288.png
deleted file mode 100644
index 0e266e3b4..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-options@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-override.png b/data/voxedit-ui/ui/skin/voxedit-override.png
deleted file mode 100644
index d3f2bb62e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-override.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-override@288.png b/data/voxedit-ui/ui/skin/voxedit-override@288.png
deleted file mode 100644
index 0d9457ed8..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-override@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-quadview-selected.png b/data/voxedit-ui/ui/skin/voxedit-quadview-selected.png
deleted file mode 100644
index 7d335b973..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-quadview-selected.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-quadview-selected@288.png b/data/voxedit-ui/ui/skin/voxedit-quadview-selected@288.png
deleted file mode 100644
index 4abb2c158..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-quadview-selected@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-quadview.png b/data/voxedit-ui/ui/skin/voxedit-quadview.png
deleted file mode 100644
index 60128d119..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-quadview.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-quadview@288.png b/data/voxedit-ui/ui/skin/voxedit-quadview@288.png
deleted file mode 100644
index d69b977ff..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-quadview@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-quit.png b/data/voxedit-ui/ui/skin/voxedit-quit.png
deleted file mode 100644
index 0ed80bb40..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-quit.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-quit@288.png b/data/voxedit-ui/ui/skin/voxedit-quit@288.png
deleted file mode 100644
index 9a2b60ed4..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-quit@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-reset-camera.png b/data/voxedit-ui/ui/skin/voxedit-reset-camera.png
deleted file mode 100644
index 5e2caf68a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-reset-camera.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-reset-camera@288.png b/data/voxedit-ui/ui/skin/voxedit-reset-camera@288.png
deleted file mode 100644
index a2326a933..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-reset-camera@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-rotate.png b/data/voxedit-ui/ui/skin/voxedit-rotate.png
deleted file mode 100644
index 3f4581bdc..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-rotate.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-rotate@288.png b/data/voxedit-ui/ui/skin/voxedit-rotate@288.png
deleted file mode 100644
index 893c82aba..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-rotate@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-save.png b/data/voxedit-ui/ui/skin/voxedit-save.png
deleted file mode 100644
index e6fe9a211..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-save.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-save@288.png b/data/voxedit-ui/ui/skin/voxedit-save@288.png
deleted file mode 100644
index 8e79be49d..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-save@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-settings.png b/data/voxedit-ui/ui/skin/voxedit-settings.png
deleted file mode 100644
index 23e0a7858..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-settings.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-settings@288.png b/data/voxedit-ui/ui/skin/voxedit-settings@288.png
deleted file mode 100644
index 00a8e33e2..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-settings@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-shift.png b/data/voxedit-ui/ui/skin/voxedit-shift.png
deleted file mode 100644
index 1d930c7e5..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-shift.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-shift@288.png b/data/voxedit-ui/ui/skin/voxedit-shift@288.png
deleted file mode 100644
index 60806ae87..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-shift@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-show-grid-selected.png b/data/voxedit-ui/ui/skin/voxedit-show-grid-selected.png
deleted file mode 100644
index 8ee008c2e..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-show-grid-selected.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-show-grid-selected@288.png b/data/voxedit-ui/ui/skin/voxedit-show-grid-selected@288.png
deleted file mode 100644
index 2049de734..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-show-grid-selected@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-show-grid.png b/data/voxedit-ui/ui/skin/voxedit-show-grid.png
deleted file mode 100644
index e40ca413f..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-show-grid.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-show-grid@288.png b/data/voxedit-ui/ui/skin/voxedit-show-grid@288.png
deleted file mode 100644
index df5d626c9..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-show-grid@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-skin.tb.txt b/data/voxedit-ui/ui/skin/voxedit-skin.tb.txt
deleted file mode 100644
index be5d5935e..000000000
--- a/data/voxedit-ui/ui/skin/voxedit-skin.tb.txt
+++ /dev/null
@@ -1,173 +0,0 @@
-elements
- voxedit-color
- bitmap voxedit-color.png
- voxedit-delete
- bitmap voxedit-delete.png
- voxedit-flip-horizontal
- bitmap voxedit-flip-horizontal.png
- voxedit-flip-vertical
- bitmap voxedit-flip-vertical.png
- voxedit-load
- bitmap voxedit-load.png
- voxedit-import-palette
- bitmap voxedit-import-palette.png
- voxedit-down
- bitmap voxedit-up.png
- flip-y 1
- voxedit-colors
- bitmap voxedit-colors.png
- voxedit-add
- bitmap voxedit-add.png
- voxedit-up
- bitmap voxedit-up.png
- voxedit-new
- bitmap voxedit-new.png
- voxedit-options
- bitmap voxedit-options.png
- voxedit-quit
- bitmap voxedit-quit.png
- voxedit-move
- bitmap voxedit-move.png
- voxedit-shift
- bitmap voxedit-shift.png
- voxedit-redo
- bitmap voxedit-undo-redo.png
- voxedit-rotate-left
- bitmap voxedit-rotate.png
- voxedit-rotate-right
- bitmap voxedit-rotate.png
- flip-x 1
- voxedit-save
- bitmap voxedit-save.png
- voxedit-show-grid
- bitmap voxedit-show-grid.png
- voxedit-undo
- bitmap voxedit-undo-redo.png
- flip-x 1
- voxedit-voxel
- bitmap voxedit-voxel.png
- voxedit-reset-camera
- bitmap voxedit-reset-camera.png
- voxedit-override
- bitmap voxedit-override.png
- voxedit-export
- bitmap voxedit-export.png
- voxedit-axis-x
- bitmap voxedit-axis-x.png
- voxedit-axis-y
- bitmap voxedit-axis-y.png
- voxedit-axis-z
- bitmap voxedit-axis-z.png
- voxedit-tree
- bitmap voxedit-tree.png
- voxedit-structure
- bitmap voxedit-tree.png
- voxedit-extend
- bitmap voxedit-extend.png
- voxedit-crop
- bitmap voxedit-crop.png
- voxedit-tree_pine
- bitmap voxedit-tree_pine.png
-
- voxedit-animation-button
- bitmap voxedit-animation.png
- children
- element voxedit-animation-button.selected
- state selected
- element voxedit-animation-button.pressed
- state pressed
- voxedit-animation-button.selected
- bitmap voxedit-animation-selected.png
- type Image
- voxedit-animation-button.pressed
- bitmap voxedit-animation-selected.png
- type Image
-
- voxedit-quadview-button
- bitmap voxedit-quadview.png
- children
- element voxedit-quadview-button.selected
- state selected
- element voxedit-quadview-button.pressed
- state pressed
- voxedit-quadview-button.selected
- bitmap voxedit-quadview-selected.png
- type Image
- voxedit-quadview-button.pressed
- bitmap voxedit-quadview-selected.png
- type Image
-
- voxedit-anim-button
- bitmap voxedit-anim-play.png
- children
- element voxedit-anim-button.selected
- state selected
- element voxedit-anim-button.pressed
- state pressed
- voxedit-anim-button.selected
- bitmap voxedit-anim-play-selected.png
- type Image
- voxedit-anim-button.pressed
- bitmap voxedit-anim-play-selected.png
- type Image
-
- voxedit-visible-button
- bitmap voxedit-visible.png
- children
- element voxedit-visible-button.selected
- state selected
- element voxedit-visible-button.pressed
- state pressed
- voxedit-visible-button.selected
- bitmap voxedit-visible-selected.png
- type Image
- voxedit-visible-button.pressed
- bitmap voxedit-visible-selected.png
- type Image
-
- voxedit-lock-layer-button
- bitmap voxedit-lock-layer.png
- children
- element voxedit-lock-layer-button.selected
- state selected
- element voxedit-lock-layer-button.pressed
- state pressed
- voxedit-lock-layer-button.selected
- bitmap voxedit-lock-layer-selected.png
- type Image
- voxedit-lock-layer-button.pressed
- bitmap voxedit-lock-layer-selected.png
- type Image
-
- voxedit-grid-button
- bitmap voxedit-show-grid.png
- children
- element voxedit-grid-button.selected
- state selected
- element voxedit-grid-button.pressed
- state pressed
- voxedit-grid-button.selected
- bitmap voxedit-show-grid-selected.png
- type Image
- voxedit-grid-button.pressed
- bitmap voxedit-show-grid-selected.png
- type Image
-
- color-picker
- type StretchBox
- bitmap voxedit-color-picker.png
-
- voxedit-file
- bitmap editfield.png
- cut 12
- expand 4
- padding 4 4 4 24
- min-width 50
- children
- element voxedit-file.icon
-
- voxedit-file.icon
- bitmap voxedit-load.png
- type Image
- img-position-x 0
- img-ofs-x 5
diff --git a/data/voxedit-ui/ui/skin/voxedit-tree.png b/data/voxedit-ui/ui/skin/voxedit-tree.png
deleted file mode 100644
index ae98d1930..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-tree.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-tree@288.png b/data/voxedit-ui/ui/skin/voxedit-tree@288.png
deleted file mode 100644
index c128c9e1a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-tree@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-tree_pine.png b/data/voxedit-ui/ui/skin/voxedit-tree_pine.png
deleted file mode 100644
index ae98d1930..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-tree_pine.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-tree_pine@288.png b/data/voxedit-ui/ui/skin/voxedit-tree_pine@288.png
deleted file mode 100644
index c128c9e1a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-tree_pine@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-undo-redo.png b/data/voxedit-ui/ui/skin/voxedit-undo-redo.png
deleted file mode 100644
index e4ea4bcc7..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-undo-redo.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-undo-redo@288.png b/data/voxedit-ui/ui/skin/voxedit-undo-redo@288.png
deleted file mode 100644
index 6816217eb..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-undo-redo@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-up.png b/data/voxedit-ui/ui/skin/voxedit-up.png
deleted file mode 100644
index b06ca9de9..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-up.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-up@288.png b/data/voxedit-ui/ui/skin/voxedit-up@288.png
deleted file mode 100644
index a92b28713..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-up@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-visible-selected.png b/data/voxedit-ui/ui/skin/voxedit-visible-selected.png
deleted file mode 100644
index 2b2df955a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-visible-selected.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-visible-selected@288.png b/data/voxedit-ui/ui/skin/voxedit-visible-selected@288.png
deleted file mode 100644
index 6e3add499..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-visible-selected@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-visible.png b/data/voxedit-ui/ui/skin/voxedit-visible.png
deleted file mode 100644
index 9d70d6b5d..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-visible.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-visible@288.png b/data/voxedit-ui/ui/skin/voxedit-visible@288.png
deleted file mode 100644
index 36a19ced2..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-visible@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-voxel.png b/data/voxedit-ui/ui/skin/voxedit-voxel.png
deleted file mode 100644
index f33bc824a..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-voxel.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/skin/voxedit-voxel@288.png b/data/voxedit-ui/ui/skin/voxedit-voxel@288.png
deleted file mode 100644
index 919dc5fb4..000000000
Binary files a/data/voxedit-ui/ui/skin/voxedit-voxel@288.png and /dev/null differ
diff --git a/data/voxedit-ui/ui/widget/voxedit-layer-item.tb.txt b/data/voxedit-ui/ui/widget/voxedit-layer-item.tb.txt
deleted file mode 100644
index f7caa30fd..000000000
--- a/data/voxedit-ui/ui/widget/voxedit-layer-item.tb.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-TBCheckBox: id: visible, skin: voxedit-visible-button
-TBCheckBox: id: locked, skin: voxedit-lock-layer-button
-TBLayout: axis: y, position: left, spacing: 0, ignore-input: 1, size: available, position: left top
- TBTextField: id: name, text-align: left
-TBButton: id: delete, skin: TBWindow.close
diff --git a/data/voxedit-ui/ui/widget/voxedit-layer.tb.txt b/data/voxedit-ui/ui/widget/voxedit-layer.tb.txt
deleted file mode 100644
index d34ddd528..000000000
--- a/data/voxedit-ui/ui/widget/voxedit-layer.tb.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-TBLayout
- lp: width: 200
- axis y
- distribution gravity
- gravity all
- TBLayout
- distribution gravity
- TBSelectList
- id list
- gravity all
- TBLayout
- distribution gravity
- TBCheckBox
- id anim
- skin voxedit-anim-button
- command animate
- TBButton
- command layermovedown
- skin voxedit-down
- TBButton
- command layermoveup
- skin voxedit-up
- TBWidget
- gravity left right
- TBButton
- id layeradd
- skin voxedit-add
diff --git a/data/voxedit-ui/ui/window/voxedit-layer-move.tb.txt b/data/voxedit-ui/ui/window/voxedit-layer-move.tb.txt
deleted file mode 100644
index 02384e318..000000000
--- a/data/voxedit-ui/ui/window/voxedit-layer-move.tb.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-TBLayout: distribution: available, size: available, axis: y
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-x
- TBInlineSelect: id: move.x
- lp: width: 120
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-y
- TBInlineSelect: id: move.y
- lp: width: 120
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-z
- TBInlineSelect: id: move.z
- lp: width: 120
- TBLayout: distribution-position: right bottom, id: buttons
diff --git a/data/voxedit-ui/ui/window/voxedit-layer-rename.tb.txt b/data/voxedit-ui/ui/window/voxedit-layer-rename.tb.txt
deleted file mode 100644
index 65eb245c0..000000000
--- a/data/voxedit-ui/ui/window/voxedit-layer-rename.tb.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-TBLayout: axis: y, distribution: available, size: available
- TBClickLabel: text: Name
- TBEditField: id: name
- lp: width: 100
- TBLayout: distribution-position: right bottom, id: buttons
diff --git a/data/voxedit-ui/ui/window/voxedit-layer.tb.txt b/data/voxedit-ui/ui/window/voxedit-layer.tb.txt
deleted file mode 100644
index 66f487027..000000000
--- a/data/voxedit-ui/ui/window/voxedit-layer.tb.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-TBLayout: axis: y, distribution: available, size: available
- TBClickLabel: text: Position
- TBLayout: axis: x
- TBEditField: type: number, id: pos.x
- lp: width: 60
- TBEditField: type: number, id: pos.y
- lp: width: 60
- TBEditField: type: number, id: pos.z
- lp: width: 60
- TBClickLabel: text: Size
- TBLayout: axis: x
- TBEditField: type: number, id: size.x
- lp: width: 60
- TBEditField: type: number, id: size.y
- lp: width: 60
- TBEditField: type: number, id: size.z
- lp: width: 60
- TBSeparator
- TBClickLabel: text: Name
- TBEditField: id: name
- lp: width: 100
- TBEditField: id: note, size: available, readonly: 1, multiline: 1, multiline: 1, wrapping: 1
- TBLayout: distribution-position: right bottom, id: buttons
diff --git a/data/voxedit-ui/ui/window/voxedit-main.tb.txt b/data/voxedit-ui/ui/window/voxedit-main.tb.txt
deleted file mode 100644
index ee3d66e73..000000000
--- a/data/voxedit-ui/ui/window/voxedit-main.tb.txt
+++ /dev/null
@@ -1,378 +0,0 @@
-WindowInfo
- fullscreen 1
-
-definitions
- menubutton
- lp: height: 28
- skin TBButton.flat
- menutextfield
- lp: height: 28
- gravity left right
- text-align right
- type number
- toolbutton
- group-id toolgroup
- cursorbutton
- group-id cursorgroup
- selectbutton
- group-id selectgroup
-
-shaderselection
- TBSelectDropdown: gravity: right top, @include: definitions>menubutton, id: shader
- items
- item: text: "Normal", id: 0
- item: text: "Edge", id: 1
-
-cameramode
- TBSelectDropdown: gravity: right bottom, @include: definitions>menubutton, id: cammode
- items
- item: text: "Solid", id: 0
- item: text: "Points", id: 1
- item: text: "Lines", id: 2
-
-camerarottype
- TBSelectDropdown: gravity: left bottom, @include: definitions>menubutton, id: camrottype
- items
- item: text: "Reference Point", id: 0
- item: text: "Eye", id: 1
-
-TBLayout: distribution: gravity, axis: y
- TBContainer: gravity: all, id: maincontainer
- TBLayout: distribution: gravity, axis: y
- TBLayout: distribution: gravity
- TBContainer: skin: container, gravity: left right
- TBLayout: distribution: gravity
- TBButton: gravity: left, @include: definitions>menubutton, text: File, id: menu_file
- TBSkinImage: skin: voxedit-load
- TBButton: gravity: left, @include: definitions>menubutton, text: Undo, id: undo, command: undo
- TBSkinImage: skin: voxedit-undo
- TBButton: gravity: left, @include: definitions>menubutton, text: Redo, id: redo, command: redo
- TBSkinImage: skin: voxedit-redo
- TBButton: gravity: left, @include: definitions>menubutton, text: Settings, id: scene_settings_open
- TBSkinImage: skin: voxedit-options
- TBButton: gravity: left, @include: definitions>menubutton, text: Trees, id: show_tree_panel
- TBSkinImage: skin: voxedit-tree
- TBButton: gravity: left, @include: definitions>menubutton, text: Scripts, id: show_script_panel
- TBSkinImage: skin: voxedit-script
- TBButton: gravity: left, @include: definitions>menubutton, text: Noise, id: show_noise_panel
- TBButton: gravity: left, @include: definitions>menubutton, text: L-System, id: show_lsystem_panel
-
- TBLayout: gravity: left right
- TBWidget
- TBLayout: distribution: gravity, position: top
- TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom, skin: no-padding-container
- TBSection: value: 1, text: "Palette"
- TBLayout: position: left top, axis: y
- lp: padding: 0
- PaletteWidget: id: palettecontainer, width: 18, height: 18, amount-x: 14, connection: current-voxel-color
- TBLayout: position: right top, axis: x
- lp: padding: 0
- TBButton: @include: definitions>menubutton, text: Import, command: "importpalette"
- TBSkinImage: skin: voxedit-import-palette
- TBButton: @include: definitions>menubutton, text: Load, id: loadpalette
- TBSkinImage: skin: voxedit-load
- TBLayout: position: right top, axis: x
- lp: padding: 0
- TBButton: @include: definitions>menubutton, text: "Extract color", command: colortolayer
- TBEditField: id: paletteindex, placeholder: index, gravity: left: right, text-align: left, readonly: 1
- lp: height: 28
-
- TBSection: value: 1, text: "Tools", is-group-root: 1
- TBLayout: position: left top, axis: y
- TBClickLabel
- text Place
- TBSkinImage: skin: voxedit-voxel
- TBRadioButton
- id actionplace
- value 1
- @include definitions>toolbutton
- TBClickLabel
- text Select
- TBSkinImage: skin: voxedit-voxel
- TBRadioButton
- id actionselect
- @include definitions>toolbutton
- TBClickLabel
- text Delete
- TBSkinImage: skin: voxedit-delete
- TBRadioButton
- id actiondelete
- @include definitions>toolbutton
- TBClickLabel
- text Override
- TBSkinImage: skin: voxedit-override
- TBRadioButton
- id actionoverride
- @include definitions>toolbutton
- TBClickLabel
- text Colorize
- TBSkinImage: skin: voxedit-color
- TBRadioButton
- id actioncolorize
- @include definitions>toolbutton
- TBSelectDropdown: gravity: right top, @include: definitions>menubutton, id: shapetype
- items
- item: text: "Cube", id: 0
- item: text: "Torus", id: 1
- item: text: "Cylinder", id: 2
- item: text: "Cone", id: 3
- item: text: "Dome", id: 4
- item: text: "Ellipse", id: 5
-
- TBSeparator: gravity: left right, skin: separator
-
- TBWidget: gravity: top bottom
-
- TBLayout: distribution: gravity, axis: y
- TBLayout: distribution: gravity, id: editorcontainer
- TBLayout: distribution: gravity, axis: y
- TBLayout: distribution: gravity, axis: x
- Viewport: id: editorscene, gravity: left right top bottom, skin: no-padding-container, camera: free, want-focus-on-hover: 1
- @include cameramode
- @include camerarottype
- @include shaderselection
- Viewport: id: editorscenetop, gravity: left right top bottom, skin: no-padding-container, camera: top, visibility: gone, want-focus-on-hover: 1
- @include cameramode
- @include camerarottype
- @include shaderselection
- TBLayout: distribution: gravity, skin: no-padding-container, id: animationwidget, gravity: left right top bottom, visibility: gone, axis: y
- TBSelectDropdown: text: Animations, gravity: right top, skin: no-padding-container, @include: definitions>menubutton, id: animationlist
- Viewport: id: animationscene, gravity: left right top bottom, skin: no-padding-container, camera: free, mode: animation, want-focus-on-hover: 1
- @include cameramode
- @include camerarottype
- TBLayout: distribution: gravity, skin: no-padding-container, id: animationsettings, gravity: left right top bottom, axis: y
- lp: height: 400
- TBLayout: distribution: gravity, axis: x
- Viewport: id: editorsceneleft, gravity: left right top bottom, skin: no-padding-container, camera: left, visibility: gone, want-focus-on-hover: 1
- @include cameramode
- @include camerarottype
- @include shaderselection
- Viewport: id: editorscenefront, gravity: left right top bottom, skin: no-padding-container, camera: front, visibility: gone, want-focus-on-hover: 1
- @include cameramode
- @include camerarottype
- @include shaderselection
-
- TBLayout: distribution: gravity, axis: y, position: right, gravity: top bottom, skin: no-padding-container, id: treesection, visibility: gone
- TBTextField: gravity: left right, skin: Header, text: Trees
- TBLayout: position: left top, axis: y, distribution: gravity
- TBSelectDropdown: gravity: left right, id: treetype
-
- TBLayout: position: left top, axis: y, id: treeparameterlayout, distribution: gravity
-
- TBClickLabel: text: Auto generate
- TBCheckBox: id: treeautogen, value: 0
-
- TBButton: text: Generate, id: treegenerate, gravity: left right
-
- TBWidget: gravity: top bottom
-
- TBLayout: distribution: gravity, axis: y, position: right, gravity: top bottom, skin: no-padding-container, id: scriptsection, visibility: gone
- TBTextField: gravity: left right, skin: Header, text: Scripts
- TBLayout: position: left top, axis: y, distribution: gravity
- TBSelectDropdown: gravity: left right, id: scripttype
-
- TBLayout: position: left top, axis: y, id: scriptparameterslayout, distribution: gravity
-
- TBButton: text: Execute, id: scriptexecute, gravity: left right
-
- TBWidget: gravity: top bottom
-
- TBLayout: distribution: gravity, axis: y, position: right, gravity: top bottom, skin: no-padding-container, id: lsystemsection, visibility: gone
- lp: min-width: 350
-
- TBTextField: gravity: left right, skin: Header, text: L-System
- TBLayout: position: left top, axis: y, distribution: gravity
- TBEditField: multiline: 1, styling: 1, gravity: all, readonly: 1, skin: TBTextField
- text: "F: Draw line forwards with current step width\n" \
- "b: Move backward without drawing\n" \
- "L: Draw leaves\n" \
- "+: Rotate right\n" \
- "-: Rotate left\n" \
- ">: Rotate forward\n" \
- "<: Rotate backward\n" \
- "#: Increment width\n" \
- "[: Push\n" \
- "]: Pop\n" \
- "(colorindex): Set voxel type to palette index\n" \
- "\n"
-
- TBTextField: text: Axiom, gravity: left right
- TBEditField: id: lsystem_axiom, placeholder: Axiom, text: "F", gravity: left right
-
- TBTextField: text: Rules, gravity: left right
- TBEditField: multiline: 1, id: lsystem_rules, gravity: all
- text: "{\n" \
- " F\n" \
- " (67)F+[!+F-F-F(37)L]-[!-F+F+F(142)L]>[!FF>F(123)L]\n" \
- "}\n"
-
- TBLayout: position: left top, axis: x, distribution: gravity
- TBTextField: text: Angle, gravity: left right
- TBInlineSelectDouble: id: lsystem_angle, value: 22.5, position: right
-
- TBLayout: position: left top, axis: x, distribution: gravity
- TBTextField: text: Length, gravity: left right
- TBInlineSelectDouble: id: lsystem_length, value: 12.0, position: right
-
- TBLayout: position: left top, axis: x, distribution: gravity
- TBTextField: text: Width, gravity: left right
- TBInlineSelectDouble: id: lsystem_width, value: 4.0, position: right
-
- TBLayout: position: left top, axis: x, distribution: gravity
- TBTextField: text: WidthIncrement, gravity: left right
- TBInlineSelectDouble: id: lsystem_widthincrement, value: 1.5, position: right
-
- TBLayout: position: left top, axis: x, distribution: gravity
- TBTextField: text: Leaves radius, gravity: left right
- TBInlineSelectDouble: id: lsystem_leavesradius, value: 8.0, position: right
-
- TBLayout: position: left top, axis: x, distribution: gravity
- TBTextField: text: Iterations, gravity: left right
- TBInlineSelect: id: lsystem_iterations, value: 2, position: right
-
- TBButton: text: Generate, id: lsystemgenerate, gravity: left right
-
- TBLayout: distribution: gravity, axis: y, position: right, gravity: top bottom, skin: no-padding-container, id: noisesection, visibility: gone
- TBTextField: gravity: left right, skin: Header, text: Noise
- TBLayout: position: left top, axis: y, distribution: gravity
- TBTextField: text: Octaves, gravity: left right
- TBInlineSelect: id: noise_octaves, value: 4, gravity: left right
-
- TBTextField: text: Frequency, gravity: left right
- TBInlineSelectDouble: id: noise_frequency, value: 0.01, gravity: left right
-
- TBTextField: text: Offset, gravity: left right
- TBInlineSelectDouble: id: noise_offset, value: 1.0, gravity: left right
-
- TBTextField: text: Gain, gravity: left right
- TBInlineSelectDouble: id: noise_gain, value: 0.5, gravity: left right
-
- TBTextField: text: Lacunarity, gravity: left right
- TBInlineSelectDouble: id: noise_lacunarity, value: 2.0, gravity: left right
-
- TBButton: text: Generate, id: noisegenerate, gravity: left right
-
- TBWidget: gravity: top bottom
-
- TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom, skin: no-padding-container
-
- TBSection: value: 1, text: "Operations"
- TBLayout: position: left top, axis: y
- TBButton: @include: definitions>menubutton, text: Crop, id: crop, command: "crop"
- TBSkinImage: skin: voxedit-crop
- TBButton: @include: definitions>menubutton, text: Extend, id: extend, command: "resize", auto-repeat: 1
- TBSkinImage: skin: voxedit-extend
- TBButton: @include: definitions>menubutton, text: Layer from color, id: colortolayer, command: "colortolayer"
- TBButton: @include: definitions>menubutton, text: Scale, id: scale, command: "scale"
-
- TBSection: value: 1, text: "Translate"
- TBLayout: position: left top, axis: y, distribution: gravity
- TBInlineSelect: id: translatex, min: -128, max: 128, value: 0, gravity: left right
- TBInlineSelect: id: translatey, min: -128, max: 128, value: 0, gravity: left right
- TBInlineSelect: id: translatez, min: -128, max: 128, value: 0, gravity: left right
- TBLayout: position: left top, axis: x
- TBButton: @include: definitions>menubutton, text: Volumes, id: shiftvolumes
- TBSkinImage: skin: voxedit-shift
- TBButton: @include: definitions>menubutton, text: Voxels, id: movevoxels
- TBSkinImage: skin: voxedit-move
-
- TBSection: value: 1, text: "Cursor"
- TBLayout: position: left top, axis: y, distribution: gravity
- TBLayout: axis: x
- TBEditField: @include: definitions>menutextfield, id: cursorx, placeholder: x
- TBClickLabel
- TBSkinImage: skin: voxedit-axis-x
- TBCheckBox: command: lockx
- TBLayout: axis: x
- TBEditField: @include: definitions>menutextfield, id: cursory, placeholder: y
- TBClickLabel
- TBSkinImage: skin: voxedit-axis-y
- TBCheckBox: command: locky
- TBLayout: axis: x
- TBEditField: @include: definitions>menutextfield, id: cursorz, placeholder: z
- TBClickLabel
- TBSkinImage: skin: voxedit-axis-z
- TBCheckBox: command: lockz
-
- TBSection: value: 1, text: "Rotate on axis"
- TBLayout: position: left top, axis: x
- TBButton: id: rotatex, @include: definitions>menubutton, command: "rotate 90 0 0"
- TBSkinImage: skin: voxedit-axis-x
- TBButton: id: rotatey, @include: definitions>menubutton, command: "rotate 0 90 0"
- TBSkinImage: skin: voxedit-axis-y
- TBButton: id: rotatez, @include: definitions>menubutton, command: "rotate 0 0 90"
- TBSkinImage: skin: voxedit-axis-z
-
- TBSection: value: 1, text: "Flip on axis"
- TBLayout: position: left top, axis: x
- TBButton: id: mirrorx, @include: definitions>menubutton, command: "flip x"
- TBSkinImage: skin: voxedit-axis-x
- TBButton: id: mirrory, @include: definitions>menubutton, command: "flip y"
- TBSkinImage: skin: voxedit-axis-y
- TBButton: id: mirrorz, @include: definitions>menubutton, command: "flip z"
- TBSkinImage: skin: voxedit-axis-z
-
- TBSection: value: 1, text: "Mirror axis"
- TBLayout: position: left top, axis: x
- TBClickLabel: text: none
- TBRadioButton: group-id: mirrorgroup, id: mirroraxisnone
- TBClickLabel: text: x
- TBRadioButton: group-id: mirrorgroup, id: mirroraxisx
- TBClickLabel: text: y
- TBRadioButton: group-id: mirrorgroup, id: mirroraxisy
- TBClickLabel: text: z
- TBRadioButton: group-id: mirrorgroup, id: mirroraxisz
-
- TBTextField: gravity: left right, skin: Header, text: Layers
- LayerWidget: id: layercontainer, gravity: top bottom
-
- TBSection: value: 0, text: "Options"
- TBLayout: position: left top, axis: y
- TBClickLabel: text: Show axis
- TBCheckBox: id: optionshowaxis, value: 1, varref: ve_showaxis
- TBClickLabel: text: Model space
- TBCheckBox: id: optionaxismodelspace, value: 1, varref: ve_modelspace
- TBClickLabel: text: Show locked axis
- TBCheckBox: id: optionshowlockaxis, value: 1, varref: ve_showlockedaxis
- TBClickLabel: text: Bounding box
- TBCheckBox: id: optionshowaabb, value: 0, varref: ve_showaabb
- TBClickLabel: text: Shadow
- TBCheckBox: id: optionrendershadow, value: 1, varref: ve_rendershadow
- TBClickLabel: text: Outlines
- TBCheckBox: id: optionoutline, value: 1, varref: r_renderoutline
- TBLayout: axis: y
- TBTextField: text: Animation speed
- TBEditField: varref: ve_animspeed
-
- TBLayout: distribution: gravity
- TBContainer: skin: container, gravity: left right
- TBLayout: distribution: gravity
- TBLayout: gravity: left
- TBTextField: id: status, text: -
- TBWidget
- lp: width: 40
- TBTextField: id: dimension, text: -
- TBLayout: gravity: left right
- TBWidget
- TBClickLabel: text: Grid
- TBCheckBox: id: optionshowgrid, value: 1, skin: voxedit-grid-button, varref: ve_showgrid
- TBWidget
- lp: width: 10
- TBClickLabel: text: Grid size
- TBInlineSelect: id: optionvoxelsize, min: 1, max: 64, value: 4, varref: ve_gridsize
- TBWidget
- lp: width: 10
- TBButton: @include: definitions>menubutton, text: Reset View, id: resetcamera, command: resetcamera
- TBSkinImage: skin: voxedit-reset-camera
- TBWidget
- lp: width: 10
- TBClickLabel: text: Quad view
- TBCheckBox: id: toggleviewport, skin: voxedit-quadview-button, command: toggleviewport
- TBWidget
- lp: width: 10
- TBClickLabel: text: Animation view, id: toggleanimationlabel
- TBCheckBox: id: toggleanimation, skin: voxedit-animation-button, command: toggleanimation
- TBWidget
- lp: width: 10
- TBClickLabel: text: Scene view, id: togglescenelabel
- TBCheckBox: id: togglescene, skin: voxedit-scene-button, command: togglescene
diff --git a/data/voxedit-ui/ui/window/voxedit-palette-selector.tb.txt b/data/voxedit-ui/ui/window/voxedit-palette-selector.tb.txt
deleted file mode 100644
index 13b46af16..000000000
--- a/data/voxedit-ui/ui/window/voxedit-palette-selector.tb.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-WindowInfo
- title Select existing palette
- position 500 0
-
-TBLayout: distribution: gravity, axis: y
- TBSelectList
- id palettes
- gravity all
-
- TBSeparator: gravity: left right, skin: separator
- TBLayout: distribution: gravity, axis: x
- TBButton: text: Ok, id: ok, autofocus: 1, gravity: left right, size: gravity
- TBButton: text: Cancel, id: cancel, gravity: left right, size: gravity
diff --git a/data/voxedit-ui/ui/window/voxedit-scene-settings.tb.txt b/data/voxedit-ui/ui/window/voxedit-scene-settings.tb.txt
deleted file mode 100644
index 90690dac6..000000000
--- a/data/voxedit-ui/ui/window/voxedit-scene-settings.tb.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-lighting_settings
- TBContainer
- TBLayout: axis: y
- TBTextField: text: Sun position
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-x
- TBInlineSelect: id: position.x
- lp: width: 120
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-y
- TBInlineSelect: id: position.y
- lp: width: 120
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-z
- TBInlineSelect: id: position.z
- lp: width: 120
- TBContainer
- TBLayout: axis: y
- TBTextField: text: Sun angle
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-x
- TBInlineSelect: id: direction.x
- lp: width: 120
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-y
- TBInlineSelect: id: direction.y
- lp: width: 120
- TBLayout: axis: x
- TBSkinImage: skin: voxedit-axis-z
- TBInlineSelect: id: direction.z
- lp: width: 120
- TBContainer
- TBLayout: axis: y
- TBTextField: text: Ambient color
- TBLayout: axis: x
- TBInlineSelect: id: ambient.r
- min: 0
- max: 255
- lp: width: 120
- TBLayout: axis: x
- TBInlineSelect: id: ambient.g
- min: 0
- max: 255
- lp: width: 120
- TBLayout: axis: x
- TBInlineSelect: id: ambient.b
- min: 0
- max: 255
- lp: width: 120
- TBContainer
- TBLayout: axis: y
- TBTextField: text: Diffuse color
- TBLayout: axis: x
- TBInlineSelect: id: diffuse.r
- min: 0
- max: 255
- lp: width: 120
- TBLayout: axis: x
- TBInlineSelect: id: diffuse.g
- min: 0
- max: 255
- lp: width: 120
- TBLayout: axis: x
- TBInlineSelect: id: diffuse.b
- min: 0
- max: 255
- lp: width: 120
-
-TBLayout: axis: y
- TBTabContainer
- gravity all
- id tabcontainer
- tabs
- TBButton: text: "Lighting"
- TBLayout
- @include lighting_settings
- axis y
- distribution-position top
-
- TBLayout: distribution-position: right bottom, id: buttons
diff --git a/docs/VisualTests.md b/docs/VisualTests.md
index 5a4aad37e..6e30e6f7d 100644
--- a/docs/VisualTests.md
+++ b/docs/VisualTests.md
@@ -80,10 +80,6 @@ Uses GLSL compute shader to render a circle.
Conversion of OpenCL marching cubes taken from:
-## testturbobadger
-
-Renders the turbobadger demo.
-
## testluaui
Test the nuklear lua ui binding
diff --git a/src/modules/ui/CMakeLists.txt b/src/modules/ui/CMakeLists.txt
index f1aa358d7..0e6f56465 100644
--- a/src/modules/ui/CMakeLists.txt
+++ b/src/modules/ui/CMakeLists.txt
@@ -1,3 +1,2 @@
add_subdirectory(imgui)
-add_subdirectory(turbobadger)
add_subdirectory(nuklear)
diff --git a/src/modules/ui/turbobadger/CMakeLists.txt b/src/modules/ui/turbobadger/CMakeLists.txt
deleted file mode 100644
index 585f42330..000000000
--- a/src/modules/ui/turbobadger/CMakeLists.txt
+++ /dev/null
@@ -1,223 +0,0 @@
-set(LIB turbobadger)
-set(SRCS
- tb/animation/tb_animation_utils.h
- tb/animation/tb_animation.cpp
- tb/animation/tb_widget_animation.h
- tb/animation/tb_animation.h
- tb/animation/tb_widget_animation.cpp
- tb/utf8/utf8.cpp
- tb/utf8/utf8.h
- tb/renderers/tb_renderer_batcher.cpp
- tb/renderers/tb_renderer_batcher.h
- tb/thirdparty/stb_truetype.h
- tb/parser/tb_parser.h
- tb/parser/tb_parser.cpp
- tb/image/tb_image_manager.cpp
- tb/image/tb_image_widget.cpp
- tb/image/tb_image_widget.h
- tb/image/tb_image_manager.h
- tb/tb_bitmap_fragment.cpp
- tb/tb_color.cpp
- tb/tb_core.cpp
- tb/tb_debug.cpp
- tb/tb_dimension.cpp
- tb/tb_editfield.cpp
- tb/tb_font_renderer.cpp
- tb/tb_font_renderer_stb.cpp
- tb/tb_font_renderer_tbbf.cpp
- tb/tb_geometry.cpp
- tb/tb_hashtable.cpp
- tb/tb_inline_select.cpp
- tb/tb_language.cpp
- tb/tb_layout.cpp
- tb/tb_linklist.cpp
- tb/tb_list.cpp
- tb/tb_menu_window.cpp
- tb/tb_message_window.cpp
- tb/tb_msg.cpp
- tb/tb_node_ref_tree.cpp
- tb/tb_node_tree.cpp
- tb/tb_popup_window.cpp
- tb/tb_renderer.cpp
- tb/tb_scroll_container.cpp
- tb/tb_scroller.cpp
- tb/tb_select.cpp
- tb/tb_select_item.cpp
- tb/tb_skin.cpp
- tb/tb_skin_util.cpp
- tb/tb_str.cpp
- tb/tb_style_edit.cpp
- tb/tb_style_edit_content.cpp
- tb/tb_system.cpp
- tb/tb_tab_container.cpp
- tb/tb_tempbuffer.cpp
- tb/tb_toggle_container.cpp
- tb/tb_value.cpp
- tb/tb_widget_skin_condition_context.cpp
- tb/tb_widget_value.cpp
- tb/tb_widgets.cpp
- tb/tb_widgets_common.cpp
- tb/tb_widgets_listener.cpp
- tb/tb_widgets_reader.cpp
- tb/tb_window.cpp
- tb/tb_bitmap_fragment.h
- tb/tb_color.h
- tb/tb_config.h
- tb/tb_core.h
- tb/tb_debug.h
- tb/tb_dimension.h
- tb/tb_editfield.h
- tb/tb_font_desc.h
- tb/tb_font_renderer.h
- tb/tb_geometry.h
- tb/tb_hash.h
- tb/tb_hashtable.h
- tb/tb_id.h
- tb/tb_inline_select.h
- tb/tb_language.h
- tb/tb_layout.h
- tb/tb_linklist.h
- tb/tb_list.h
- tb/tb_menu_window.h
- tb/tb_message_window.h
- tb/tb_msg.h
- tb/tb_node_ref_tree.h
- tb/tb_node_tree.h
- tb/tb_object.h
- tb/tb_popup_window.h
- tb/tb_renderer.h
- tb/tb_scroll_container.h
- tb/tb_scroller.h
- tb/tb_select.h
- tb/tb_select_item.h
- tb/tb_skin.h
- tb/tb_skin_util.h
- tb/tb_sort.h
- tb/tb_str.h
- tb/tb_style_edit.h
- tb/tb_style_edit_content.h
- tb/tb_system.h
- tb/tb_tab_container.h
- tb/tb_tempbuffer.h
- tb/tb_toggle_container.h
- tb/tb_types.h
- tb/tb_value.h
- tb/tb_widget_skin_condition_context.h
- tb/tb_widget_value.h
- tb/tb_widgets.h
- tb/tb_widgets_common.h
- tb/tb_widgets_listener.h
- tb/tb_widgets_reader.h
- tb/tb_window.h
-
- UIApp.cpp UIApp.h
- TurboBadger.h
- Window.cpp Window.h
- Widget.h
- FontUtil.h
- FileDialogWindow.h FileDialogWindow.cpp
- WaitingMessage.h WaitingMessage.cpp
- Console.cpp Console.h
- ui_renderer_gl.cpp ui_renderer_gl.h
- ui_widgets.cpp ui_widgets.h
-)
-
-set(IMAGES
- shared/ui/skin/arrow_down
- shared/ui/skin/arrow_left
- shared/ui/skin/arrow_right
- shared/ui/skin/arrow_up
- shared/ui/skin/button_flat_outline
- shared/ui/skin/button_flat_pressed
- shared/ui/skin/button_grouped_x_first_down
- shared/ui/skin/button_grouped_x_first_up
- shared/ui/skin/button_grouped_x_last_down
- shared/ui/skin/button_grouped_x_last_up
- shared/ui/skin/button_grouped_x_middle_down
- shared/ui/skin/button_grouped_x_middle_up
- shared/ui/skin/button
- shared/ui/skin/button_pressed
- shared/ui/skin/checkbox_mark
- shared/ui/skin/checkbox
- shared/ui/skin/checkbox_pressed
- shared/ui/skin/container
- shared/ui/skin/editfield
- shared/ui/skin/fadeout_x
- shared/ui/skin/fadeout_y
- shared/ui/skin/filedialog-dir
- shared/ui/skin/filedialog-file
- shared/ui/skin/focus_r4
- shared/ui/skin/focus_tabbutton_left
- shared/ui/skin/focus_tabbutton_top
- shared/ui/skin/item_hover
- shared/ui/skin/item_selected
- shared/ui/skin/item_separator_x
- shared/ui/skin/item_separator_y
- shared/ui/skin/progress_spinner_strip
- shared/ui/skin/radio_mark
- shared/ui/skin/radio
- shared/ui/skin/radio_pressed
- shared/ui/skin/remove
- shared/ui/skin/resizer
- shared/ui/skin/scroll_bg_x
- shared/ui/skin/scroll_bg_y
- shared/ui/skin/scroll_fg_x
- shared/ui/skin/scroll_fg_y
- shared/ui/skin/search
- shared/ui/skin/section_container
- shared/ui/skin/selection
- shared/ui/skin/slider_bg_x
- shared/ui/skin/slider_bg_y
- shared/ui/skin/slider_handle
- shared/ui/skin/tab_button_bottom_active
- shared/ui/skin/tab_button_bottom_inactive
- shared/ui/skin/tab_button_left_active
- shared/ui/skin/tab_button_left_inactive
- shared/ui/skin/tab_button_right_active
- shared/ui/skin/tab_button_right_inactive
- shared/ui/skin/tab_button_top_active
- shared/ui/skin/tab_button_top_inactive
- shared/ui/skin/toggle_section_icon_down
- shared/ui/skin/toggle_section_icon_middle
- shared/ui/skin/toggle_section_icon_up
- shared/ui/skin/window_active
- shared/ui/skin/window_close
- shared/ui/skin/window_close_pressed
- shared/ui/skin/window_mover_bg_tile
- shared/ui/skin/window_mover_overlay
- shared/ui/skin/window
-)
-
-set(FILES
- shared/ui/skin/skin.tb.txt
- shared/ui/font/font_14.png
- shared/ui/font/font_28.png
- shared/ui/font/font.tb.txt
- shared/ui/font/DejaVuSansMono.ttf
- shared/ui/window/filedialog_dir.tb.txt
- shared/ui/window/filedialog_file.tb.txt
- shared/ui/window/filedialog.tb.txt
-)
-
-foreach(IMAGE ${IMAGES})
- list(APPEND FILES ${IMAGE}.png)
-endforeach()
-set(DPIS "@288")
-foreach(DPI ${DPIS})
- foreach(IMAGE ${IMAGES})
- list(APPEND FILES ${IMAGE}${DPI}.png)
- endforeach()
-endforeach()
-
-if (WINDOWS)
- add_definitions(-D_CRT_SECURE_NO_WARNINGS)
- add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
- add_definitions(-DTB_USE_CURRENT_DIRECTORY)
-elseif (LINUX)
-elseif (DARWIN)
- add_definitions(-DMACOSX)
- add_definitions(-DTB_USE_CURRENT_DIRECTORY)
-endif()
-
-engine_add_module(TARGET ${LIB} SRCS ${SRCS} FILES ${FILES} DEPENDENCIES imgui app render)
-target_include_directories(${LIB} PUBLIC tb)
diff --git a/src/modules/ui/turbobadger/Console.cpp b/src/modules/ui/turbobadger/Console.cpp
deleted file mode 100644
index 30eb9fd74..000000000
--- a/src/modules/ui/turbobadger/Console.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * @file
- */
-
-#include "Console.h"
-#include "TurboBadger.h"
-#include "FontUtil.h"
-#include "core/Color.h"
-#include "UIApp.h"
-#include
-
-namespace ui {
-namespace turbobadger {
-
-Console::Console() :
- Super() {
-}
-
-void Console::construct() {
- Super::construct();
- _consoleAlpha = core::Var::get("ui_consolealpha", "0.9", "Console background alpha value between 0.0 and 1.0");
- _consoleBackground = core::Var::get("ui_consolebackground", "0.1", "Console background gray color value between 0.0 and 1.0");
- _consoleFontSize = core::Var::get("ui_consolefontsize", "14", "Console font size");
-}
-
-bool Console::init() {
- if (!Super::init()) {
- return false;
- }
- _font = getMonoSpaceFont(_consoleFontSize->intVal());
- return true;
-}
-
-bool Console::toggle() {
- const bool active = Super::toggle();
- if (active) {
- SDL_StartTextInput();
- } else {
- SDL_StopTextInput();
- }
- return active;
-}
-
-void Console::drawString(int x, int y, const glm::ivec4& color, int, const char* str, int len) {
- _font->drawString(x, y, tb::TBColor{color.r, color.g, color.b}, str, len);
-}
-
-void Console::beforeRender(const math::Rect &rect) {
- _consoleFontSize->setVal(_fontSize);
- if (_consoleFontSize->isDirty()) {
- _font = getMonoSpaceFont(_consoleFontSize->intVal());
- _consoleFontSize->markClean();
- }
- const tb::TBRect r(rect.getMinX(), rect.getMinZ(), rect.getMaxX(), rect.getMaxZ());
- const int c = glm::clamp((int)(_consoleBackground->floatVal() * core::Color::magnitudef), 0, 255);
- const int a = glm::clamp((int)(_consoleAlpha->floatVal() * core::Color::magnitudef), 0, 255);
- const tb::TBColor consoleBgColor(c, c, c, a);
- tb::g_tb_skin->paintRectFill(r, consoleBgColor);
- char buf[64];
- SDL_snprintf(buf, sizeof(buf), "FPS: %f", UIApp::fps());
- const int bufSize = SDL_strlen(buf);
- const int length = _font->getStringWidth(buf, bufSize);
- _font->drawString(rect.getMaxX() - length, 0, tb::TBColor{255, 255, 255}, buf, bufSize);
-}
-
-int Console::lineHeight() {
- const int lineHeight = _font->getFontDescription().getSize();
- return lineHeight;
-}
-
-glm::ivec2 Console::stringSize(const char* s, int length) {
- return glm::ivec2(_font->getStringWidth(s, length), lineHeight());
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/Console.h b/src/modules/ui/turbobadger/Console.h
deleted file mode 100644
index 552447415..000000000
--- a/src/modules/ui/turbobadger/Console.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "util/Console.h"
-#include "core/Var.h"
-
-namespace tb {
-class TBFontFace;
-}
-
-namespace ui {
-namespace turbobadger {
-
-class Console : public util::Console {
-private:
- using Super = util::Console;
- tb::TBFontFace *_font = nullptr;
- core::VarPtr _consoleAlpha;
- core::VarPtr _consoleBackground;
- core::VarPtr _consoleFontSize;
-
- void drawString(int x, int y, const glm::ivec4& color, int, const char* str, int len) override;
- int lineHeight() override;
- glm::ivec2 stringSize(const char* s, int length) override;
- void beforeRender(const math::Rect &rect) override;
-
-public:
- Console();
- void construct() override;
- bool init() override;
- bool toggle() override;
-};
-
-}
-}
diff --git a/src/modules/ui/turbobadger/FileDialogWindow.cpp b/src/modules/ui/turbobadger/FileDialogWindow.cpp
deleted file mode 100644
index 2556612e0..000000000
--- a/src/modules/ui/turbobadger/FileDialogWindow.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/**
- * @file
- */
-
-#include "FileDialogWindow.h"
-#include "core/StringUtil.h"
-#include "ui/turbobadger/UIApp.h"
-#include
-
-namespace ui {
-namespace turbobadger {
-
-static const char *FILELIST = "files";
-static const char *DIRLIST = "dirs";
-static const char *FILTERLIST = "filter";
-static const char *INPUT = "input";
-
-FileDialogItemWidget::FileDialogItemWidget(FileDialogItem *item) : tb::TBLayout() {
- setSkinBg(TBIDC("TBSelectItem"));
- setLayoutDistribution(tb::LAYOUT_DISTRIBUTION_GRAVITY);
- setLayoutDistributionPosition(tb::LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP);
- setPaintOverflowFadeout(false);
-
- if (item->entry().type == io::Filesystem::DirEntry::Type::dir) {
- tb::g_widgets_reader->loadFile(getContentRoot(), "ui/window/filedialog_dir.tb.txt");
- } else {
- tb::g_widgets_reader->loadFile(getContentRoot(), "ui/window/filedialog_file.tb.txt");
- }
- if (tb::TBTextField *name = getWidgetByIDAndType(TBIDC("name"))) {
- name->setText(item->entry().name.c_str());
- }
-}
-
-bool FileDialogItemSource::filterHidden(const io::Filesystem::DirEntry& entry) const {
- if (_showHidden) {
- return false;
- }
- if (entry.name == "..") {
- return false;
- }
- return entry.name[0] == '.';
-}
-
-bool FileDialogItemSource::filter(int index, const char *filter) {
- const FileDialogItem* item = getItem(index);
- if (item == nullptr) {
- return false;
- }
-
- const io::Filesystem::DirEntry& entry = item->entry();
-
- if (filterHidden(entry)) {
- return false;
- }
-
- // never filter directories if we want to see directories - because we
- // always want to be able to switch to those directories
- if (entry.type == io::Filesystem::DirEntry::Type::dir && _mode != video::WindowedApp::OpenFileMode::Directory) {
- return true;
- }
-
- return core::string::fileMatchesMultiple(item->str.c_str(), filter);
-}
-
-tb::TBWidget *FileDialogItemSource::createItemWidget(int index, tb::TBSelectItemViewer *viewer) {
- return new FileDialogItemWidget(getItem(index));
-}
-
-FileDialogWindow::FileDialogWindow(UIApp* tool, const std::function& callback, const core::VarPtr& lastDirectory) :
- Super(tool), _callback(callback), _lastDirectory(lastDirectory) {
- _fs = tool->filesystem();
- loadResourceFile("ui/window/filedialog.tb.txt");
- if (tb::TBSelectList * select = getWidgetByType(FILELIST)) {
- select->setSource(&_entityList);
- select->getScrollContainer()->setScrollMode(tb::SCROLL_MODE_X_AUTO_Y_AUTO);
- }
- if (tb::TBSelectList * select = getWidgetByType(DIRLIST)) {
- select->setSource(&_dirList);
- const io::Paths& paths = io::filesystem()->paths();
- for (const auto& p : paths) {
- _dirList.addItem(new tb::TBGenericStringItem(p.c_str()));
- }
- }
- if (tb::TBSelectDropdown * select = getWidgetByType(FILTERLIST)) {
- select->setSource(&_filterList);
- }
-
- _filterList.setSort(tb::TB_SORT_ASCENDING);
- _directory = _fs->absolutePath(".");
- setMode(video::WindowedApp::OpenFileMode::Open);
-}
-
-FileDialogWindow::~FileDialogWindow() {
- if (tb::TBSelectList *select = getWidgetByType(FILELIST)) {
- select->setSource(nullptr);
- }
- if (tb::TBSelectDropdown * select = getWidgetByType(FILTERLIST)) {
- select->setSource(nullptr);
- }
- if (tb::TBSelectList * select = getWidgetByType(DIRLIST)) {
- select->setSource(nullptr);
- }
-}
-
-void FileDialogWindow::addShortcut(const core::String& dir) {
- _dirList.addItem(new tb::TBGenericStringItem(dir.c_str()));
-}
-
-void FileDialogWindow::setMode(video::WindowedApp::OpenFileMode mode, const char *inputText) {
- _mode = mode;
- _entityList.setMode(mode);
- if (tb::TBEditField * input = getWidgetByType(INPUT)) {
- if (_mode == video::WindowedApp::OpenFileMode::Save
- || _mode == video::WindowedApp::OpenFileMode::Open) {
- input->setVisibility(tb::WIDGET_VISIBILITY_VISIBLE);
- input->setFocus(tb::WIDGET_FOCUS_REASON_UNKNOWN);
- if (inputText != nullptr) {
- input->setText(inputText);
- }
- if (_mode == video::WindowedApp::OpenFileMode::Save) {
- input->setPlaceholderText(tr("Enter filename for saving"));
- if (tb::TBButton * ok = getWidgetByType("ok")) {
- ok->setState(tb::WIDGET_STATE_DISABLED, input->getText().empty());
- }
- } else {
- input->setPlaceholderText(tr("Enter filename for loading"));
- if (tb::TBButton * ok = getWidgetByType("ok")) {
- ok->setState(tb::WIDGET_STATE_DISABLED, false);
- }
- }
- } else {
- input->setVisibility(tb::WIDGET_VISIBILITY_GONE);
- }
- }
-}
-
-void FileDialogWindow::setFilter(const char **filter) {
- _filterList.deleteAllItems();
- tb::TBSelectDropdown * select = getWidgetByType(FILTERLIST);
- if (filter == nullptr) {
- if (select != nullptr) {
- select->setVisibility(tb::WIDGET_VISIBILITY_INVISIBLE);
- }
- return;
- }
- for (const char** f = filter; *f; ++f) {
- _filterList.addItem(new tb::TBGenericStringItem(*f));
- }
- _filterList.addItem(new tb::TBGenericStringItem("*"));
- if (select != nullptr && _filterList.getNumItems() > 0) {
- select->setValue(0);
- select->setVisibility(tb::WIDGET_VISIBILITY_VISIBLE);
- }
-}
-
-bool FileDialogWindow::onEvent(const tb::TBWidgetEvent &ev) {
- if (ev.type == tb::EVENT_TYPE_CHANGED) {
- if (ev.target->getID() == TBIDC(FILTERLIST)) {
- if (tb::TBSelectList *select = getWidgetByType(FILELIST)) {
- select->setFilter(ev.target->getText());
- return true;
- }
- } else if (ev.target->getID() == TBIDC(DIRLIST)) {
- if (tb::TBGenericStringItem* item = _dirList.getItem(ev.target->getValue())) {
- changeDir(item->str.c_str());
- if (tb::TBEditField * input = getWidgetByType(INPUT)) {
- input->setText(_directory.c_str());
- }
- }
- return true;
- } else if (ev.target->getID() == TBIDC(INPUT)) {
- const core::String& str = ev.target->getText();
- if (tb::TBButton * ok = getWidgetByType("ok")) {
- bool disabled;
- if (str.empty()) {
- disabled = true;
- } else {
- disabled = true;
- if (_filterList.getNumItems() == 1) {
- disabled = false;
- } else {
- for (int i = 0; i < _filterList.getNumItems(); i++) {
- const char *filter = _filterList.getItemString(i);
- if (!SDL_strcmp(filter, "*")) {
- continue;
- }
- if (core::string::fileMatchesMultiple(str.c_str(), filter)) {
- disabled = false;
- break;
- }
- }
- }
- }
- ok->setState(tb::WIDGET_STATE_DISABLED, disabled);
- }
- // if entered manually, we want to change the directory.
- if (io::Filesystem::isReadableDir(str.c_str())) {
- changeDir(str.c_str());
- }
- }
- }
- if (ev.type == tb::EVENT_TYPE_KEY_DOWN && ev.special_key == tb::TB_KEY_ESC) {
- tb::TBWidgetEvent click_ev(tb::EVENT_TYPE_CLICK);
- m_close_button.invokeEvent(click_ev);
- return true;
- }
- const tb::TBID& id = ev.target->getID();
- if (ev.type == tb::EVENT_TYPE_POINTER_DOWN && ev.count >= 2) {
- if (tb::TBSelectList *select = getWidgetByType(FILELIST)) {
- const int index = select->getValue();
- if (index >= 0 && index < _entityList.getNumItems()) {
- const FileDialogItem* item = _entityList.getItem(index);
- const auto& dirEntry = item->entry();
- if (_mode != video::WindowedApp::OpenFileMode::Directory
- && dirEntry.type == io::Filesystem::DirEntry::Type::dir) {
- changeDir(dirEntry.name);
- if (tb::TBEditField * input = getWidgetByType(INPUT)) {
- input->setText(_directory.c_str());
- }
- return true;
- }
- if (_mode == video::WindowedApp::OpenFileMode::Save) {
- if (tb::TBEditField * input = getWidgetByType(INPUT)) {
- input->setText(dirEntry.name.c_str());
- }
- } else {
- const core::String& filename = dirEntry.name;
- if (io::Filesystem::isRelativePath(filename)) {
- _callback(_directory + "/" + filename);
- } else {
- _callback(filename);
- }
- tb::TBWidgetEvent click_ev(tb::EVENT_TYPE_CLICK);
- m_close_button.invokeEvent(click_ev);
- }
- return true;
- }
- }
- } else if (ev.type == tb::EVENT_TYPE_CLICK) {
- if (id == TBIDC("ok")) {
- if (_mode == video::WindowedApp::OpenFileMode::Save) {
- if (tb::TBEditField * input = getWidgetByType(INPUT)) {
- const core::String& filename = input->getText();
- const core::String& sfilename = core::String(filename.c_str());
- if (io::Filesystem::isRelativePath(sfilename)) {
- _callback(_directory + "/" + sfilename);
- } else {
- _callback(sfilename);
- }
- } else {
- Log::error("Failed to get input node");
- }
- } else if (tb::TBSelectList *select = getWidgetByType(FILELIST)) {
- const int index = select->getValue();
- if (index >= 0 && index < _entityList.getNumItems()) {
- const FileDialogItem* item = _entityList.getItem(index);
- const auto& dirEntry = item->entry();
- const core::String& filename = dirEntry.name;
- if (io::Filesystem::isRelativePath(filename)) {
- _callback(_directory + "/" + filename);
- } else {
- _callback(filename);
- }
- }
- }
- tb::TBWidgetEvent click_ev(tb::EVENT_TYPE_CLICK);
- m_close_button.invokeEvent(click_ev);
- return true;
- } else if (id == TBIDC("cancel")) {
- tb::TBWidgetEvent click_ev(tb::EVENT_TYPE_CLICK);
- m_close_button.invokeEvent(click_ev);
- return true;
- }
- }
-
- return Super::onEvent(ev);
-}
-
-void FileDialogWindow::init() {
- if (tb::TBEditField * input = getWidgetByType(INPUT)) {
- input->setText(_directory.c_str());
- }
-}
-
-void FileDialogWindow::changeDir(const core::String& dir) {
- if (!dir.empty()) {
- if (io::Filesystem::isRelativePath(dir)) {
- _directory = _fs->absolutePath(_directory + "/" + dir);
- } else {
- _directory = dir;
- }
- if (!io::Filesystem::isReadableDir(_directory)) {
- _directory = _fs->absolutePath(".");
- }
- }
- _lastDirectory->setVal(_directory);
-
- _entityList.deleteAllItems();
- _entityList.addItem(new FileDialogItem(io::Filesystem::DirEntry{"..", io::Filesystem::DirEntry::Type::dir, (uint64_t)0, (uint64_t)0}));
-
- core::DynamicArray entities;
- getApp()->filesystem()->list(_directory, entities);
-
- Log::debug("Looking in %s and found %i entries", _directory.c_str(), (int)entities.size());
- for (const io::Filesystem::DirEntry& e : entities) {
- _entityList.addItem(new FileDialogItem(e));
- }
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/FileDialogWindow.h b/src/modules/ui/turbobadger/FileDialogWindow.h
deleted file mode 100644
index fe18d1dc1..000000000
--- a/src/modules/ui/turbobadger/FileDialogWindow.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "ui/turbobadger/Window.h"
-#include "ui/turbobadger/ui_widgets.h"
-#include "video/WindowedApp.h"
-#include "io/Filesystem.h"
-
-namespace ui {
-namespace turbobadger {
-
-/**
- * @brief Adds extra info to a string item.
- */
-class FileDialogItem: public tb::TBGenericStringItem {
-private:
- const io::Filesystem::DirEntry _entry;
-public:
- FileDialogItem(const io::Filesystem::DirEntry& entry) :
- tb::TBGenericStringItem(entry.name.c_str()), _entry(entry) {
- }
-
- inline const io::Filesystem::DirEntry& entry() const { return _entry; }
-};
-
-/**
- * @brief FileDialogItemWidget is the widget representing a FileDialogItem.
- * On changes to the item, it calls InvokeItemChanged on the source, so that all
- * viewers of the source are updated to reflect the change.
- */
-class FileDialogItemWidget : public tb::TBLayout {
-public:
- FileDialogItemWidget(FileDialogItem *item);
-};
-
-/**
- * @brief FileDialogItemSource provides items of type FileDialogItem and makes sure
- * the viewer is populated with the customized widget for each item.
- */
-class FileDialogItemSource: public tb::TBSelectItemSourceList {
-private:
- video::WindowedApp::OpenFileMode _mode;
- bool _showHidden = false;
- bool filterHidden(const io::Filesystem::DirEntry& entry) const;
-public:
- bool filter(int index, const char *filter) override;
- tb::TBWidget *createItemWidget(int index, tb::TBSelectItemViewer *viewer) override;
-
- inline void setMode(video::WindowedApp::OpenFileMode mode) { _mode = mode; }
- inline void setShowHidden(bool showHidden) { _showHidden = showHidden; }
-};
-
-class FileDialogWindow: public ui::turbobadger::Window {
-private:
- using Super = ui::turbobadger::Window;
- core::String _directory;
- video::WindowedApp::OpenFileMode _mode;
- FileDialogItemSource _entityList;
- tb::TBGenericStringItemSource _dirList;
- tb::TBGenericStringItemSource _filterList;
- std::function _callback;
- io::FilesystemPtr _fs;
- core::VarPtr _lastDirectory;
-public:
- FileDialogWindow(UIApp* app, const std::function& callback, const core::VarPtr& lastDirectory);
- ~FileDialogWindow();
- void changeDir(const core::String& dir = "");
- void init();
- void addShortcut(const core::String& dir);
-
- void setFilter(const char **filter);
- void setMode(video::WindowedApp::OpenFileMode mode, const char *inputText = nullptr);
-
- bool onEvent(const tb::TBWidgetEvent &ev) override;
-};
-
-}
-}
diff --git a/src/modules/ui/turbobadger/FontUtil.h b/src/modules/ui/turbobadger/FontUtil.h
deleted file mode 100644
index b8036f611..000000000
--- a/src/modules/ui/turbobadger/FontUtil.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "TurboBadger.h"
-#include "core/Common.h"
-
-extern void register_tbbf_font_renderer();
-extern void register_stb_font_renderer();
-
-namespace ui {
-namespace turbobadger {
-
-static inline void initFonts() {
- register_tbbf_font_renderer();
- register_stb_font_renderer();
-
- tb::g_font_manager->addFontInfo("ui/font/font.tb.txt", "Segoe");
- tb::g_font_manager->addFontInfo("ui/font/DejaVuSansMono.ttf", "monospace");
-}
-
-static inline tb::TBFontFace *getFontByName(const char* fontname, int dpSize = 14, bool registerAsDefault = false) {
- tb::TBFontFace *_font;
- tb::TBFontDescription fd;
- fd.setID(TBIDC(fontname));
- fd.setSize(tb::g_tb_skin->getDimensionConverter()->dpToPx(dpSize));
-
- tb::TBFontManager *fontMgr = tb::g_font_manager;
- if (registerAsDefault) {
- fontMgr->setDefaultFontDescription(fd);
- }
-
- if (fontMgr->hasFontFace(fd)) {
- _font = fontMgr->getFontFace(fd);
- } else {
- _font = fontMgr->createFontFace(fd);
- }
- core_assert_msg(_font != nullptr, "Could not find the default font - make sure the ui is already configured");
- _font->renderGlyphs(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ");
- return _font;
-}
-
-static inline tb::TBFontFace *getFont(int dpSize = 14, bool registerAsDefault = false) {
- return getFontByName("Segoe", dpSize, registerAsDefault);
-}
-
-static inline tb::TBFontFace *getMonoSpaceFont(int dpSize = 14, bool registerAsDefault = false) {
- return getFontByName("monospace", dpSize, registerAsDefault);
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/TurboBadger.h b/src/modules/ui/turbobadger/TurboBadger.h
deleted file mode 100644
index 9e30c8a81..000000000
--- a/src/modules/ui/turbobadger/TurboBadger.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "ui_renderer_gl.h"
-
-#define UIWIDGET_SUBCLASS(clazz, baseclazz) TBOBJECT_SUBCLASS(clazz, baseclazz)
-#define UIWIDGET_FACTORY(classname, sync_type, add_child_z) \
- class classname##Factory : public tb::TBWidgetFactory \
- { \
- public: \
- classname##Factory() \
- : tb::TBWidgetFactory(#classname, sync_type) { doRegister(); } \
- virtual ~classname##Factory() {} \
- virtual tb::TBWidget *create(tb::INFLATE_INFO *info) \
- { \
- classname *widget = new classname(); \
- if (widget) { \
- widget->getContentRoot()->setZInflate(add_child_z); \
- } \
- return widget; \
- } \
- };
-
-namespace ui {
-namespace turbobadger {
-using UIRect = tb::TBRect;
-using UICheckBox = tb::TBCheckBox;
-using UIRadioButton = tb::TBRadioButton;
-using UITextField = tb::TBTextField;
-}
-}
diff --git a/src/modules/ui/turbobadger/UIApp.cpp b/src/modules/ui/turbobadger/UIApp.cpp
deleted file mode 100644
index 41aed5f6e..000000000
--- a/src/modules/ui/turbobadger/UIApp.cpp
+++ /dev/null
@@ -1,549 +0,0 @@
-/**
- * @file
- */
-
-#include "UIApp.h"
-#include "ui/turbobadger/TurboBadger.h"
-#include "ui/turbobadger/FontUtil.h"
-#include "FileDialogWindow.h"
-
-#include "io/Filesystem.h"
-#include "command/Command.h"
-#include "core/collection/DynamicArray.h"
-#include "core/Color.h"
-#include "core/UTF8.h"
-#include "core/Common.h"
-#include "core/Trace.h"
-#include "math/Rect.h"
-#include "ui_renderer_gl.h"
-#include "ui_widgets.h"
-#include
-
-namespace ui {
-namespace turbobadger {
-
-namespace {
-
-static ImageWidgetFactory imageWidget_wf;
-static ColorWidgetFactory colorWidget_wf;
-
-static inline tb::MODIFIER_KEYS mapModifier(int32_t key, int16_t modifier) {
- tb::MODIFIER_KEYS code = tb::TB_MODIFIER_NONE;
- switch (key) {
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- code |= tb::TB_CTRL;
- break;
- case SDLK_LSHIFT:
- case SDLK_RSHIFT:
- code |= tb::TB_SHIFT;
- break;
- case SDLK_LALT:
- case SDLK_RALT:
- code |= tb::TB_ALT;
- break;
- case SDLK_LGUI:
- case SDLK_RGUI:
- code |= tb::TB_SUPER;
- break;
- case SDLK_MODE:
- break;
- }
-
- if (modifier & KMOD_ALT)
- code |= tb::TB_ALT;
- if (modifier & KMOD_CTRL)
- code |= tb::TB_CTRL;
- if (modifier & KMOD_SHIFT)
- code |= tb::TB_SHIFT;
- if (modifier & KMOD_GUI)
- code |= tb::TB_SUPER;
- return code;
-}
-
-static tb::SPECIAL_KEY mapSpecialKey(int32_t key) {
- switch (key) {
- case SDLK_F1:
- return tb::TB_KEY_F1;
- case SDLK_F2:
- return tb::TB_KEY_F2;
- case SDLK_F3:
- return tb::TB_KEY_F3;
- case SDLK_F4:
- return tb::TB_KEY_F4;
- case SDLK_F5:
- return tb::TB_KEY_F5;
- case SDLK_F6:
- return tb::TB_KEY_F6;
- case SDLK_F7:
- return tb::TB_KEY_F7;
- case SDLK_F8:
- return tb::TB_KEY_F8;
- case SDLK_F9:
- return tb::TB_KEY_F9;
- case SDLK_F10:
- return tb::TB_KEY_F10;
- case SDLK_F11:
- return tb::TB_KEY_F11;
- case SDLK_F12:
- return tb::TB_KEY_F12;
- case SDLK_LEFT:
- return tb::TB_KEY_LEFT;
- case SDLK_UP:
- return tb::TB_KEY_UP;
- case SDLK_RIGHT:
- return tb::TB_KEY_RIGHT;
- case SDLK_DOWN:
- return tb::TB_KEY_DOWN;
- case SDLK_PAGEUP:
- return tb::TB_KEY_PAGE_UP;
- case SDLK_PAGEDOWN:
- return tb::TB_KEY_PAGE_DOWN;
- case SDLK_HOME:
- return tb::TB_KEY_HOME;
- case SDLK_END:
- return tb::TB_KEY_END;
- case SDLK_INSERT:
- return tb::TB_KEY_INSERT;
- case SDLK_TAB:
- return tb::TB_KEY_TAB;
- case SDLK_DELETE:
- return tb::TB_KEY_DELETE;
- case SDLK_BACKSPACE:
- return tb::TB_KEY_BACKSPACE;
- case SDLK_RETURN:
- case SDLK_KP_ENTER:
- return tb::TB_KEY_ENTER;
- case SDLK_ESCAPE:
- return tb::TB_KEY_ESC;
- case SDLK_LSHIFT:
- case SDLK_RSHIFT:
- return tb::TB_KEY_SHIFT;
- case SDLK_LALT:
- case SDLK_RALT:
- return tb::TB_KEY_ALT;
- case SDLK_RGUI:
- case SDLK_LGUI:
- return tb::TB_KEY_GUI;
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- return tb::TB_KEY_CTRL;
- case SDLK_MODE:
- return tb::TB_KEY_MODE;
- }
-
- return tb::TB_KEY_UNDEFINED;
-}
-
-static inline int mapKey(int32_t key) {
- switch (key) {
- case SDLK_LCTRL:
- case SDLK_LSHIFT:
- case SDLK_LALT:
- case SDLK_LGUI:
- case SDLK_RCTRL:
- case SDLK_RSHIFT:
- case SDLK_RALT:
- case SDLK_RGUI:
- case SDLK_MODE:
- break;
- default:
- if (mapSpecialKey(key) == tb::TB_KEY_UNDEFINED) {
- return key;
- }
- }
- return 0;
-}
-
-}
-
-tb::UIRendererGL _renderer;
-
-UIApp::UIApp(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider, size_t threadPoolSize) :
- Super(metric, filesystem, eventBus, timeProvider, threadPoolSize) {
-}
-
-UIApp::~UIApp() {
-}
-
-bool UIApp::invokeKey(int key, tb::SPECIAL_KEY special, tb::MODIFIER_KEYS mod, bool down) {
-#ifdef MACOSX
- bool shortcutKey = (mod & tb::TB_SUPER) ? true : false;
-#else
- bool shortcutKey = (mod & tb::TB_CTRL) ? true : false;
-#endif
- Log::debug(_logId, "invoke key: %s (%i)", down ? "down" : "up", key);
- if (tb::TBWidget::focused_widget && down && shortcutKey && key != 0) {
- bool reverseKey = (mod & tb::TB_SHIFT) ? true : false;
- if (key >= 'a' && key <= 'z') {
- key += 'A' - 'a';
- }
- tb::TBID id;
- if (key == 'X') {
- id = TBIDC("cut");
- } else if (key == 'C' || special == tb::TB_KEY_INSERT) {
- id = TBIDC("copy");
- } else if (key == 'V' || (special == tb::TB_KEY_INSERT && reverseKey)) {
- id = TBIDC("paste");
- } else if (key == 'A') {
- id = TBIDC("selectall");
- } else if (key == 'Z' || key == 'Y') {
- bool undo = key == 'Z';
- if (reverseKey) {
- undo = !undo;
- }
- id = undo ? TBIDC("undo") : TBIDC("redo");
- } else if (key == 'N') {
- id = TBIDC("new");
- } else if (key == 'O') {
- id = TBIDC("open");
- } else if (key == 'S') {
- id = TBIDC("save");
- } else if (key == 'W') {
- id = TBIDC("close");
- } else if (special == tb::TB_KEY_PAGE_UP) {
- id = TBIDC("prev_doc");
- } else if (special == tb::TB_KEY_PAGE_DOWN) {
- id = TBIDC("next_doc");
- } else {
- return false;
- }
-
- tb::TBWidgetEvent ev(tb::EVENT_TYPE_SHORTCUT, 0, 0, tb::TB_UNKNOWN, mod);
- ev.ref_id = id;
- Log::debug(_logId, "invoke shortcut event: %i", key);
- return tb::TBWidget::focused_widget->invokeEvent(ev);
- }
-
- if (special == tb::TB_KEY_UNDEFINED && SDL_IsTextInputActive()) {
- return true;
- }
-
- if (_root->getVisibility() != tb::WIDGET_VISIBILITY_VISIBLE) {
- return false;
- }
- return _root->invokeKey(key, special, mod, down);
-}
-
-void UIApp::showStr(int x, int y, const glm::vec4& color, const char *fmt, ...) {
- static char buf[1024];
- va_list ap;
- va_start(ap, fmt);
- SDL_vsnprintf(buf, sizeof(buf), fmt, ap);
- buf[sizeof(buf) - 1] = '\0';
- _root->getFont()->drawString(x, y, tb::TBColor(color.r * 255.0f, color.g * 255.0f, color.b * 255.0f, color.a * 255.0f), buf, SDL_strlen(buf));
- va_end(ap);
-}
-
-void UIApp::enqueueShowStr(int x, const glm::vec4& color, const char *fmt, ...) {
- static char buf[1024];
- va_list ap;
- va_start(ap, fmt);
- SDL_vsnprintf(buf, sizeof(buf), fmt, ap);
- buf[sizeof(buf) - 1] = '\0';
- tb::TBFontFace* font = _root->getFont();
- font->drawString(x, _lastShowTextY, tb::TBColor(color.r * 255.0f, color.g * 255.0f, color.b * 255.0f, color.a * 255.0f), buf, SDL_strlen(buf));
- _lastShowTextY += _root->getFont()->getHeight() + 5;
- va_end(ap);
-}
-
-void UIApp::fileDialog(const std::function& callback, OpenFileMode mode, const core::String& filter) {
- if (isRelativeMouseMode()) {
- toggleRelativeMouseMode();
- }
- FileDialogWindow* dialog = new FileDialogWindow(this, callback, _lastDirectory);
- dialog->setMode(mode);
- const core::String& lastDir = _lastDirectory->strVal();
- if (!lastDir.empty()) {
- dialog->addShortcut(lastDir);
- }
- if (!filter.empty()) {
- core::DynamicArray tokens;
- core::string::splitString(filter, tokens, ";");
- const char **filters = new const char*[tokens.size() + 1];
- int n = 0;
- for (const auto& f : tokens) {
- filters[n++] = f.c_str();
- }
- filters[n] = nullptr;
- dialog->setFilter((const char**)filters);
- delete[] filters;
- }
- dialog->changeDir(lastDir);
- dialog->init();
-}
-
-bool UIApp::onMouseWheel(int32_t x, int32_t y) {
- if (_console.onMouseWheel(x, y)) {
- return true;
- }
- if (Super::onMouseWheel(x, y)) {
- return true;
- }
- return _root->invokeWheel(_mousePos.x, _mousePos.y, x, -y, getModifierKeys());
-}
-
-void UIApp::onMouseButtonPress(int32_t x, int32_t y, uint8_t button, uint8_t clicks) {
- if (_console.onMouseButtonPress(x, y, button)) {
- return;
- }
- const tb::MODIFIER_KEYS modKeys = getModifierKeys();
-
- tb::BUTTON_TYPE type = tb::BUTTON_TYPE::TB_UNKNOWN;
- if (button == SDL_BUTTON_LEFT) {
- type = tb::TB_LEFT;
- } else if (button == SDL_BUTTON_RIGHT) {
- type = tb::TB_RIGHT;
- } else if (button == SDL_BUTTON_MIDDLE) {
- type = tb::TB_MIDDLE;
- }
-
- _root->invokePointerDown(x, y, clicks, modKeys, type);
- Super::onMouseButtonPress(x, y, button, clicks);
-}
-
-tb::MODIFIER_KEYS UIApp::getModifierKeys() const {
- return mapModifier(0, SDL_GetModState());
-}
-
-void UIApp::onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) {
- if (_console.isActive()) {
- return;
- }
- const tb::MODIFIER_KEYS modKeys = getModifierKeys();
- tb::BUTTON_TYPE type = tb::BUTTON_TYPE::TB_UNKNOWN;
- if (button == SDL_BUTTON_LEFT) {
- type = tb::TB_LEFT;
- } else if (button == SDL_BUTTON_RIGHT) {
- type = tb::TB_RIGHT;
- } else if (button == SDL_BUTTON_MIDDLE) {
- type = tb::TB_MIDDLE;
- }
- if (button == SDL_BUTTON_RIGHT) {
- _root->invokePointerMove(x, y, modKeys, type);
- tb::TBWidget* hover = tb::TBWidget::hovered_widget;
- if (hover != nullptr) {
- hover->convertFromRoot(x, y);
- tb::TBWidgetEvent ev(tb::EVENT_TYPE_CONTEXT_MENU, x, y, type, modKeys);
- if (!hover->invokeEvent(ev)) {
- _root->invokePointerUp(x, y, modKeys, type);
- }
- } else {
- _root->invokePointerUp(x, y, modKeys, type);
- }
- } else {
- _root->invokePointerUp(x, y, modKeys, type);
- }
- Super::onMouseButtonRelease(x, y, button);
-}
-
-bool UIApp::onTextInput(const core::String& text) {
- if (_console.onTextInput(text)) {
- return true;
- }
- const char *c = text.c_str();
- for (;;) {
- const int key = core::utf8::next(&c);
- if (key == -1) {
- return true;
- }
- _root->invokeKey(key, tb::TB_KEY_UNDEFINED, tb::TB_MODIFIER_NONE, true);
- _root->invokeKey(key, tb::TB_KEY_UNDEFINED, tb::TB_MODIFIER_NONE, false);
- }
- return true;
-}
-
-bool UIApp::onKeyPress(int32_t key, int16_t modifier) {
- if (_console.onKeyPress(key, modifier)) {
- return true;
- }
-
- if (Super::onKeyPress(key, modifier)) {
- return true;
- }
-
- return invokeKey(mapKey(key), mapSpecialKey(key), mapModifier(key, modifier), true);
-}
-
-bool UIApp::onKeyRelease(int32_t key, int16_t modifier) {
- if (_console.isActive()) {
- return true;
- }
- Super::onKeyRelease(key, modifier);
- tb::MODIFIER_KEYS mod = mapModifier(0, modifier);
- mod |= mapModifier(key, 0);
- if (key == SDLK_MENU && tb::TBWidget::focused_widget) {
- tb::TBWidgetEvent ev(tb::EVENT_TYPE_CONTEXT_MENU, 0, 0, tb::TB_UNKNOWN, mod);
- if (tb::TBWidget::focused_widget->invokeEvent(ev)) {
- return true;
- }
- }
- return invokeKey(mapKey(key), mapSpecialKey(key), mod, false);
-}
-
-void UIApp::onWindowResize(int windowWidth, int windowHeight) {
- Super::onWindowResize(windowWidth, windowHeight);
- _renderer.onWindowResize(frameBufferDimension(), windowDimension());
- _root->setRect(tb::TBRect(0, 0, _frameBufferDimension.x, _frameBufferDimension.y));
-}
-
-app::AppState UIApp::onConstruct() {
- const app::AppState state = Super::onConstruct();
- command::Command::registerCommand("cl_ui_debug", [&] (const command::CmdArgs& args) {
-#ifdef DEBUG
- tb::ShowDebugInfoSettingsWindow(_root);
-#endif
- }).setHelp("Show ui debug information - only available in debug builds");
-
- _console.construct();
-
- return state;
-}
-
-void UIApp::onWidgetFocusChanged(tb::TBWidget *widget, bool focused) {
- if (focused && widget->isOfType()) {
- SDL_StartTextInput();
- } else {
- SDL_StopTextInput();
- }
-}
-
-void UIApp::afterRootWidget() {
- const math::Rect rect(0, 0, _frameBufferDimension.x, _frameBufferDimension.y);
- _console.render(rect, _deltaFrameSeconds);
-}
-
-app::AppState UIApp::onInit() {
- const app::AppState state = Super::onInit();
- video::checkError();
- if (state != app::AppState::Running) {
- return state;
- }
- if (!tb::tb_core_init(&_renderer)) {
- Log::error(_logId, "failed to initialize the ui");
- return app::AppState::InitFailure;
- }
-
- tb::TBWidgetListener::addGlobalListener(this);
- _uiInitialized = true;
-
- if (!tb::g_tb_lng->load("ui/lang/en.tb.txt")) {
- Log::warn(_logId, "could not load the translation ui/lang/en.tb.txt");
- }
-
- if (_applicationSkin.empty()) {
- const core::String skin = "ui/skin/" + _appname + "-skin.tb.txt";
- if (filesystem()->exists(skin)) {
- _applicationSkin = skin;
- }
- }
-
- tb::TBWidgetsAnimationManager::init();
-
- if (!tb::g_tb_skin->load("ui/skin/skin.tb.txt", _applicationSkin.empty() ? nullptr : _applicationSkin.c_str())) {
- Log::error(_logId, "could not load the skin at ui/skin/skin.tb.txt and/or %s",
- _applicationSkin.empty() ? "none" : _applicationSkin.c_str());
- return app::AppState::InitFailure;
- }
-
- if (!_renderer.init(frameBufferDimension(), windowDimension())) {
- Log::error(_logId, "could not init ui renderer");
- return app::AppState::InitFailure;
- }
-
- initFonts();
- tb::TBFontFace *font = getFont(_uiFontSize->intVal(), true);
- if (font == nullptr) {
- Log::error(_logId, "could not create the font face");
- return app::AppState::InitFailure;
- }
-
- _root = new tb::TBWidget();
- _root->setRect(tb::TBRect(0, 0, _frameBufferDimension.x, _frameBufferDimension.y));
- _root->setSkinBg(TBIDC("background"));
- _root->setGravity(tb::WIDGET_GRAVITY_ALL);
-
- _console.init();
-
- return state;
-}
-
-void UIApp::addChild(Window* window) {
- _root->addChild(window);
-}
-
-tb::TBWidget* UIApp::getWidget(const char *name) {
- return _root->getWidgetByID(tb::TBID(name));
-}
-
-tb::TBWidget* UIApp::getWidgetAt(int x, int y, bool includeChildren) {
- return _root->getWidgetAt(x, y, includeChildren);
-}
-
-void UIApp::beforeUI() {
- _console.update(_deltaFrameSeconds);
-
- _lastShowTextY = 5;
-
- if (!_console.isActive()) {
- static glm::ivec2 lastMousePos = _mousePos;
- if (lastMousePos != _mousePos) {
- _root->invokePointerMove(_mousePos.x, _mousePos.y, getModifierKeys(), tb::TB_UNKNOWN);
- lastMousePos = _mousePos;
- }
- }
-
- const bool renderUI = _renderUI->boolVal();
- if (renderUI) {
- core_trace_scoped(UIAppUpdateUI);
- tb::TBAnimationManager::update();
- _root->invokeProcessStates();
- _root->invokeProcess();
-
- _renderer.beginPaint(_frameBufferDimension.x, _frameBufferDimension.y);
- _root->invokePaint(tb::TBWidget::PaintProps());
- }
- {
- core_trace_scoped(UIAppAfterUI);
- afterRootWidget();
- }
- if (renderUI) {
- core_trace_scoped(UIAppEndPaint);
- _renderer.endPaint();
- // If animations are running, reinvalidate immediately
- if (tb::TBAnimationManager::hasAnimationsRunning()) {
- _root->invalidate();
- }
- }
- double next_fire_time = tb::TBMessageHandler::getNextMessageFireTime();
- double now = tb::TBSystem::getTimeMS();
- if (next_fire_time == TB_NOT_SOON || (next_fire_time - now) <= 1.0) {
- tb::TBMessageHandler::processMessages();
- }
-}
-
-app::AppState UIApp::onCleanup() {
- tb::TBAnimationManager::abortAllAnimations();
- if (_uiInitialized) {
- tb::TBWidgetListener::removeGlobalListener(this);
- tb::TBWidgetsAnimationManager::shutdown();
- _uiInitialized = false;
- }
-
- tb::tb_core_shutdown();
-
- Log::debug("shutdown ui widgets");
- if (_root != nullptr) {
- _root->die();
- }
- _root = nullptr;
-
- _console.shutdown();
-
- _renderer.shutdown();
-
- return Super::onCleanup();
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/UIApp.h b/src/modules/ui/turbobadger/UIApp.h
deleted file mode 100644
index 454720f1d..000000000
--- a/src/modules/ui/turbobadger/UIApp.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "ui/imgui/IMGUIApp.h"
-#include "Window.h"
-#include "Console.h"
-#include
-
-namespace ui {
-namespace turbobadger {
-
-/**
- * @ingroup UI
- */
-class UIApp: public ui::imgui::IMGUIApp, private tb::TBWidgetListener {
-private:
- using Super = ui::imgui::IMGUIApp;
-protected:
- static constexpr uint32_t _logId = Log::logid("UIAPP");
- tb::TBWidget* _root = nullptr;
- Console _console;
- int _lastShowTextY = -1;
- core::String _applicationSkin;
- bool _uiInitialized = false;
-
- virtual bool onKeyRelease(int32_t key, int16_t modifier) override;
- virtual bool onKeyPress(int32_t key, int16_t modifier) override;
- virtual bool onTextInput(const core::String& text) override;
- virtual bool onMouseWheel(int32_t x, int32_t y) override;
- virtual void onMouseButtonPress(int32_t x, int32_t y, uint8_t button, uint8_t clicks) override;
- virtual void onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) override;
-
- virtual void onWidgetFocusChanged(tb::TBWidget *widget, bool focused) override;
-
- bool invokeKey(int key, tb::SPECIAL_KEY special, tb::MODIFIER_KEYS mod, bool down);
- void showStr(int x, int y, const glm::vec4& color, CORE_FORMAT_STRING const char *fmt, ...) CORE_PRINTF_VARARG_FUNC(5);
- void enqueueShowStr(int x, const glm::vec4& color, CORE_FORMAT_STRING const char *fmt, ...) CORE_PRINTF_VARARG_FUNC(4);
-
- tb::MODIFIER_KEYS getModifierKeys() const;
-public:
- UIApp(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider, size_t threadPoolSize = 1);
- virtual ~UIApp();
-
- virtual void beforeUI() override;
-
- template
- T* getWidgetByType(const char *name);
-
- tb::TBWidget* getWidget(const char *name);
- tb::TBWidget* getWidgetAt(int x, int y, bool includeChildren = true);
-
- // hook that is called directory before the ui is rendered. Your last chance to let the app contribute
- // something in the ui context and the ui drawcalls (like debug text or rendering an in-game console on
- // top of the ui)
- virtual void afterRootWidget();
-
- void addChild(Window* window);
-
- /**
- * @param[in] filter png,jpg;psd The default filter is for png and jpg files. A second filter is available for psd files. There is a wildcard option in a dropdown.
- */
- void fileDialog(const std::function& callback, OpenFileMode mode, const core::String& filter) override;
-
- virtual void onRenderUI() override {}
-
- virtual void onWindowResize(int windowWidth, int windowHeight) override;
- virtual app::AppState onConstruct() override;
- virtual app::AppState onInit() override;
- virtual app::AppState onCleanup() override;
-};
-
-template
-inline T* UIApp::getWidgetByType(const char *name) {
- return _root->getWidgetByIDAndType(tb::TBID(name));
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/UIDummies.h b/src/modules/ui/turbobadger/UIDummies.h
deleted file mode 100644
index 4718ff1c4..000000000
--- a/src/modules/ui/turbobadger/UIDummies.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-class DummyBitmap: public tb::TBBitmap {
-public:
- bool init(int width, int height, uint32_t *data) {
- m_w = width;
- m_h = height;
- setData(data);
- return true;
- }
-
- virtual int width() override {
- return m_w;
- }
-
- virtual int height() override {
- return m_h;
- }
-
- virtual void setData(uint32_t *data) override {
- }
-public:
- int m_w = 0, m_h = 0;
-};
-
-class DummyRenderer: public tb::TBRendererBatcher {
-private:
- tb::TBRect _clipRect;
-public:
- void beginPaint(int, int) override {
- }
-
- void endPaint() override {
- }
-
- tb::TBBitmap *createBitmap(int width, int height, uint32_t* data) override {
- DummyBitmap *bitmap = new DummyBitmap();
- if (!bitmap || !bitmap->init(width, height, data)) {
- delete bitmap;
- return nullptr;
- }
- return bitmap;
- }
-
- void renderBatch(Batch*) override {
- }
-
- void setClipRect(const tb::TBRect&) override {
- }
-};
diff --git a/src/modules/ui/turbobadger/WaitingMessage.cpp b/src/modules/ui/turbobadger/WaitingMessage.cpp
deleted file mode 100644
index 8707f6035..000000000
--- a/src/modules/ui/turbobadger/WaitingMessage.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "WaitingMessage.h"
-#include "FontUtil.h"
-#include "core/ArrayLength.h"
-#include "UIApp.h"
-
-namespace ui {
-namespace turbobadger {
-
-WaitingMessage::WaitingMessage(UIApp* app) :
- _app(app) {
-}
-
-WaitingMessage::~WaitingMessage() {
- shutdown();
-}
-
-void WaitingMessage::setColor(const glm::vec4& color) {
- _color = tb::TBColor(color.r, color.g, color.b, color.a);
-}
-
-void WaitingMessage::init(int fontSize) {
- _font = getFont(fontSize);
-}
-
-void WaitingMessage::shutdown() {
- _font = nullptr;
-}
-
-void WaitingMessage::setTextId(const char *textId) {
- _translatedStr = tr(textId);
-}
-
-void WaitingMessage::reset() {
- _connectingStart = 0ul;
- _dotsIndex = 0;
-}
-
-void WaitingMessage::update(uint64_t deltaFrame) {
- _connectingStart += deltaFrame;
-}
-
-void WaitingMessage::render() {
- static const char *dotsArray[] = { ".", "..", "...", "....", "....." };
- if (_translatedStr == nullptr) {
- return;
- }
- if (_font == nullptr) {
- return;
- }
- if (_connectingStart >= 2000ul) {
- _dotsIndex = (_dotsIndex + 1) % lengthof(dotsArray);
- _connectingStart -= 2000ul;
- }
- const int y = _app->frameBufferHeight() / 2 - _font->getHeight() / 2;
- const int len = SDL_strlen(_translatedStr);
- const int w = _font->getStringWidth(_translatedStr, len);
- const int x = _app->frameBufferWidth() / 2 - w / 2;
- _font->drawString(x, y, _color, _translatedStr, len);
-
- const int dotX = x + w + 5;
- const char *dotsString = dotsArray[_dotsIndex];
- _font->drawString(dotX, y, _color, dotsString, SDL_strlen(dotsString));
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/WaitingMessage.h b/src/modules/ui/turbobadger/WaitingMessage.h
deleted file mode 100644
index b847907a1..000000000
--- a/src/modules/ui/turbobadger/WaitingMessage.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include "TurboBadger.h"
-#include "core/Color.h"
-
-namespace ui {
-namespace turbobadger {
-
-class UIApp;
-
-class WaitingMessage {
-private:
- UIApp* _app;
- tb::TBFontFace *_font = nullptr;
- tb::TBColor _color = {255, 255, 255, 255};
- const char* _translatedStr = nullptr;
- uint64_t _connectingStart = 0ul;
- int _dotsIndex = 0;
-public:
- WaitingMessage(UIApp* app);
- ~WaitingMessage();
-
- void init(int fontSize = 28);
- void shutdown();
-
- void setColor(const glm::vec4& color);
- /**
- * @param[in] textId The language identifier
- */
- void setTextId(const char *textId);
-
- void reset();
- void update(uint64_t deltaFrame);
- void render();
-};
-
-}
-}
diff --git a/src/modules/ui/turbobadger/Widget.h b/src/modules/ui/turbobadger/Widget.h
deleted file mode 100644
index 1b5e3b61e..000000000
--- a/src/modules/ui/turbobadger/Widget.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "TurboBadger.h"
-#include
-
-namespace ui {
-namespace turbobadger {
-
-class Widget : public tb::TBWidget {
-protected:
- inline bool isRelativeMouseMode() const {
- return SDL_GetRelativeMouseMode() == SDL_TRUE ? true : false;
- }
-
- inline bool isMiddleMouseButtonPressed() const {
- return SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(SDL_BUTTON_MIDDLE);
- }
-
- inline bool isRightMouseButtonPressed() const {
- return SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(SDL_BUTTON_RIGHT);
- }
-public:
- Widget() :
- tb::TBWidget() {
- }
-
- ~Widget() override {}
-};
-
-}
-}
diff --git a/src/modules/ui/turbobadger/Window.cpp b/src/modules/ui/turbobadger/Window.cpp
deleted file mode 100644
index 24e810b39..000000000
--- a/src/modules/ui/turbobadger/Window.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-/**
- * @file
- */
-
-#include "Window.h"
-#include "UIApp.h"
-#include "io/Filesystem.h"
-#include "core/GLM.h"
-#include "core/Singleton.h"
-#include "core/StringUtil.h"
-#include "core/Var.h"
-#include
-
-namespace ui {
-namespace turbobadger {
-
-static const core::String EMPTY = "";
-
-Window::Window(UIApp* app) :
- Super(), _app(app) {
- app->addChild(this);
- core::Singleton::getInstance().registerObserver(this);
-}
-
-Window::Window(Window* parent) :
- Super(), _app(parent == nullptr ? nullptr : parent->_app) {
- // if this is null, make sure to add the window on your own
- if (parent != nullptr) {
- parent->addChild(this);
- }
- core::Singleton::getInstance().registerObserver(this);
-}
-
-Window::~Window() {
- removeFromParent();
- core::Singleton::getInstance().removeObserver(this);
-}
-
-tb::TBGenericStringItem* Window::addStringItem(tb::TBGenericStringItemSource& items, const char *text, const char *id, bool translate) {
- tb::TBGenericStringItem* item;
- if (id == nullptr) {
- const core::String& lowerId = core::String::lower(text);
- item = new tb::TBGenericStringItem(translate ? tr(text) : text, TBIDC(lowerId.c_str()));
- const core::String& iconId = app::App::getInstance()->appname() + "-" + lowerId;
- item->setSkinImage(TBIDC(iconId.c_str()));
- } else {
- item = new tb::TBGenericStringItem(translate ? tr(text) : text, TBIDC(id));
- char buf[128];
- SDL_snprintf(buf, sizeof(buf), "%s-%s", app::App::getInstance()->appname().c_str(), id);
- item->setSkinImage(TBIDC(buf));
- }
- items.addItem(item);
- return item;
-}
-
-void Window::onDie() {
- Super::onDie();
- core::Singleton::getInstance().removeObserver(this);
-}
-
-bool Window::onEvent(const tb::TBWidgetEvent &ev) {
- return Super::onEvent(ev);
-}
-
-float Window::getFloat(const char *nodeId) {
- return core::string::toFloat(getStr(nodeId));
-}
-
-int Window::getSelectedId(const char *nodeId) {
- if (tb::TBSelectDropdown *select = getWidgetByIDAndType(TBIDC(nodeId))) {
- return select->getValue();
- }
- return -1;
-}
-
-int Window::getInt(const char *nodeId) {
- return core::string::toInt(getStr(nodeId));
-}
-
-Window* Window::getParent() const {
- return static_cast(Super::getParent());
-}
-
-UIApp* Window::getApp() const {
- if (_app) {
- return _app;
- }
- Window* parent = getParent();
- if (parent == nullptr) {
- return nullptr;
- }
- return parent->getApp();
-}
-
-void Window::fillWidgets(const Field* fields, int fieldAmount, void* basePtr) {
- for (int i = 0; i < fieldAmount; ++i) {
- const Field& field = fields[i];
- const tb::TBID& name = field.name;
- TBWidget *widget = getWidgetByID(name);
- if (widget == nullptr) {
- Log::warn("Could not find widget in window %s", getClassName());
- continue;
- }
- void* fieldPtr = (uint8_t*)basePtr + field.offset;
- switch (field.type) {
- case T_INT: {
- const core::String& str = core::string::format("%i", *(int*)fieldPtr);
- widget->setText(str.c_str());
- break;
- }
- case T_FLOAT: {
- const core::String& str = core::string::format("%f", *(float*)fieldPtr);
- widget->setText(str.c_str());
- break;
- }
- case T_IVEC2: {
- glm::ivec2* vec = (glm::ivec2*)fieldPtr;
- const core::String& str = core::string::format("%i:%i", vec->x, vec->y);
- widget->setText(str.c_str());
- break;
- }
- case T_VEC2: {
- glm::vec2* vec = (glm::vec2*)fieldPtr;
- const core::String& str = core::string::format("%f:%f", vec->x, vec->y);
- widget->setText(str.c_str());
- break;
- }
- }
- }
-}
-
-void Window::fillFields(const Field* fields, int fieldAmount, void* basePtr) {
- for (int i = 0; i < fieldAmount; ++i) {
- const Field& field = fields[i];
- const tb::TBID name(field.name);
- core::String str;
-
- tb::TBSelectList *list = getWidgetByIDAndType(name);
- if (list != nullptr) {
- const int value = list->getValue();
- tb::TBGenericStringItem* item = list->getDefaultSource()->getItem(value);
- if (field.type == T_INT) {
- const uint32_t id = item->id;
- str = core::string::format("%i", id);
- } else {
- str = item->str;
- }
- } else {
- TBWidget *widget = getWidgetByID(name);
- if (widget == nullptr) {
- Log::warn("Could not find widget with id %s in window %s", field.name, getClassName());
- continue;
- }
- str = widget->getText();
- }
- const char *string = str.c_str();
- void* fieldPtr = (uint8_t*)basePtr + field.offset;
- switch (field.type) {
- case T_INT: {
- const int value = core::string::toInt(string);
- Log::info("Set %i for %s (%s)", value, field.name, string);
- *(int*)fieldPtr = value;
- break;
- }
- case T_FLOAT: {
- const float value = core::string::toFloat(string);
- Log::info("Set %f for %s (%s)", value, field.name, string);
- *(float*)fieldPtr = value;
- break;
- }
- case T_IVEC2: {
- char buf[64];
- SDL_strlcpy(buf, string, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- char *sep = SDL_strchr(buf, ':');
- if (sep == nullptr) {
- break;
- }
- *sep++ = '\0';
- glm::ivec2* vec = (glm::ivec2*)fieldPtr;
- vec->x = core::string::toInt(string);
- vec->y = core::string::toInt(sep);
- break;
- }
- case T_VEC2: {
- char buf[64];
- SDL_strlcpy(buf, string, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- char *sep = SDL_strchr(buf, ':');
- if (sep == nullptr) {
- break;
- }
- *sep++ = '\0';
- glm::vec2* vec = (glm::vec2*)fieldPtr;
- vec->x = core::string::toFloat(string);
- vec->y = core::string::toFloat(sep);
- break;
- }
- }
- }
-}
-
-bool Window::loadResourceFile(const char *filename) {
- _filename = filename;
- tb::TBNode node;
- const io::FilesystemPtr& filesystem = io::filesystem();
- const io::FilePtr& file = filesystem->open(filename);
- if (!file->exists()) {
- Log::error("%s doesn't exists", filename);
- return false;
- }
- const core::String& data = file->load();
- if (!node.readData(data.c_str(), (int)data.size(), tb::TB_NODE_READ_FLAGS_NONE)) {
- return false;
- }
- return loadResource(node);
-}
-
-void Window::popup(const core::String& title, const core::String& str, PopupType type, const char *id) {
- tb::TBMessageWindow *win = new tb::TBMessageWindow(this, TBIDC(id));
- tb::TBMessageWindowSettings settings((tb::TB_MSG)core::enumVal(type), tb::TBID(0u));
- settings.dimmer = true;
- win->show(title.c_str(), str.c_str(), &settings);
-}
-
-void Window::setStr(const char *nodeId, const core::String& text) {
- tb::TBEditField *widget = getWidgetByType(nodeId);
- if (widget == nullptr) {
- Log::info("could not find an edit field node with the name %s", nodeId);
- return;
- }
- widget->setText(text.c_str());
-}
-
-void Window::toggleViaVar(const char *checkBoxNodeId, const core::VarPtr& var) {
- toggle(checkBoxNodeId, var->boolVal());
-}
-
-void Window::toggle(const char *checkBoxNodeId, bool state) {
- tb::TBCheckBox *widget = getWidgetByIDAndType(checkBoxNodeId);
- if (widget == nullptr) {
- Log::info("could not find a checkbox node with the name %s", checkBoxNodeId);
- return;
- }
- return widget->setValue(state ? 1 : 0);
-}
-
-bool Window::isToggled(const char *checkBoxNodeId) {
- tb::TBCheckBox *widget = getWidgetByIDAndType(checkBoxNodeId);
- if (widget == nullptr) {
- Log::info("could not find a checkbox node with the name %s", checkBoxNodeId);
- return false;
- }
- return widget->getValue() == 1;
-}
-
-core::String Window::getStr(const char *nodeId) {
- tb::TBWidget *widget = getWidgetByID(nodeId);
- if (widget == nullptr) {
- Log::info("could not find a node with the name %s", nodeId);
- return EMPTY;
- }
- const core::String& amplitude = widget->getText();
- return core::String(amplitude.c_str());
-}
-
-bool Window::loadResourceData(const char *data) {
- tb::TBNode node;
- if (!node.readData(data)) {
- return false;
- }
- return loadResource(node);
-}
-
-static void printNodeTree(const core::String& filename, tb::TBNode &node) {
- for (tb::TBNode *child = node.getFirstChild(); child; child = child->getNext()) {
- Log::trace("File: %s: node found: '%s' = '%s'", filename.c_str(), child->getName(), child->getValue().getString());
- printNodeTree(filename, *child);
- }
-}
-
-bool Window::loadResource(tb::TBNode &node) {
- printNodeTree(_filename, node);
-
- tb::g_widgets_reader->loadNodeTree(this, &node);
-
- // Get title from the WindowInfo section (or use "" if not specified)
- setText(node.getValueString("WindowInfo>title", ""));
-
- tb::TBWidget *parent = getParent();
- if (parent == nullptr) {
- return false;
- }
- const tb::TBRect& r = parent->getRect();
- const tb::TBRect parentRect(0, 0, r.w, r.h);
- const tb::TBDimensionConverter *dc = tb::g_tb_skin->getDimensionConverter();
- tb::TBRect windowRect = getResizeToFitContentRect();
-
- // Use specified size or adapt to the preferred content size.
- tb::TBNode *tmp = node.getNode("WindowInfo>size");
- if (tmp && tmp->getValue().getArrayLength() == 2) {
- tb::TBValueArray *dimensions = tmp->getValue().getArray();
- const char *sizeW = dimensions->getValue(0)->getString();
- if (sizeW[SDL_strlen(sizeW) - 1] == '%') {
- _percentWidth = SDL_atof(sizeW);
- windowRect.w = _app->frameBufferWidth() * _percentWidth / 100.0f;
- } else {
- windowRect.w = dc->getPxFromString(sizeW, windowRect.w);
- }
- const char *sizeH = dimensions->getValue(1)->getString();
- if (sizeH[SDL_strlen(sizeH) - 1] == '%') {
- _percentHeight = SDL_atof(sizeW);
- windowRect.h = _app->frameBufferHeight() * _percentHeight / 100.0f;
- } else {
- windowRect.h = dc->getPxFromString(sizeH, windowRect.h);
- }
- }
-
- // Use the specified position or center in parent.
- tmp = node.getNode("WindowInfo>position");
- if (tmp && tmp->getValue().getArrayLength() == 2) {
- tb::TBValueArray *position = tmp->getValue().getArray();
- const char *posW = position->getValue(0)->getString();
- const char *posH = position->getValue(1)->getString();
- windowRect.x = dc->getPxFromString(posW, windowRect.x);
- windowRect.y = dc->getPxFromString(posH, windowRect.y);
- } else {
- windowRect = windowRect.centerIn(parentRect);
- }
-
- if (tb::TBNode *fullscreen = node.getNode("WindowInfo>fullscreen")) {
- const int fullscreenVal = fullscreen->getValue().getInt();
- if (fullscreenVal != 0) {
- windowRect.x = 0;
- windowRect.y = 0;
- if (_app != nullptr) {
- windowRect.w = _app->frameBufferWidth();
- windowRect.h = _app->frameBufferHeight();
- } else {
- TBWidget *parent = getParent();
- if (parent != nullptr) {
- windowRect.w = parent->getPreferredSize().pref_w;
- windowRect.h = parent->getPreferredSize().pref_h;
- }
- }
- }
- }
-
- // Make sure the window is inside the parent, and not larger.
- windowRect = windowRect.moveIn(parentRect).clip(parentRect);
-
- setRect(windowRect);
-
- // Ensure we have focus - now that we've filled the window with possible focusable
- // widgets. EnsureFocus was automatically called when the window was activated (by
- // adding the window to the root), but then we had nothing to focus.
- // Alternatively, we could add the window after setting it up properly.
- ensureFocus();
- return true;
-}
-
-void Window::onWindowResize(int, int) {
- const tb::TBRect parentRect(0, 0, getParent()->getRect().w, getParent()->getRect().h);
- tb::TBRect windowRect = getRect();
- windowRect = windowRect.moveIn(parentRect).clip(parentRect);
- if (_percentHeight > 0.0f) {
- windowRect.w = _app->frameBufferWidth() * _percentWidth;
- }
- if (_percentHeight > 0.0f) {
- windowRect.h = _app->frameBufferHeight() * _percentHeight;
- }
- setRect(windowRect);
-}
-
-tb::TBWidget* Window::getWidget(const char *name) {
- return getWidgetByID(tb::TBID(name));
-}
-
-bool Window::setActive(const char *name, bool active) {
- tb::TBWidget* widget = getWidget(name);
- if (widget == nullptr) {
- return false;
- }
-
- widget->setState(tb::WIDGET_STATE_DISABLED, !active);
- return true;
-}
-
-bool Window::setVisible(const char *name, bool visible) {
- tb::TBWidget* widget = getWidget(name);
- if (widget == nullptr) {
- return false;
- }
-
- if (visible) {
- widget->setVisibility(tb::WIDGET_VISIBILITY_GONE);
- } else {
- widget->setVisibility(tb::WIDGET_VISIBILITY_VISIBLE);
- }
- return true;
-}
-
-void Window::requestQuit() {
- app::App::getInstance()->requestQuit();
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/Window.h b/src/modules/ui/turbobadger/Window.h
deleted file mode 100644
index c44ea894c..000000000
--- a/src/modules/ui/turbobadger/Window.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "TurboBadger.h"
-#include "video/IEventObserver.h"
-#include
-#include "core/SharedPtr.h"
-
-namespace core {
-class Var;
-typedef core::SharedPtr VarPtr;
-}
-
-namespace ui {
-namespace turbobadger {
-
-class UIApp;
-
-#define FIELD(name, type, structtarget, structmember) name, type, offsetof(structtarget, structmember)
-#define INT_FIELD(name, structtarget, structmember) FIELD(name, ui::turbobadger::Window::T_INT, structtarget, structmember)
-#define FLOAT_FIELD(name, structtarget, structmember) FIELD(name, ui::turbobadger::Window::T_FLOAT, structtarget, structmember)
-#define IVEC2_FIELD(name, structtarget, structmember) FIELD(name, ui::turbobadger::Window::T_IVEC2, structtarget, structmember)
-#define VEC2_FIELD(name, structtarget, structmember) FIELD(name, ui::turbobadger::Window::T_VEC2, structtarget, structmember)
-#define tr(id) ui::turbobadger::Window::getTranslation(id)
-
-class Window: public tb::TBWindow, public io::IEventObserver {
-private:
- UIApp* _app;
-protected:
- using Super = tb::TBWindow;
- float _percentWidth = 0.0f;
- float _percentHeight = 0.0f;
- core::String _filename;
-
- tb::TBGenericStringItem* addStringItem(tb::TBGenericStringItemSource& items, const char *text, const char *id = nullptr, bool translate = true);
-
-public:
- static inline const char *getTranslation(const char *input) {
- const char *str = tb::g_tb_lng->getString(tb::TBID(input));
- if (!SDL_strncmp(str, "
- T* getWidgetByType(const char *name);
-
- tb::TBWidget* getWidget(const char *name);
- bool setVisible(const char *name, bool visible);
- bool setActive(const char *name, bool active);
- void setStr(const char *nodeId, const core::String& text);
-
- virtual void onDie() override;
- virtual bool onEvent(const tb::TBWidgetEvent &ev) override;
-
- virtual void onWindowResize(int windowWidth, int windowHeight) override;
-};
-
-template
-inline T* Window::getWidgetByType(const char *name) {
- return getWidgetByIDAndType(tb::TBID(name));
-}
-
-}
-}
diff --git a/src/modules/ui/turbobadger/tb/LICENSE b/src/modules/ui/turbobadger/tb/LICENSE
deleted file mode 100644
index 0e5a955a0..000000000
--- a/src/modules/ui/turbobadger/tb/LICENSE
+++ /dev/null
@@ -1,28 +0,0 @@
-The whole source code in this directory based on the original work of
-Emil Segerås. But was modified to integrate better into the engine.
-
-License
-
-Turbo Badger
-Copyright (C) 2011-2014 Emil Segerås
-
-License:
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software
-in a product, an acknowledgment in the product documentation would be
-appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
diff --git a/src/modules/ui/turbobadger/tb/animation/tb_animation.cpp b/src/modules/ui/turbobadger/tb/animation/tb_animation.cpp
deleted file mode 100644
index 76ca41f6b..000000000
--- a/src/modules/ui/turbobadger/tb/animation/tb_animation.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/**
- * @file
- */
-
-#include "animation/tb_animation.h"
-#include "core/Assert.h"
-#include "core/Trace.h"
-#include "tb_system.h"
-
-namespace tb {
-
-#define SMOOTHSTEP(x) ((x) * (x) * (3.0f - 2.0f * (x)))
-
-static float sc(float x) {
- float s = x < 0 ? -1.F : 1.F;
- x = Abs(x);
- if (x >= 1) {
- return s;
- }
- return s * (x < 0 ? x / 0.5F : (x / (1 + x * x)) / 0.5F);
-}
-
-static float smoothCurve(float x, float a) {
- float r = a * x / (2 * a * x - a - x + 1);
- r = (r - 0.5F) * 2;
- return sc(r) * 0.5F + 0.5F;
-}
-
-void TBAnimationObject::invokeOnAnimationStart() {
- TBLinkListOf::Iterator li = m_listeners.iterateForward();
- onAnimationStart();
- while (TBAnimationListener *listener = li.getAndStep())
- listener->onAnimationStart(this);
-}
-
-void TBAnimationObject::invokeOnAnimationUpdate(float progress) {
- TBLinkListOf::Iterator li = m_listeners.iterateForward();
- onAnimationUpdate(progress);
- while (TBAnimationListener *listener = li.getAndStep())
- listener->onAnimationUpdate(this, progress);
-}
-
-void TBAnimationObject::invokeOnAnimationStop(bool aborted) {
- TBLinkListOf::Iterator li = m_listeners.iterateForward();
- onAnimationStop(aborted);
- while (TBAnimationListener *listener = li.getAndStep())
- listener->onAnimationStop(this, aborted);
-}
-
-TBLinkListOf TBAnimationManager::animating_objects;
-static int block_animations_counter = 0;
-
-// static
-void TBAnimationManager::abortAllAnimations() {
- while (TBAnimationObject *obj = animating_objects.getFirst())
- abortAnimation(obj, true);
-}
-
-// static
-void TBAnimationManager::update() {
- core_trace_scoped(AnimationManagerUpdate);
- double time_now = TBSystem::getTimeMS();
-
- TBLinkListOf::Iterator iter = animating_objects.iterateForward();
- while (TBAnimationObject *obj = iter.getAndStep()) {
- // Adjust the start time if it's the first update time for this object.
- if (obj->adjust_start_time) {
- obj->animation_start_time = time_now;
- obj->adjust_start_time = false;
- }
-
- // Calculate current progress
- // If animation_duration is 0, it should just complete immediately.
- float progress = 1.0f;
- if (obj->animation_duration != 0) {
- progress = (float)(time_now - obj->animation_start_time) / (float)obj->animation_duration;
- progress = Min(progress, 1.0f);
- }
-
- // Apply animation curve
- float tmp;
- switch (obj->animation_curve) {
- case ANIMATION_CURVE_SLOW_DOWN:
- tmp = 1 - progress;
- progress = 1 - tmp * tmp * tmp;
- break;
- case ANIMATION_CURVE_SPEED_UP:
- progress = progress * progress * progress;
- break;
- case ANIMATION_CURVE_BEZIER:
- progress = SMOOTHSTEP(progress);
- break;
- case ANIMATION_CURVE_SMOOTH:
- progress = smoothCurve(progress, 0.6f);
- break;
- default: // linear (progress is already linear)
- break;
- }
-
- // Update animation
- obj->invokeOnAnimationUpdate(progress);
-
- // Remove completed animations
- if (progress == 1.0f) {
- animating_objects.remove(obj);
- obj->invokeOnAnimationStop(false);
- delete obj;
- }
- }
-}
-
-// static
-bool TBAnimationManager::hasAnimationsRunning() {
- return animating_objects.hasLinks();
-}
-
-// static
-void TBAnimationManager::startAnimation(TBAnimationObject *obj, ANIMATION_CURVE animationCurve,
- double animationDuration, ANIMATION_TIME animationTime) {
- if (obj->isAnimating())
- abortAnimation(obj, false);
- if (isAnimationsBlocked())
- animationDuration = 0;
- obj->adjust_start_time = (animationTime == ANIMATION_TIME_FIRST_UPDATE ? true : false);
- obj->animation_start_time = TBSystem::getTimeMS();
- obj->animation_duration = Max(animationDuration, 0.0);
- obj->animation_curve = animationCurve;
- animating_objects.addLast(obj);
- obj->invokeOnAnimationStart();
-}
-
-// static
-void TBAnimationManager::abortAnimation(TBAnimationObject *obj, bool deleteAnimation) {
- if (obj->isAnimating()) {
- animating_objects.remove(obj);
- obj->invokeOnAnimationStop(true);
- if (deleteAnimation)
- delete obj;
- }
-}
-
-// static
-bool TBAnimationManager::isAnimationsBlocked() {
- return block_animations_counter > 0;
-}
-
-// static
-void TBAnimationManager::beginBlockAnimations() {
- block_animations_counter++;
-}
-
-// static
-void TBAnimationManager::endBlockAnimations() {
- core_assert(block_animations_counter > 0);
- block_animations_counter--;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/animation/tb_animation.h b/src/modules/ui/turbobadger/tb/animation/tb_animation.h
deleted file mode 100644
index e08e26bba..000000000
--- a/src/modules/ui/turbobadger/tb/animation/tb_animation.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_linklist.h"
-#include "tb_object.h"
-
-namespace tb {
-
-class TBAnimationObject;
-
-/** Defines how the animation progress value is interpolated. */
-enum ANIMATION_CURVE {
- ANIMATION_CURVE_LINEAR, ///< Linear
- ANIMATION_CURVE_SLOW_DOWN, ///< Fast start, slow end
- ANIMATION_CURVE_SPEED_UP, ///< Slow start, fast end
- ANIMATION_CURVE_BEZIER, ///< Slow start, slow end. Almost linear.
- ANIMATION_CURVE_SMOOTH ///< Slow start, slow end. Stronger than ANIMATION_CURVE_BEZIER.
-};
-
-/** Defines what the animation duration time is relative to. */
-enum ANIMATION_TIME {
-
- /** The start time begins when the animation start in TBAnimationManager::startAnimation. */
- ANIMATION_TIME_IMMEDIATELY,
-
- /** The animation start in StartAnimation just as with ANIMATION_TIME_IMMEDIATELY,
- but the start time is adjusted to when the animations Update is about to be called
- the first time since it was started.
-
- Using this is most often preferable since starting a animation is often accompanied
- with some extra work that might eat up a considerable time of the total duration (and
- chop of the beginning of it).
-
- F.ex: Creating a window and starting its appearance animation. During initialization
- of the window, you might initiate loading of additional resources. When that is done
- and you finally end up updating animations, most of the animation time might already
- have passed. If the animation start time is adjusted to the first update, the whole
- animation will run from 0.0 - 1.0 smoothly when the initialization is done. */
- ANIMATION_TIME_FIRST_UPDATE
-};
-
-#define ANIMATION_DEFAULT_CURVE ANIMATION_CURVE_SLOW_DOWN
-#define ANIMATION_DEFAULT_DURATION 200
-
-/** TBAnimationListener - Listens to the progress of TBAnimationObject. */
-
-class TBAnimationListener : public TBLinkOf {
-public:
- virtual ~TBAnimationListener(){};
-
- /** Called after the animation object handled its own OnAnimationStart.
- See TBAnimationObject::onAnimationStart for details. */
- virtual void onAnimationStart(TBAnimationObject *obj) = 0;
-
- /** Called after the animation object handled its own OnAnimationStart.
- See TBAnimationObject::onAnimationUpdate for details. */
- virtual void onAnimationUpdate(TBAnimationObject *obj, float progress) = 0;
-
- /** Called after the animation object handled its own OnAnimationStart.
- See TBAnimationObject::onAnimationStop for details. */
- virtual void onAnimationStop(TBAnimationObject *obj, bool aborted) = 0;
-};
-
-/** TBAnimationObject - Base class for all animated object */
-
-class TBAnimationObject : public TBTypedObject, public TBLinkOf {
-public:
- ANIMATION_CURVE animation_curve;
- double animation_start_time;
- double animation_duration;
- bool adjust_start_time;
-
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBAnimationObject, TBTypedObject);
-
- virtual ~TBAnimationObject() {
- }
-
- /** Return true if the object is currently animating. */
- bool isAnimating() const {
- return linklist ? true : false;
- }
-
- /** Called on animation start */
- virtual void onAnimationStart() = 0;
-
- /** Called on animation update. progress is current progress from 0 to 1.
- Note that it isn't called on start, so progress 0 might not happen.
- It will be called with progress 1 before the animation is completed normally (not aborted) */
- virtual void onAnimationUpdate(float progress) = 0;
-
- /** Called on animation stop. aborted is true if it was aborted before completion.
- Note that if a animation is started when it's already running, it will first
- be aborted and then started again. */
- virtual void onAnimationStop(bool aborted) = 0;
-
- /** Add an listener to this animation object. */
- void addListener(TBAnimationListener *listener) {
- m_listeners.addLast(listener);
- }
-
- /** Remove an listener from this animation object. */
- void removeListener(TBAnimationListener *listener) {
- m_listeners.remove(listener);
- }
-
-private:
- friend class TBAnimationManager;
- TBLinkListOf m_listeners;
- void invokeOnAnimationStart();
- void invokeOnAnimationUpdate(float progress);
- void invokeOnAnimationStop(bool aborted);
-};
-
-/** TBAnimationManager - System class that manages all animated object */
-
-class TBAnimationManager {
-private:
- static TBLinkListOf animating_objects;
-
-public:
- /** Update all running animations. */
- static void update();
-
- /** Return true if there are running animations. */
- static bool hasAnimationsRunning();
-
- static void startAnimation(TBAnimationObject *obj, ANIMATION_CURVE animation_curve = ANIMATION_DEFAULT_CURVE,
- double animation_duration = ANIMATION_DEFAULT_DURATION,
- ANIMATION_TIME animation_time = ANIMATION_TIME_FIRST_UPDATE);
- /** Abort the animation. If delete_animation is true, the animation will be deleted in
- this call after running callbacks and listeners callbacks. In rare situations,
- you might want to keep the animation around and delete it later (or start it
- again). */
- static void abortAnimation(TBAnimationObject *obj, bool delete_animation);
-
- /** Abort and delete all animations. */
- static void abortAllAnimations();
-
- /** Return true if new animations are blocked. */
- static bool isAnimationsBlocked();
-
- /** Begin a period of blocking new animations. End the period with EndBlockAnimations.
- If StartAnimation is called during the blocked period, the animation object will
- finish the next animation update as it completed normally. */
- static void beginBlockAnimations();
-
- /** End a period of blocking new animations that was started with BeginBlockAnimations. */
- static void endBlockAnimations();
-};
-
-/** TBAnimationBlocker blocks new animations during its lifetime.
- It's convenient to put on the stack to block new animations
- within a scope of code. */
-class TBAnimationBlocker {
-public:
- TBAnimationBlocker() {
- TBAnimationManager::beginBlockAnimations();
- }
- ~TBAnimationBlocker() {
- TBAnimationManager::endBlockAnimations();
- }
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/animation/tb_animation_utils.h b/src/modules/ui/turbobadger/tb/animation/tb_animation_utils.h
deleted file mode 100644
index 4233a290f..000000000
--- a/src/modules/ui/turbobadger/tb/animation/tb_animation_utils.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "animation/tb_animation.h"
-
-namespace tb {
-
-// TBAnimatedFloat - A animated float value
-
-class TBAnimatedFloat : public TBAnimationObject {
-public:
- float src_val;
- float dst_val;
- float current_progress;
-
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBAnimatedFloat, TBAnimationObject);
-
- TBAnimatedFloat(float initial_value, ANIMATION_CURVE animation_curve = ANIMATION_DEFAULT_CURVE,
- double animation_duration = ANIMATION_DEFAULT_DURATION)
- : src_val(initial_value), dst_val(initial_value), current_progress(0) {
- TBAnimationObject::animation_curve = animation_curve;
- TBAnimationObject::animation_duration = animation_duration;
- }
- virtual ~TBAnimatedFloat() {}
-
- float getValue() const {
- return src_val + (dst_val - src_val) * current_progress;
- }
- void setValueAnimated(float value) {
- src_val = getValue();
- dst_val = value;
- TBAnimationManager::startAnimation(this, animation_curve, animation_duration);
- }
- void setValueImmediately(float value) {
- TBAnimationManager::abortAnimation(this, false);
- src_val = dst_val = value;
- onAnimationUpdate(1.0f);
- }
-
- virtual void onAnimationStart() {
- current_progress = 0;
- }
- virtual void onAnimationUpdate(float progress) {
- current_progress = progress;
- }
- virtual void onAnimationStop(bool aborted) {
- }
-};
-
-// TBFloatAnimator - Animates a external float value, which address is given in the constructor.
-
-class TBFloatAnimator : public TBAnimatedFloat {
-public:
- float *target_value;
-
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBFloatAnimator, TBAnimationObject);
-
- TBFloatAnimator(float *target_value, ANIMATION_CURVE animation_curve = ANIMATION_DEFAULT_CURVE,
- double animation_duration = ANIMATION_DEFAULT_DURATION)
- : TBAnimatedFloat(*target_value), target_value(target_value) {
- }
-
- virtual void onAnimationStart() {
- TBAnimatedFloat::onAnimationStart();
- *target_value = getValue();
- }
- virtual void onAnimationUpdate(float progress) {
- TBAnimatedFloat::onAnimationUpdate(progress);
- *target_value = getValue();
- }
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/animation/tb_widget_animation.cpp b/src/modules/ui/turbobadger/tb/animation/tb_widget_animation.cpp
deleted file mode 100644
index 4f512055e..000000000
--- a/src/modules/ui/turbobadger/tb/animation/tb_widget_animation.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/**
- * @file
- */
-
-#include "animation/tb_widget_animation.h"
-#include "tb_list.h"
-#include "tb_message_window.h"
-#include "tb_widgets.h"
-#include "tb_widgets_common.h"
-#include "tb_window.h"
-
-namespace tb {
-
-TBLinkListOf widget_animations;
-
-#define LERP(src, dst, progress) (src + (dst - src) * progress)
-
-TBWidgetAnimationObject::TBWidgetAnimationObject(TBWidget *widget) : m_widget(widget) {
- widget_animations.addLast(this);
-}
-
-TBWidgetAnimationObject::~TBWidgetAnimationObject() {
- widget_animations.remove(this);
-}
-
-// == TBWidgetAnimationOpacity ============================================================
-
-TBWidgetAnimationOpacity::TBWidgetAnimationOpacity(TBWidget *widget, float srcOpacity, float dstOpacity, bool die)
- : TBWidgetAnimationObject(widget), m_src_opacity(srcOpacity), m_dst_opacity(dstOpacity), m_die(die) {
-}
-
-void TBWidgetAnimationOpacity::onAnimationStart() {
- // Make sure we don't stay idle if nothing is scheduled (hack).
- // FIX: fix this properly
- m_widget->invalidate();
-
- m_widget->setOpacity(m_src_opacity);
-}
-
-void TBWidgetAnimationOpacity::onAnimationUpdate(float progress) {
- m_widget->setOpacity(LERP(m_src_opacity, m_dst_opacity, progress));
-}
-
-void TBWidgetAnimationOpacity::onAnimationStop(bool aborted) {
- // If we're aborted, it may be because the widget is being deleted
- if (m_die && !aborted) {
- TBWidgetSafePointer the_widget(m_widget);
- m_widget->removeFromParent();
- if (the_widget.get())
- delete the_widget.get();
- } else
- m_widget->setOpacity(m_dst_opacity);
-}
-
-TBWidgetAnimationRect::TBWidgetAnimationRect(TBWidget *widget, const TBRect &srcRect, const TBRect &dstRect)
- : TBWidgetAnimationObject(widget), m_src_rect(srcRect), m_dst_rect(dstRect), m_mode(MODE_SRC_TO_DST) {
-}
-
-TBWidgetAnimationRect::TBWidgetAnimationRect(TBWidget *widget, const TBRect &deltaRect, MODE mode)
- : TBWidgetAnimationObject(widget), m_delta_rect(deltaRect), m_mode(mode) {
- core_assert(mode == MODE_DELTA_IN || mode == MODE_DELTA_OUT);
-}
-
-void TBWidgetAnimationRect::onAnimationStart() {
- // Make sure we don't stay idle if nothing is scheduled (hack).
- // FIX: fix this properly
- m_widget->invalidate();
-
- if (m_mode == MODE_SRC_TO_DST)
- m_widget->setRect(m_src_rect);
-}
-
-void TBWidgetAnimationRect::onAnimationUpdate(float progress) {
- if (m_mode == MODE_DELTA_IN || m_mode == MODE_DELTA_OUT) {
- m_dst_rect = m_src_rect = m_widget->getRect();
- if (m_dst_rect.equals(TBRect())) {
- // Widget hasn't been laid out yet,
- // the animation was started too soon.
- //! \TODO this is certainly a BUG because it can be called from within the
- // TBAnimationManager::update() loop which ALSO deletes the animation objevt.
- TBAnimationManager::abortAnimation(this, true);
- return;
- }
- if (m_mode == MODE_DELTA_IN) {
- m_dst_rect.x += m_delta_rect.x;
- m_dst_rect.y += m_delta_rect.y;
- m_dst_rect.w += m_delta_rect.w;
- m_dst_rect.h += m_delta_rect.h;
- } else {
- m_src_rect.x += m_delta_rect.x;
- m_src_rect.y += m_delta_rect.y;
- m_src_rect.w += m_delta_rect.w;
- m_src_rect.h += m_delta_rect.h;
- }
- m_mode = MODE_SRC_TO_DST;
- }
- TBRect rect;
- rect.x = (int)LERP(m_src_rect.x, m_dst_rect.x, progress);
- rect.y = (int)LERP(m_src_rect.y, m_dst_rect.y, progress);
- rect.w = (int)LERP(m_src_rect.w, m_dst_rect.w, progress);
- rect.h = (int)LERP(m_src_rect.h, m_dst_rect.h, progress);
- m_widget->setRect(rect);
-}
-
-void TBWidgetAnimationRect::onAnimationStop(bool aborted) {
- if (m_mode == MODE_SRC_TO_DST) // m_dst_rect may still be unset if aborted.
- m_widget->setRect(m_dst_rect);
-}
-
-// == TBWidgetsAnimationManager =====================================================
-
-TBWidgetsAnimationManager widgets_animation_manager;
-
-void TBWidgetsAnimationManager::init() {
- TBWidgetListener::addGlobalListener(&widgets_animation_manager);
-}
-
-void TBWidgetsAnimationManager::shutdown() {
- TBWidgetListener::removeGlobalListener(&widgets_animation_manager);
-}
-
-void TBWidgetsAnimationManager::abortAnimations(TBWidget *widget) {
- abortAnimations(widget, nullptr);
-}
-
-void TBWidgetsAnimationManager::abortAnimations(TBWidget *widget, TB_TYPE_ID typeId) {
- TBLinkListOf::Iterator iter = widget_animations.iterateForward();
- while (TBWidgetAnimationObject *wao = iter.getAndStep()) {
- if (wao->m_widget == widget) {
- // Skip this animation if we asked for a specific (and
- // different) animation type.
- if (typeId != nullptr && !wao->isOfTypeId(typeId))
- continue;
-
- // Abort the animation. This will both autoremove itself
- // and delete it, so no need to do it here.
- TBAnimationManager::abortAnimation(wao, true);
- }
- }
-}
-
-void TBWidgetsAnimationManager::onWidgetDelete(TBWidget *widget) {
- // Kill and delete all animations running for the widget being deleted.
- abortAnimations(widget);
-}
-
-bool TBWidgetsAnimationManager::onWidgetDying(TBWidget *widget) {
- bool handled = false;
- if (TBWindow *window = TBSafeCast(widget)) {
- // Fade out dying windows
- if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(window, 1.f, TB_ALMOST_ZERO_OPACITY, true))
- TBAnimationManager::startAnimation(anim, ANIMATION_CURVE_BEZIER);
- handled = true;
- }
- if (TBMessageWindow *window = TBSafeCast(widget)) {
- // Move out dying message windows
- if (TBAnimationObject *anim =
- new TBWidgetAnimationRect(window, TBRect(0, 50, 0, 0), TBWidgetAnimationRect::MODE_DELTA_IN))
- TBAnimationManager::startAnimation(anim, ANIMATION_CURVE_SPEED_UP);
- handled = true;
- }
- if (TBDimmer *dimmer = TBSafeCast(widget)) {
- // Fade out dying dim layers
- if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(dimmer, 1.f, TB_ALMOST_ZERO_OPACITY, true))
- TBAnimationManager::startAnimation(anim, ANIMATION_CURVE_BEZIER);
- handled = true;
- }
- return handled;
-}
-
-void TBWidgetsAnimationManager::onWidgetAdded(TBWidget *parent, TBWidget *widget) {
- if (TBWindow *window = TBSafeCast(widget)) {
- // Fade in new windows
- if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(window, TB_ALMOST_ZERO_OPACITY, 1.f, false))
- TBAnimationManager::startAnimation(anim, ANIMATION_CURVE_BEZIER);
- }
- if (TBMessageWindow *window = TBSafeCast(widget)) {
- // Move in new message windows
- if (TBAnimationObject *anim =
- new TBWidgetAnimationRect(window, TBRect(0, -50, 0, 0), TBWidgetAnimationRect::MODE_DELTA_OUT))
- TBAnimationManager::startAnimation(anim);
- }
- if (TBDimmer *dimmer = TBSafeCast(widget)) {
- // Fade in dim layer
- if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(dimmer, TB_ALMOST_ZERO_OPACITY, 1.f, false))
- TBAnimationManager::startAnimation(anim, ANIMATION_CURVE_BEZIER);
- }
-}
-
-void TBWidgetsAnimationManager::onWidgetRemove(TBWidget *parent, TBWidget *widget) {
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/animation/tb_widget_animation.h b/src/modules/ui/turbobadger/tb/animation/tb_widget_animation.h
deleted file mode 100644
index e7c9e54ee..000000000
--- a/src/modules/ui/turbobadger/tb/animation/tb_widget_animation.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "animation/tb_animation.h"
-#include "tb_widgets_listener.h"
-
-namespace tb {
-
-/** Don't use 0.0 for opacity animations since that may break focus code.
- At the moment a window should appear and start fading in from opacity 0,
- it would also attempt setting the focus to it, but if opacity is 0 it will
- think focus should not be set in that window and fail. */
-#define TB_ALMOST_ZERO_OPACITY 0.001f
-
-/** Base class for widget animations. This animation object will
- be deleted automatically if the widget is deleted. */
-class TBWidgetAnimationObject : public TBAnimationObject, public TBLinkOf {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBWidgetAnimationObject, TBAnimationObject);
-
- TBWidgetAnimationObject(TBWidget *widget);
- virtual ~TBWidgetAnimationObject();
-
-public:
- TBWidget *m_widget;
-};
-
-/** Animate the opacity of the target widget. */
-class TBWidgetAnimationOpacity : public TBWidgetAnimationObject {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBWidgetAnimationOpacity, TBWidgetAnimationObject);
-
- TBWidgetAnimationOpacity(TBWidget *widget, float src_opacity, float dst_opacity, bool die);
- virtual void onAnimationStart() override;
- virtual void onAnimationUpdate(float progress) override;
- virtual void onAnimationStop(bool aborted) override;
-
-private:
- float m_src_opacity;
- float m_dst_opacity;
- bool m_die;
-};
-
-/** Animate the rectangle of the target widget. */
-class TBWidgetAnimationRect : public TBWidgetAnimationObject {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBWidgetAnimationRect, TBWidgetAnimationObject);
-
- enum MODE {
- /** Animate from source to dest. */
- MODE_SRC_TO_DST,
- /** Animate from current + delta to current. */
- MODE_DELTA_IN,
- /** Animate from current to current + delta. */
- MODE_DELTA_OUT
- };
- /** Animate the widget between the given source and dest rectangle. */
- TBWidgetAnimationRect(TBWidget *widget, const TBRect &src_rect, const TBRect &dst_rect);
- /** Animate the widget between rectangles based on the current widget
- rectangle and a delta. The reference rectangle will be taken from
- the target widget on the first OnAnimationUpdate. */
- TBWidgetAnimationRect(TBWidget *widget, const TBRect &delta_rect, MODE mode);
- virtual void onAnimationStart() override;
- virtual void onAnimationUpdate(float progress) override;
- virtual void onAnimationStop(bool aborted) override;
-
-private:
- TBRect m_src_rect;
- TBRect m_dst_rect;
- TBRect m_delta_rect;
- MODE m_mode;
-};
-
-class TBWidgetsAnimationManager : public TBWidgetListener {
-public:
- virtual ~TBWidgetsAnimationManager() {
- }
- /** Init the widgets animation manager. */
- static void init();
-
- /** Shutdown the widgets animation manager. */
- static void shutdown();
-
- /** Abort all animations that are running for the given widget. */
- static void abortAnimations(TBWidget *widget);
-
- /** Abort all animations matching the given type that are running for the given widget.
- This example will abort all opacity animations:
- AbortAnimations(widget, TBTypedObject::getTypeId()) */
- static void abortAnimations(TBWidget *widget, TB_TYPE_ID type_id);
-
-private:
- // == TBWidgetListener ==================
- virtual void onWidgetDelete(TBWidget *widget) override;
- virtual bool onWidgetDying(TBWidget *widget) override;
- virtual void onWidgetAdded(TBWidget *parent, TBWidget *child) override;
- virtual void onWidgetRemove(TBWidget *parent, TBWidget *child) override;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/image/tb_image_manager.cpp b/src/modules/ui/turbobadger/tb/image/tb_image_manager.cpp
deleted file mode 100644
index af9bbb26c..000000000
--- a/src/modules/ui/turbobadger/tb/image/tb_image_manager.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_image_manager.h"
-#include "tb_skin.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-
-namespace tb {
-
-TBImageRep::TBImageRep(TBImageManager *imageManager, TBBitmapFragment *fragment, uint32_t hashKey)
- : ref_count(0), hash_key(hashKey), image_manager(imageManager), fragment(fragment) {
-}
-
-void TBImageRep::incRef() {
- ref_count++;
-}
-
-void TBImageRep::decRef() {
- ref_count--;
- if (ref_count == 0) {
- if (image_manager != nullptr) {
- image_manager->removeImageRep(this);
- }
- delete this;
- }
-}
-
-TBImage::TBImage(TBImageRep *rep) : m_image_rep(rep) {
- if (m_image_rep != nullptr) {
- m_image_rep->incRef();
- }
-}
-
-TBImage::TBImage(const TBImage &image) : m_image_rep(image.m_image_rep) {
- if (m_image_rep != nullptr) {
- m_image_rep->incRef();
- }
-}
-
-TBImage::~TBImage() {
- if (m_image_rep != nullptr) {
- m_image_rep->decRef();
- }
-}
-
-bool TBImage::isEmpty() const {
- return !(m_image_rep && m_image_rep->fragment);
-}
-
-int TBImage::width() const {
- if (m_image_rep && m_image_rep->fragment)
- return m_image_rep->fragment->width();
- return 0;
-}
-
-int TBImage::height() const {
- if (m_image_rep && m_image_rep->fragment)
- return m_image_rep->fragment->height();
- return 0;
-}
-
-TBBitmapFragment *TBImage::getBitmap() const {
- return m_image_rep ? m_image_rep->fragment : nullptr;
-}
-
-void TBImage::setImageRep(TBImageRep *imageRep) {
- if (m_image_rep == imageRep) {
- return;
- }
-
- if (m_image_rep != nullptr) {
- m_image_rep->decRef();
- }
-
- m_image_rep = imageRep;
-
- if (m_image_rep != nullptr) {
- m_image_rep->incRef();
- }
-}
-
-TBImageManager *g_image_manager = nullptr;
-
-TBImageManager::TBImageManager() {
- g_renderer->addListener(this);
-}
-
-TBImageManager::~TBImageManager() {
- g_renderer->removeListener(this);
-
- // If there is TBImageRep objects live, we must unset the fragment pointer
- // since the m_frag_manager is going to be destroyed very soon.
- TBHashTableIteratorOf it(&m_image_rep_hash);
- while (TBImageRep *image_rep = it.getNextContent()) {
- image_rep->fragment = nullptr;
- image_rep->image_manager = nullptr;
- }
-}
-
-TBImage TBImageManager::getImage(const char *filename) {
- uint32_t hash_key = TBGetHash(filename);
- TBImageRep *image_rep = m_image_rep_hash.get(hash_key);
- if (image_rep == nullptr) {
- // Load a fragment. Load a destination DPI bitmap if available.
- TBBitmapFragment *fragment = nullptr;
- if (g_tb_skin->getDimensionConverter()->needConversion()) {
- TBTempBuffer filename_dst_DPI;
- g_tb_skin->getDimensionConverter()->getDstDPIFilename(filename, &filename_dst_DPI);
- fragment = m_frag_manager.getFragmentFromFile(filename_dst_DPI.getData(), false);
- }
- if (!fragment)
- fragment = m_frag_manager.getFragmentFromFile(filename, false);
-
- image_rep = new TBImageRep(this, fragment, hash_key);
- if (!image_rep || !fragment || !m_image_rep_hash.add(hash_key, image_rep)) {
- delete image_rep;
- m_frag_manager.freeFragment(fragment);
- image_rep = nullptr;
- }
- Log::debug(image_rep ? "TBImageManager - Loaded new image.\n" : "TBImageManager - Loading image failed.");
- }
- return TBImage(image_rep);
-}
-
-TBImage TBImageManager::getImage(const char *name, uint32_t *buffer, int width, int height) {
- uint32_t hash_key = TBGetHash(name);
- TBImageRep *image_rep = m_image_rep_hash.get(hash_key);
- if (image_rep == nullptr) {
- TBID id(name);
- TBBitmapFragment *fragment = m_frag_manager.createNewFragment(id, false, width, height, width, buffer);
-
- image_rep = new TBImageRep(this, fragment, hash_key);
- if (!image_rep || !fragment || !m_image_rep_hash.add(hash_key, image_rep)) {
- delete image_rep;
- m_frag_manager.freeFragment(fragment);
- image_rep = nullptr;
- }
- Log::debug(image_rep ? "TBImageManager - Loaded new image.\n" : "TBImageManager - Loading image failed.");
- }
- return TBImage(image_rep);
-}
-
-void TBImageManager::removeImageRep(TBImageRep *imageRep) {
- core_assert(imageRep->ref_count == 0);
- if (imageRep->fragment) {
- m_frag_manager.freeFragment(imageRep->fragment);
- imageRep->fragment = nullptr;
- }
- m_image_rep_hash.remove(imageRep->hash_key);
- imageRep->image_manager = nullptr;
- Log::debug("TBImageManager - Removed image.");
-}
-
-void TBImageManager::onContextLost() {
- m_frag_manager.deleteBitmaps();
-}
-
-void TBImageManager::onContextRestored() {
- // No need to do anything. The bitmaps will be created when drawing.
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/image/tb_image_manager.h b/src/modules/ui/turbobadger/tb/image/tb_image_manager.h
deleted file mode 100644
index e98f92c26..000000000
--- a/src/modules/ui/turbobadger/tb/image/tb_image_manager.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_bitmap_fragment.h"
-#include "tb_core.h"
-#include "tb_hashtable.h"
-#include "tb_linklist.h"
-#include "tb_renderer.h"
-
-namespace tb {
-
-class TBImageManager;
-
-/** TBImageRep is the internal contents of a TBImage. Owned by reference counting from TBImage. */
-class TBImageRep {
- friend class TBImageManager;
- friend class TBImage;
-
- TBImageRep(TBImageManager *imageManager, TBBitmapFragment *fragment, uint32_t hashKey);
-
- void incRef();
- void decRef();
-
- int ref_count;
- uint32_t hash_key;
- TBImageManager *image_manager;
- TBBitmapFragment *fragment;
-};
-
-/** TBImage is a reference counting object representing a image loaded by TBImageManager.
- As long as there are TBImage objects for a certain image, it will be kept loaded in memory.
- It may be empty if the image has not yet been set, or if the TBImageManager is destroyed
- when the image is still alive.
-*/
-class TBImage {
-public:
- TBImage() : m_image_rep(nullptr) {
- }
- TBImage(TBImageRep *rep);
- TBImage(const TBImage &image);
- ~TBImage();
-
- /** Return true if this image is empty. */
- bool isEmpty() const;
-
- /** Return the width of this image, or 0 if empty. */
- int width() const;
-
- /** Return the height of this image, or 0 if empty. */
- int height() const;
-
- /** Return the bitmap fragment for this image, or nullptr if empty. */
- TBBitmapFragment *getBitmap() const;
-
- const TBImage &operator=(const TBImage &image) {
- setImageRep(image.m_image_rep);
- return *this;
- }
- bool operator==(const TBImage &image) const {
- return m_image_rep == image.m_image_rep;
- }
- bool operator!=(const TBImage &image) const {
- return m_image_rep != image.m_image_rep;
- }
-
-private:
- void setImageRep(TBImageRep *image_rep);
- TBImageRep *m_image_rep;
-};
-
-/** TBImageManager loads images returned as TBImage objects.
-
- It internally use a TBBitmapFragmentManager that create fragment maps for loaded images,
- and keeping track of which images are loaded so they are not loaded several times.
-
- Images are forgotten when there are no longer any TBImage objects for a given file.
-*/
-
-class TBImageManager : private TBRendererListener {
-public:
- TBImageManager();
- ~TBImageManager();
-
- /** Return a image object for the given filename.
- If it fails, the returned TBImage object will be empty. */
- TBImage getImage(const char *filename);
- TBImage getImage(const char *name, uint32_t *buffer, int width, int height);
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- /** Render the skin bitmaps on screen, to analyze fragment positioning. */
- void debug() {
- m_frag_manager.debug();
- }
-#endif
-
- // Implementing TBRendererListener
- virtual void onContextLost();
- virtual void onContextRestored();
-
-private:
- TBBitmapFragmentManager m_frag_manager;
- TBHashTableOf m_image_rep_hash;
-
- friend class TBImageRep;
- void removeImageRep(TBImageRep *image_rep);
-};
-
-/** The global TBImageManager. */
-extern TBImageManager *g_image_manager;
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/image/tb_image_widget.cpp b/src/modules/ui/turbobadger/tb/image/tb_image_widget.cpp
deleted file mode 100644
index ee30c6540..000000000
--- a/src/modules/ui/turbobadger/tb/image/tb_image_widget.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * @file
- */
-
-#include "image/tb_image_widget.h"
-#include "tb_node_tree.h"
-#include "tb_widgets_reader.h"
-
-namespace tb {
-
-PreferredSize TBImageWidget::onCalculatePreferredContentSize(const SizeConstraints &constraints) {
- return PreferredSize(m_image.width(), m_image.height());
-}
-
-void TBImageWidget::onPaint(const PaintProps &paintProps) {
- if (TBBitmapFragment *fragment = m_image.getBitmap())
- g_renderer->drawBitmap(getPaddingRect(), TBRect(0, 0, m_image.width(), m_image.height()), fragment);
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/image/tb_image_widget.h b/src/modules/ui/turbobadger/tb/image/tb_image_widget.h
deleted file mode 100644
index 7533bcb38..000000000
--- a/src/modules/ui/turbobadger/tb/image/tb_image_widget.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_image_manager.h"
-#include "tb_object.h"
-#include "tb_widgets.h"
-
-namespace tb {
-
-/** TBImageWidget is a widget showing a image loaded by TBImageManager,
- constrained in size to its skin.
- If you need to show a image from the skin, you can use TBSkinImage. */
-class TBImageWidget : public TBWidget {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBImageWidget, TBWidget);
-
- TBImageWidget() {
- }
-
- void setImage(const TBImage &image) {
- m_image = image;
- }
- void setImage(const char *filename) {
- m_image = g_image_manager->getImage(filename);
- }
-
- virtual PreferredSize onCalculatePreferredContentSize(const SizeConstraints &constraints) override;
-
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual void onPaint(const PaintProps &paintProps) override;
-
-private:
- TBImage m_image;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/parser/tb_parser.cpp b/src/modules/ui/turbobadger/tb/parser/tb_parser.cpp
deleted file mode 100644
index 38b4de4bc..000000000
--- a/src/modules/ui/turbobadger/tb/parser/tb_parser.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/**
- * @file
- */
-
-#include "parser/tb_parser.h"
-#include "core/Assert.h"
-#include "tb_tempbuffer.h"
-#include "utf8/utf8.h"
-#include
-
-namespace tb {
-
-static bool is_hex(char c) {
- return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
-}
-
-static uint32_t parse_hex(char *&src, int maxCount) {
- uint32_t hex = 0;
- for (int i = 0; i < maxCount; i++) {
- char c = *src;
- if (!is_hex(c)) {
- break;
- }
- hex <<= 4;
- hex |= SDL_isdigit(c) != 0 ? c - '0' : SDL_tolower(c) - 'a' + 10;
- src++;
- }
- return hex;
-}
-
-void unescapeString(char *str) {
- // fast forward to any escape sequence
- while ((*str != 0) && *str != '\\') {
- str++;
- }
-
- char *dst = str;
- char *src = str;
- while (*src != 0) {
- if (*src == '\\') {
- bool code_found = true;
- switch (src[1]) {
- case 'a':
- *dst = '\a';
- break;
- case 'b':
- *dst = '\b';
- break;
- case 'f':
- *dst = '\f';
- break;
- case 'n':
- *dst = '\n';
- break;
- case 'r':
- *dst = '\r';
- break;
- case 't':
- *dst = '\t';
- break;
- case 'v':
- *dst = '\v';
- break;
- case '0':
- *dst = '\0';
- break;
- case '\"':
- *dst = '\"';
- break;
- case '\'':
- *dst = '\'';
- break;
- case '\\':
- *dst = '\\';
- break;
- case 'x': // \xXX
- case 'u': // \uXXXX
- {
- // This should be safe. A utf-8 character can be at most 4 bytes,
- // and we have 4 bytes to use for \xXX and 6 for \uXXXX.
- src += 2;
- if (UCS4 hex = parse_hex(src, src[1] == 'x' ? 2 : 4))
- dst += utf8::encode(hex, dst);
- continue;
- }
- default:
- code_found = false;
- }
- if (code_found) {
- src += 2;
- dst++;
- continue;
- }
- }
- *dst = *src;
- dst++;
- src++;
- }
- *dst = 0;
-}
-
-bool is_white_space(const char *str) {
- switch (*str) {
- case ' ':
- case '\t':
- return true;
- default:
- return false;
- }
-}
-
-/** Return true if the given string starts with a color.
- Ex: #ffdd00, #fd0 */
-bool is_start_of_color(const char *str) {
- if (*str++ != '#') {
- return false;
- }
- int digit_count = 0;
- while (is_hex(*str)) {
- str++;
- digit_count++;
- }
- return digit_count == 8 || digit_count == 6 || digit_count == 4 || digit_count == 3;
-}
-
-/** Return true if the given string may be a node reference, such
- as language strings or TBNodeRefTree references. */
-bool is_start_of_reference(const char *str) {
- if (*str++ != '@') {
- return false;
- }
- while ((*str != 0) && *str != ' ') {
- // If the token ends with colon, it's not a value but a key.
- if (*str == ':') {
- return false;
- }
- str++;
- }
- return true;
-}
-
-/** Check if the line is a comment or empty space. If it is, consume the leading
- whitespace from line. */
-bool is_space_or_comment(char *&line) {
- char *tmp = line;
- while (is_white_space(tmp)) {
- tmp++;
- }
- if (*tmp == '#' || *tmp == 0) {
- line = tmp;
- return true;
- }
- return false;
-}
-
-bool is_pending_multiline(const char *str) {
- while (is_white_space(str)) {
- str++;
- }
- return str[0] == '\\' && str[1] == 0;
-}
-
-bool isEndQuote(const char *bufStart, const char *buf, const char quoteType) {
- if (*buf != quoteType) {
- return false;
- }
- int num_backslashes = 0;
- while (bufStart < buf && *(buf-- - 1) == '\\') {
- num_backslashes++;
- }
- return (num_backslashes & 1) == 0;
-}
-
-TBParser::STATUS TBParser::read(TBParserStream *stream, TBParserTarget *target) {
- TBTempBuffer line, work;
- if (!line.reserve(1024) || !work.reserve(1024))
- return STATUS_OUT_OF_MEMORY;
-
- current_indent = 0;
- current_line_nr = 1;
- pending_multiline = false;
- multi_line_sub_level = 0;
-
- while (int read_len = stream->getMoreData((char *)work.getData(), work.getCapacity())) {
- char *buf = work.getData();
-
- // Skip BOM (BYTE ORDER MARK) character, often in the beginning of UTF-8 documents.
- if (current_line_nr == 1 && read_len > 3 && (uint8_t)buf[0] == 239 && (uint8_t)buf[1] == 187 &&
- (uint8_t)buf[2] == 191) {
- read_len -= 3;
- buf += 3;
- }
-
- int line_pos = 0;
- while (true) {
- // Find line end
- int line_start = line_pos;
- while (line_pos < read_len && buf[line_pos] != '\n')
- line_pos++;
-
- if (line_pos < read_len) {
- // We have a line
- // Skip preceding \r (if we have one)
- int line_len = line_pos - line_start;
- if (!line.append(buf + line_start, line_len))
- return STATUS_OUT_OF_MEMORY;
-
- // Strip away trailing '\r' if the line has it
- char *linebuf = line.getData();
- int linebuf_len = line.getAppendPos();
- if (linebuf_len > 0 && linebuf[linebuf_len - 1] == '\r')
- linebuf[linebuf_len - 1] = 0;
-
- // Terminate the line string
- if (!line.append("", 1))
- return STATUS_OUT_OF_MEMORY;
-
- // Handle line
- onLine(line.getData(), target);
- current_line_nr++;
-
- line.resetAppendPos();
- line_pos++; // Skip this \n
- // Find next line
- continue;
- }
- // No more lines here so push the rest and break for more data
- if (!line.append(buf + line_start, read_len - line_start))
- return STATUS_OUT_OF_MEMORY;
- break;
- }
- }
- if (line.getAppendPos()) {
- if (!line.append("", 1))
- return STATUS_OUT_OF_MEMORY;
- onLine(line.getData(), target);
- current_line_nr++;
- }
- return STATUS_OK;
-}
-
-void TBParser::onLine(char *line, TBParserTarget *target) {
- if (is_space_or_comment(line)) {
- if (*line == '#')
- target->onComment(current_line_nr, line + 1);
- return;
- }
- if (pending_multiline) {
- onMultiline(line, target);
- return;
- }
-
- // Check indent
- int indent = 0;
- while (line[indent] == '\t' && line[indent] != 0)
- indent++;
- line += indent;
-
- if (indent - current_indent > 1) {
- target->onError(current_line_nr, "Indentation error. (Line skipped)");
- return;
- }
-
- if (indent > current_indent) {
- // FIX: Report indentation error if more than 1 higher!
- core_assert(indent - current_indent == 1);
- target->enter();
- current_indent++;
- } else if (indent < current_indent) {
- while (indent < current_indent) {
- target->leave();
- current_indent--;
- }
- }
-
- if (*line == 0)
- return;
- else {
- char *token = line;
- // Read line while consuming it and copy over to token buf
- while (!is_white_space(line) && *line != 0)
- line++;
- int token_len = line - token;
- // Consume any white space after the token
- while (is_white_space(line))
- line++;
-
- bool is_compact_line = token_len && token[token_len - 1] == ':';
-
- TBValue value;
- if (is_compact_line) {
- token_len--;
- token[token_len] = 0;
-
- // Check if the first argument is not a child but the value for this token
- if (*line == '[' || *line == '\"' || *line == '\'' || is_start_of_number(line) || is_start_of_color(line) ||
- is_start_of_reference(line)) {
- consumeValue(value, line);
-
- if (pending_multiline) {
- // The value wrapped to the next line, so we should remember the token and continue.
- multi_line_token = token;
- return;
- }
- }
- } else if (token[token_len]) {
- token[token_len] = 0;
- unescapeString(line);
- value.setFromStringAuto(line, TBValue::SET_AS_STATIC);
- }
- target->onToken(current_line_nr, token, value);
-
- if (is_compact_line)
- onCompactLine(line, target);
- }
-}
-
-void TBParser::onCompactLine(char *line, TBParserTarget *target) {
- target->enter();
- while (*line) {
- // consume any whitespace
- while (is_white_space(line))
- line++;
-
- // Find token
- char *token = line;
- while (*line != ':' && *line != 0)
- line++;
- if (!*line)
- break; // Syntax error, expected token
- *line++ = 0;
-
- // consume any whitespace
- while (is_white_space(line))
- line++;
-
- TBValue v;
- consumeValue(v, line);
-
- if (pending_multiline) {
- // The value wrapped to the next line, so we should remember the token and continue.
- multi_line_token = token;
- // Since we need to call target->Leave when the multiline is ready, set multi_line_sub_level.
- multi_line_sub_level = 1;
- return;
- }
-
- // Ready
- target->onToken(current_line_nr, token, v);
- }
-
- target->leave();
-}
-
-void TBParser::onMultiline(char *line, TBParserTarget *target) {
- // consume any whitespace
- while (is_white_space(line))
- line++;
-
- TBValue value;
- consumeValue(value, line);
-
- if (!pending_multiline) {
- // Ready with all lines
- value.setString(multi_line_value.getData(), TBValue::SET_AS_STATIC);
- target->onToken(current_line_nr, multi_line_token.c_str(), value);
-
- if (multi_line_sub_level)
- target->leave();
-
- // Reset
- multi_line_value.setAppendPos(0);
- multi_line_sub_level = 0;
- }
-}
-
-void TBParser::consumeValue(TBValue &dstValue, char *&line) {
- // Find value (As quoted string, or as auto)
- char *value = line;
- if (*line == '\"' || *line == '\'') {
- const char quote_type = *line;
- // Consume starting quote
- line++;
- value++;
- // Find ending quote or end
- while (!isEndQuote(value, line, quote_type) && *line != 0)
- line++;
- // Terminate away the quote
- if (*line == quote_type)
- *line++ = 0;
-
- // consume any whitespace
- while (is_white_space(line))
- line++;
- // consume any comma
- if (*line == ',')
- line++;
-
- unescapeString(value);
- dstValue.setString(value, TBValue::SET_AS_STATIC);
- } else {
- // Find next comma or end
- while (*line != ',' && *line != 0)
- line++;
- // Terminate away the comma
- if (*line == ',')
- *line++ = 0;
-
- unescapeString(value);
- dstValue.setFromStringAuto(value, TBValue::SET_AS_STATIC);
- }
-
- // Check if we still have pending value data on the following line and set pending_multiline.
- bool continuing_multiline = pending_multiline;
- pending_multiline = is_pending_multiline(line);
-
- // Append the multi line value to the buffer.
- if (continuing_multiline || pending_multiline)
- multi_line_value.appendString(dstValue.getString());
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/parser/tb_parser.h b/src/modules/ui/turbobadger/tb/parser/tb_parser.h
deleted file mode 100644
index 358e67013..000000000
--- a/src/modules/ui/turbobadger/tb/parser/tb_parser.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_str.h"
-#include "tb_tempbuffer.h"
-#include "tb_value.h"
-
-namespace tb {
-
-/** Unescape backslash codes. This is done in place using the string both as source
- and destination. */
-void unescapeString(char *str);
-
-/** Check if buf is pointing at an end quote. It may need to iterate
- buf backwards toward buf_start to check if any preceding backslashes
- make it a escaped quote (which should not be the end quote) */
-bool isEndQuote(const char *buf_start, const char *buf, const char quote_type);
-
-class TBParserTarget {
-public:
- virtual ~TBParserTarget() {
- }
- virtual void onError(int line_nr, const char *error) = 0;
- virtual void onComment(int line_nr, const char *comment) = 0;
- virtual void onToken(int line_nr, const char *name, TBValue &value) = 0;
- virtual void enter() = 0;
- virtual void leave() = 0;
-};
-
-class TBParserStream {
-public:
- virtual ~TBParserStream() {
- }
- virtual int getMoreData(char *buf, int buf_len) = 0;
-};
-
-class TBParser {
-public:
- enum STATUS { STATUS_OK, STATUS_OUT_OF_MEMORY, STATUS_PARSE_ERROR };
- TBParser() {
- }
- STATUS read(TBParserStream *stream, TBParserTarget *target);
-
-private:
- int current_indent = 0;
- int current_line_nr = 0;
- core::String multi_line_token;
- TBTempBuffer multi_line_value;
- int multi_line_sub_level = 0;
- bool pending_multiline = false;
- void onLine(char *line, TBParserTarget *target);
- void onCompactLine(char *line, TBParserTarget *target);
- void onMultiline(char *line, TBParserTarget *target);
- void consumeValue(TBValue &dst_value, char *&line);
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/renderers/tb_renderer_batcher.cpp b/src/modules/ui/turbobadger/tb/renderers/tb_renderer_batcher.cpp
deleted file mode 100644
index 1338aaa56..000000000
--- a/src/modules/ui/turbobadger/tb/renderers/tb_renderer_batcher.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/**
- * @file
- */
-
-#include "renderers/tb_renderer_batcher.h"
-#include "tb_bitmap_fragment.h"
-#include "tb_system.h"
-
-namespace tb {
-
-// == TBRendererBatcher::Batch ==========================================================
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-uint32_t dbg_begin_paint_batch_id = 0;
-uint32_t dbg_frame_triangle_count = 0;
-#endif // TB_RUNTIME_DEBUG_INFO
-
-#define VER_COL(r, g, b, a) (((a) << 24) + ((b) << 16) + ((g) << 8) + r)
-#define VER_COL_OPACITY(a) (0x00ffffff + (((uint32_t)a) << 24))
-
-void TBRendererBatcher::Batch::flush(TBRendererBatcher *batchRenderer) {
- if (!vertex_count || is_flushing) {
- return;
- }
-
- // Prevent re-entrancy. Calling fragment->getBitmap may end up calling TBBitmap::setData
- // which will end up flushing any existing batch with that bitmap.
- is_flushing = true;
-
- if (fragment) {
- // Now it's time to ensure the bitmap data is up to date. A call to GetBitmap
- // with TB_VALIDATE_ALWAYS should guarantee that its data is validated.
- TBBitmap *frag_bitmap = fragment->getBitmap(TB_VALIDATE_ALWAYS);
- ((void)frag_bitmap); // silence warning about unused variable
- core_assert(frag_bitmap == bitmap);
- }
-
- batchRenderer->renderBatch(this);
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- if (TB_DEBUG_SETTING(RENDER_BATCHES)) {
- // This assumes we're drawing triangles. Need to modify this
- // if we start using strips, fans or whatever.
- dbg_frame_triangle_count += vertex_count / 3;
-
- // Draw the triangles again using a random color based on the batch
- // id. This indicates which triangles belong to the same batch.
- uint32_t id = batch_id - dbg_begin_paint_batch_id;
- uint32_t hash = id * (2166136261U ^ id);
- uint32_t color = 0xAA000000 + (hash & 0x00FFFFFF);
- for (int i = 0; i < vertex_count; i++)
- vertex[i].col = color;
- bitmap = nullptr;
- batchRenderer->renderBatch(this);
- }
-#endif // TB_RUNTIME_DEBUG_INFO
-
- vertex_count = 0;
-
- ++batch_id; // Will overflow eventually, but that doesn't really matter.
-
- is_flushing = false;
-}
-
-TBRendererBatcher::Vertex *TBRendererBatcher::Batch::reserve(TBRendererBatcher *batchRenderer, int count) {
- core_assert(count < VERTEX_BATCH_SIZE);
- if (vertex_count + count > VERTEX_BATCH_SIZE) {
- flush(batchRenderer);
- }
- Vertex *ret = &vertex[vertex_count];
- vertex_count += count;
- return ret;
-}
-
-// == TBRendererBatcher ===================================================================
-
-TBRendererBatcher::TBRendererBatcher()
- : m_opacity(255), m_translation_x(0), m_translation_y(0) {
-}
-
-TBRendererBatcher::~TBRendererBatcher() {
-}
-
-void TBRendererBatcher::beginPaint(int renderTargetW, int renderTargetH) {
-#ifdef TB_RUNTIME_DEBUG_INFO
- dbg_begin_paint_batch_id = batch.batch_id;
- dbg_frame_triangle_count = 0;
-#endif // TB_RUNTIME_DEBUG_INFO
-
- m_screen_rect.set(0, 0, renderTargetW, renderTargetH);
- m_clip_rect = m_screen_rect;
-}
-
-void TBRendererBatcher::endPaint() {
- flushAllInternal();
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- if (TB_DEBUG_SETTING(RENDER_BATCHES))
- Log::debug("Frame rendered using %d batches and a total of %d triangles.",
- batch.batch_id - dbg_begin_paint_batch_id, dbg_frame_triangle_count);
-#endif // TB_RUNTIME_DEBUG_INFO
-}
-
-void TBRendererBatcher::translate(int dx, int dy) {
- m_translation_x += dx;
- m_translation_y += dy;
-}
-
-void TBRendererBatcher::setOpacity(float opacity) {
- int8_t opacity8 = (uint8_t)(opacity * 255);
- if (opacity8 == m_opacity)
- return;
- m_opacity = opacity8;
-}
-
-float TBRendererBatcher::getOpacity() {
- return m_opacity / 255.f;
-}
-
-TBRect TBRendererBatcher::setClipRect(const TBRect &rect, bool addToCurrent) {
- TBRect old_clip_rect = m_clip_rect;
- m_clip_rect = rect;
- m_clip_rect.x += m_translation_x;
- m_clip_rect.y += m_translation_y;
-
- if (addToCurrent) {
- m_clip_rect = m_clip_rect.clip(old_clip_rect);
- }
-
- flushAllInternal();
- setClipRect(m_clip_rect);
-
- old_clip_rect.x -= m_translation_x;
- old_clip_rect.y -= m_translation_y;
- return old_clip_rect;
-}
-
-TBRect TBRendererBatcher::getClipRect() {
- TBRect curr_clip_rect = m_clip_rect;
- curr_clip_rect.x -= m_translation_x;
- curr_clip_rect.y -= m_translation_y;
- return curr_clip_rect;
-}
-
-void TBRendererBatcher::drawBitmap(const TBRect &dstRect, const TBRect &srcRect, TBBitmapFragment *bitmapFragment) {
- if (TBBitmap *bitmap = bitmapFragment->getBitmap(TB_VALIDATE_FIRST_TIME))
- addQuadInternal(dstRect.offset(m_translation_x, m_translation_y),
- srcRect.offset(bitmapFragment->m_rect.x, bitmapFragment->m_rect.y), VER_COL_OPACITY(m_opacity),
- bitmap, bitmapFragment);
-}
-
-void TBRendererBatcher::drawBitmap(const TBRect &dstRect, const TBRect &srcRect, TBBitmap *bitmap) {
- addQuadInternal(dstRect.offset(m_translation_x, m_translation_y), srcRect, VER_COL_OPACITY(m_opacity), bitmap,
- nullptr);
-}
-
-void TBRendererBatcher::drawBitmapColored(const TBRect &dstRect, const TBRect &srcRect, const TBColor &color,
- TBBitmapFragment *bitmapFragment) {
- if (TBBitmap *bitmap = bitmapFragment->getBitmap(TB_VALIDATE_FIRST_TIME)) {
- uint32_t a = (color.a * m_opacity) / 255;
- addQuadInternal(dstRect.offset(m_translation_x, m_translation_y),
- srcRect.offset(bitmapFragment->m_rect.x, bitmapFragment->m_rect.y),
- VER_COL(color.r, color.g, color.b, a), bitmap, bitmapFragment);
- }
-}
-
-void TBRendererBatcher::drawBitmapColored(const TBRect &dstRect, const TBRect &srcRect, const TBColor &color,
- TBBitmap *bitmap) {
- uint32_t a = (color.a * m_opacity) / 255;
- addQuadInternal(dstRect.offset(m_translation_x, m_translation_y), srcRect, VER_COL(color.r, color.g, color.b, a),
- bitmap, nullptr);
-}
-
-void TBRendererBatcher::drawBitmapTile(const TBRect &dstRect, TBBitmap *bitmap) {
- addQuadInternal(dstRect.offset(m_translation_x, m_translation_y), TBRect(0, 0, dstRect.w, dstRect.h),
- VER_COL_OPACITY(m_opacity), bitmap, nullptr);
-}
-
-void TBRendererBatcher::addQuadInternal(const TBRect &dstRect, const TBRect &srcRect, uint32_t color, TBBitmap *bitmap,
- TBBitmapFragment *fragment) {
- if (batch.bitmap != bitmap) {
- batch.flush(this);
- batch.bitmap = bitmap;
- }
- batch.fragment = fragment;
-
- const int bitmap_w = bitmap->width();
- const int bitmap_h = bitmap->height();
- const float m_u = (float)srcRect.x / bitmap_w;
- const float m_v = (float)srcRect.y / bitmap_h;
- const float xw = (float)(srcRect.x + srcRect.w);
- const float yh = (float)(srcRect.y + srcRect.h);
- const float m_uu = xw / bitmap_w;
- const float m_vv = yh / bitmap_h;
-
- Vertex *ver = batch.reserve(this, 6);
- ver[0].x = (float)dstRect.x;
- ver[0].y = (float)(dstRect.y + dstRect.h);
- ver[0].u = m_u;
- ver[0].v = m_vv;
- ver[0].col = color;
- ver[1].x = (float)(dstRect.x + dstRect.w);
- ver[1].y = ver[0].y;
- ver[1].u = m_uu;
- ver[1].v = m_vv;
- ver[1].col = color;
- ver[2].x = ver[0].x;
- ver[2].y = (float)dstRect.y;
- ver[2].u = m_u;
- ver[2].v = m_v;
- ver[2].col = color;
-
- ver[3].x = ver[0].x;
- ver[3].y = ver[2].y;
- ver[3].u = m_u;
- ver[3].v = m_v;
- ver[3].col = color;
- ver[4].x = ver[1].x;
- ver[4].y = ver[0].y;
- ver[4].u = m_uu;
- ver[4].v = m_vv;
- ver[4].col = color;
- ver[5].x = ver[1].x;
- ver[5].y = ver[2].y;
- ver[5].u = m_uu;
- ver[5].v = m_v;
- ver[5].col = color;
-
- // Update fragments batch id (See FlushBitmapFragment)
- if (fragment)
- fragment->m_batch_id = batch.batch_id;
-}
-
-void TBRendererBatcher::flushAllInternal() {
- batch.flush(this);
-}
-
-void TBRendererBatcher::flushBitmap(TBBitmap *bitmap) {
- // Flush the batch if it's using this bitmap (that is about to change or be deleted)
- if (batch.vertex_count && bitmap == batch.bitmap) {
- batch.flush(this);
- }
-}
-
-void TBRendererBatcher::flushBitmapFragment(TBBitmapFragment *bitmapFragment) {
- // Flush the batch if it is using this fragment (that is about to change or be deleted)
- // We know if it is in use in the current batch if its batch_id matches the current
- // batch_id in our (one and only) batch.
- // If we switch to a more advance batching system with multiple batches, we need to
- // solve this a bit differently.
- if (batch.vertex_count && bitmapFragment->m_batch_id == batch.batch_id) {
- batch.flush(this);
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/renderers/tb_renderer_batcher.h b/src/modules/ui/turbobadger/tb/renderers/tb_renderer_batcher.h
deleted file mode 100644
index 31ad7ebb9..000000000
--- a/src/modules/ui/turbobadger/tb/renderers/tb_renderer_batcher.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_renderer.h"
-
-namespace tb {
-
-#define VERTEX_BATCH_SIZE 65536
-
-/** TBRendererBatcher is a helper class that implements batching of draw operations for a TBRenderer.
- If you do not want to do your own batching you can subclass this class instead of TBRenderer.
- If overriding any function in this class, make sure to call the base class too. */
-class TBRendererBatcher : public TBRenderer {
-public:
- /** Vertex stored in a Batch */
- struct Vertex {
- float x, y;
- float u, v;
- union {
- struct {
- unsigned char r, g, b, a;
- };
- uint32_t col;
- };
- };
- /** A batch which should be rendered. */
- class Batch {
- public:
- Batch() : vertex_count(0), bitmap(nullptr), fragment(nullptr), batch_id(0), is_flushing(false) {
- }
- void flush(TBRendererBatcher *batch_renderer);
- Vertex *reserve(TBRendererBatcher *batch_renderer, int count);
-
- alignas(16) Vertex vertex[VERTEX_BATCH_SIZE];
- int vertex_count;
-
- TBBitmap *bitmap;
- TBBitmapFragment *fragment;
-
- uint32_t batch_id;
- bool is_flushing;
- };
-
- TBRendererBatcher();
- virtual ~TBRendererBatcher();
-
- virtual void beginPaint(int render_target_w, int render_target_h);
- virtual void endPaint();
-
- virtual void translate(int dx, int dy);
-
- virtual void setOpacity(float opacity);
- virtual float getOpacity();
-
- virtual TBRect setClipRect(const TBRect &rect, bool add_to_current);
- virtual TBRect getClipRect();
-
- virtual void drawBitmap(const TBRect &dst_rect, const TBRect &src_rect, TBBitmapFragment *bitmap_fragment);
- virtual void drawBitmap(const TBRect &dst_rect, const TBRect &src_rect, TBBitmap *bitmap);
- virtual void drawBitmapColored(const TBRect &dst_rect, const TBRect &src_rect, const TBColor &color,
- TBBitmapFragment *bitmap_fragment);
- virtual void drawBitmapColored(const TBRect &dst_rect, const TBRect &src_rect, const TBColor &color,
- TBBitmap *bitmap);
- virtual void drawBitmapTile(const TBRect &dst_rect, TBBitmap *bitmap);
- virtual void flushBitmap(TBBitmap *bitmap);
- virtual void flushBitmapFragment(TBBitmapFragment *bitmap_fragment);
-
- virtual void beginBatchHint(TBRenderer::BATCH_HINT hint) {
- }
- virtual void endBatchHint() {
- }
-
- // == Methods that need implementation in subclasses ================================
- virtual TBBitmap *createBitmap(int width, int height, uint32_t *data) = 0;
- virtual void renderBatch(Batch *batch) = 0;
- virtual void setClipRect(const TBRect &rect) = 0;
-
-protected:
- uint8_t m_opacity;
- TBRect m_screen_rect;
- TBRect m_clip_rect;
- int m_translation_x;
- int m_translation_y;
-
- Batch batch; ///< The one and only batch. this should be improved.
-
- void addQuadInternal(const TBRect &dst_rect, const TBRect &src_rect, uint32_t color, TBBitmap *bitmap,
- TBBitmapFragment *fragment);
- void flushAllInternal();
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_bitmap_fragment.cpp b/src/modules/ui/turbobadger/tb/tb_bitmap_fragment.cpp
deleted file mode 100644
index 0c828a475..000000000
--- a/src/modules/ui/turbobadger/tb/tb_bitmap_fragment.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_bitmap_fragment.h"
-#include "image/Image.h"
-#include "tb_renderer.h"
-#include "tb_system.h"
-
-namespace tb {
-
-int TBGetNearestPowerOfTwo(int val) {
- int i;
- for (i = 31; i >= 0; i--) {
- if (((val - 1) & (1 << i)) != 0) {
- break;
- }
- }
- return (1 << (i + 1));
-}
-
-// == TBSpaceAllocator ======================================================================================
-
-bool TBSpaceAllocator::hasSpace(int neededW) const {
- if (neededW > m_available_space) {
- return false;
- }
- if (isAllAvailable()) {
- return true;
- }
- for (Space *fs = m_free_space_list.getFirst(); fs != nullptr; fs = fs->getNext()) {
- if (neededW <= fs->width) {
- return true;
- }
- }
- return false;
-}
-
-TBSpaceAllocator::Space *TBSpaceAllocator::allocSpace(int neededW) {
- if (Space *available_space = getSmallestAvailableSpace(neededW)) {
- if (Space *new_space = new Space) {
- new_space->x = available_space->x;
- new_space->width = neededW;
- m_used_space_list.addLast(new_space);
-
- // Consume the used space from the available space
- available_space->x += neededW;
- available_space->width -= neededW;
- m_available_space -= neededW;
-
- // Remove it if empty
- if (available_space->width == 0) {
- m_free_space_list.doDelete(available_space);
- }
- return new_space;
- }
- }
- return nullptr;
-}
-
-TBSpaceAllocator::Space *TBSpaceAllocator::getSmallestAvailableSpace(int neededW) {
- core_assert(neededW > 0);
-
- // Add free space covering all available space if empty.
- if (!m_free_space_list.hasLinks() && isAllAvailable()) {
- if (Space *fs = new Space) {
- fs->x = 0;
- fs->width = m_available_space;
- m_free_space_list.addLast(fs);
- }
- }
-
- // Check for the smallest space where we fit
- Space *best_fs = nullptr;
- for (Space *fs = m_free_space_list.getFirst(); fs != nullptr; fs = fs->getNext()) {
- if (neededW == fs->width) {
- return fs; // It can't be better than a perfect match!
- }
- if (neededW < fs->width) {
- if ((best_fs == nullptr) || fs->width < best_fs->width) {
- best_fs = fs;
- }
- }
- }
- return best_fs;
-}
-
-void TBSpaceAllocator::freeSpace(Space *space) {
- m_used_space_list.remove(space);
- m_available_space += space->width;
-
- // Find where in m_free_space_list we should insert the space,
- // or which existing space we can extend.
- Space *preceeding = nullptr;
- Space *succeeding = nullptr;
- for (Space *fs = m_free_space_list.getFirst(); fs != nullptr; fs = fs->getNext()) {
- if (fs->x < space->x) {
- preceeding = fs;
- }
- if (fs->x > space->x) {
- succeeding = fs;
- break;
- }
- }
- if ((preceeding != nullptr) && preceeding->x + preceeding->width == space->x) {
- preceeding->width += space->width;
- delete space;
- } else if ((succeeding != nullptr) && succeeding->x == space->x + space->width) {
- succeeding->x -= space->width;
- succeeding->width += space->width;
- delete space;
- } else {
- if (preceeding != nullptr) {
- m_free_space_list.addAfter(space, preceeding);
- } else if (succeeding != nullptr) {
- m_free_space_list.addBefore(space, succeeding);
- } else {
- core_assert(!m_free_space_list.hasLinks());
- m_free_space_list.addLast(space);
- }
- }
- // Merge free spaces
- Space *fs = m_free_space_list.getFirst();
- while (fs != nullptr) {
- Space *next_fs = fs->getNext();
- if (next_fs == nullptr) {
- break;
- }
- if (fs->x + fs->width == next_fs->x) {
- fs->width += next_fs->width;
- m_free_space_list.doDelete(next_fs);
- continue;
- }
- fs = next_fs;
- }
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- // Check that free space is in order
- Space *tmp = m_free_space_list.getFirst();
- int x = 0;
- while (tmp != nullptr) {
- core_assert(tmp->x >= x);
- x = tmp->x + tmp->width;
- tmp = tmp->getNext();
- }
-#endif // TB_RUNTIME_DEBUG_INFO
-}
-
-// == TBBitmapFragmentMap ===================================================================================
-
-TBBitmapFragmentMap::TBBitmapFragmentMap()
- : m_bitmap_w(0), m_bitmap_h(0), m_bitmap_data(nullptr), m_bitmap(nullptr), m_need_update(false),
- m_allocated_pixels(0) {
-}
-
-bool TBBitmapFragmentMap::init(int bitmapW, int bitmapH) {
- m_bitmap_data = new uint32_t[bitmapW * bitmapH];
- m_bitmap_w = bitmapW;
- m_bitmap_h = bitmapH;
-#ifdef TB_RUNTIME_DEBUG_INFO
- if (m_bitmap_data != nullptr) {
- memset(m_bitmap_data, 0x88, bitmapW * bitmapH * sizeof(uint32_t));
- }
-#endif
- return m_bitmap_data != nullptr;
-}
-
-TBBitmapFragmentMap::~TBBitmapFragmentMap() {
- delete m_bitmap;
- delete[] m_bitmap_data;
-}
-
-TBBitmapFragment *TBBitmapFragmentMap::createNewFragment(int fragW, int fragH, int dataStride, uint32_t *fragData,
- bool addBorder) {
- // Finding available space works like this:
- // The map size is sliced up horizontally in rows (initially just one row covering
- // the entire map). When adding a new fragment, put it in the row with smallest height.
- // If the smallest row is empty, it may slice the row to make a even smaller row.
-
- // When a image is stretched up to a larger size, the filtering will read
- // pixels closest (but outside) of the src_rect. When we pack images together
- // those pixels would be read from neighbour images, so we must add border space
- // around each image to avoid artifacts. We must also fill in that border with
- // the "clamp" of the image itself so we don't get any filtering artifacts at all.
- // Allways add border except when we're using the entire map for one fragment.
- int border = 0;
- int needed_w = fragW;
- int needed_h = fragH;
- if (addBorder) {
- if (needed_w != m_bitmap_w || needed_h != m_bitmap_h) {
- border = 1;
- needed_w += 2;
- needed_h += 2;
- }
- }
-
- // Snap the fragments to a certain granularity. This could maybe ease the stress
- // on the space allocator when allocating & deallocating lots of small fragments.
- // I'm not sure there is any performance issue though and it would be better to
- // optimize the algorithm instead (so disabled it for now).
- // const int granularity = 8;
- // needed_w = (needed_w + granularity - 1) / granularity * granularity;
- // needed_h = (needed_h + granularity - 1) / granularity * granularity;
-
- if (m_rows.getNumItems() == 0) {
- // Create a row covering the entire bitmap.
- TBFragmentSpaceAllocator *row;
- if (!m_rows.growIfNeeded() || ((row = new TBFragmentSpaceAllocator(0, m_bitmap_w, m_bitmap_h)) == nullptr)) {
- return nullptr;
- }
- m_rows.add(row);
- }
- // Get the smallest row where we fit
- int best_row_index = -1;
- TBFragmentSpaceAllocator *best_row = nullptr;
- for (int i = 0; i < m_rows.getNumItems(); i++) {
- TBFragmentSpaceAllocator *row = m_rows[i];
- if ((best_row == nullptr) || row->height < best_row->height) {
- // This is the best row so far, if we fit
- if (needed_h <= row->height && row->hasSpace(needed_w)) {
- best_row = row;
- best_row_index = i;
- if (needed_h == row->height) {
- break; // We can't find a smaller line, so we're done
- }
- }
- }
- }
- // Return if we're full
- if (best_row == nullptr) {
- return nullptr;
- }
- // If the row is unused, create a smaller row to only consume needed height for fragment
- if (best_row->isAllAvailable() && needed_h < best_row->height) {
- TBFragmentSpaceAllocator *row;
- if (!m_rows.growIfNeeded() || ((row = new TBFragmentSpaceAllocator(best_row->y + needed_h, m_bitmap_w,
- best_row->height - needed_h)) == nullptr)) {
- return nullptr;
- }
- // Keep the rows sorted from top to bottom
- m_rows.add(row, best_row_index + 1);
- best_row->height = needed_h;
- }
- // Allocate the fragment and copy the fragment data into the map data.
- if (TBFragmentSpaceAllocator::Space *space = best_row->allocSpace(needed_w)) {
- if (TBBitmapFragment *frag = new TBBitmapFragment) {
- frag->m_map = this;
- frag->m_row = best_row;
- frag->m_space = space;
- frag->m_rect.set(space->x + border, best_row->y + border, fragW, fragH);
- frag->m_row_height = best_row->height;
- frag->m_batch_id = 0xffffffff;
- copyData(frag, dataStride, fragData, border);
- m_need_update = true;
- m_allocated_pixels += frag->m_space->width * frag->m_row->height;
- return frag;
- }
- { best_row->freeSpace(space); }
- }
- return nullptr;
-}
-
-void TBBitmapFragmentMap::freeFragmentSpace(TBBitmapFragment *frag) {
- if (frag == nullptr) {
- return;
- }
- core_assert(frag->m_map == this);
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- // Debug code to clear the area in debug builds so it's easier to
- // see & debug the allocation & deallocation of fragments in maps.
- if (uint32_t *data32 = new uint32_t[frag->m_space->width * frag->m_row->height]) {
- static int c = 0;
- memset(data32, (c++) * 32, sizeof(uint32_t) * frag->m_space->width * frag->m_row->height);
- copyData(frag, frag->m_space->width, data32, 0);
- m_need_update = true;
- delete[] data32;
- }
-#endif // TB_RUNTIME_DEBUG_INFO
-
- m_allocated_pixels -= frag->m_space->width * frag->m_row->height;
- frag->m_row->freeSpace(frag->m_space);
- frag->m_space = nullptr;
- frag->m_row_height = 0;
-
- // If the row is now empty, merge empty rows so larger fragments
- // have a chance of allocating the space.
- if (frag->m_row->isAllAvailable()) {
- for (int i = 0; i < m_rows.getNumItems() - 1; i++) {
- core_assert(i >= 0);
- core_assert(i < m_rows.getNumItems() - 1);
- TBFragmentSpaceAllocator *row = m_rows.get(i);
- TBFragmentSpaceAllocator *next_row = m_rows.get(i + 1);
- if (row->isAllAvailable() && next_row->isAllAvailable()) {
- row->height += next_row->height;
- m_rows.doDelete(i + 1);
- i--;
- }
- }
- }
-}
-
-void TBBitmapFragmentMap::copyData(TBBitmapFragment *frag, int dataStride, uint32_t *fragData, int border) {
- // Copy the bitmap data
- uint32_t *dst = m_bitmap_data + frag->m_rect.x + frag->m_rect.y * m_bitmap_w;
- uint32_t *src = fragData;
- for (int i = 0; i < frag->m_rect.h; i++) {
- memcpy(dst, src, frag->m_rect.w * sizeof(uint32_t));
- dst += m_bitmap_w;
- src += dataStride;
- }
- // Copy the bitmap data to the border around the fragment
- if (border != 0) {
- TBRect rect = frag->m_rect.expand(border, border);
- // Copy vertical edges
- dst = m_bitmap_data + rect.x + (rect.y + 1) * m_bitmap_w;
- src = fragData;
- for (int i = 0; i < frag->m_rect.h; i++) {
- dst[0] = src[0] & 0x00ffffff;
- dst[rect.w - 1] = src[frag->m_rect.w - 1] & 0x00ffffff;
- dst += m_bitmap_w;
- src += dataStride;
- }
- // Copy horizontal edges
- dst = m_bitmap_data + rect.x + 1 + rect.y * m_bitmap_w;
- src = fragData;
- for (int i = 0; i < frag->m_rect.w; i++) {
- dst[i] = src[i] & 0x00ffffff;
- }
- dst = m_bitmap_data + rect.x + 1 + (rect.y + rect.h - 1) * m_bitmap_w;
- src = fragData + (frag->m_rect.h - 1) * dataStride;
- for (int i = 0; i < frag->m_rect.w; i++) {
- dst[i] = src[i] & 0x00ffffff;
- }
- }
-}
-
-TBBitmap *TBBitmapFragmentMap::getBitmap(TB_VALIDATE_TYPE validateType) {
- if ((m_bitmap != nullptr) && validateType == TB_VALIDATE_FIRST_TIME) {
- return m_bitmap;
- }
- validateBitmap();
- return m_bitmap;
-}
-
-bool TBBitmapFragmentMap::validateBitmap() {
- if (m_need_update) {
- if (m_bitmap != nullptr) {
- m_bitmap->setData(m_bitmap_data);
- } else {
- m_bitmap = g_renderer->createBitmap(m_bitmap_w, m_bitmap_h, m_bitmap_data);
- }
- m_need_update = false;
- }
- return m_bitmap != nullptr;
-}
-
-void TBBitmapFragmentMap::deleteBitmap() {
- delete m_bitmap;
- m_bitmap = nullptr;
- m_need_update = true;
-}
-
-// == TBBitmapFragmentManager =============================================================================
-
-TBBitmapFragmentManager::TBBitmapFragmentManager()
- : m_num_maps_limit(0), m_add_border(false), m_default_map_w(2048), m_default_map_h(2048) {
-}
-
-TBBitmapFragmentManager::~TBBitmapFragmentManager() {
- clear();
-}
-
-TBBitmapFragment *TBBitmapFragmentManager::getFragmentFromFile(const char *filename, bool dedicatedMap) {
- TBID id(filename);
-
- // If we already have a fragment for this filename, return that
- TBBitmapFragment *frag = m_fragments.get(id);
- if (frag != nullptr) {
- return frag;
- }
-
- // Load the file
- const image::ImagePtr &img = image::loadImage(filename, false);
- return createNewFragment(id, dedicatedMap, img->width(), img->height(), img->width(), (uint32_t *)img->data());
-}
-
-TBBitmapFragment *TBBitmapFragmentManager::createNewFragment(const TBID &id, bool dedicatedMap, int dataW, int dataH,
- int dataStride, uint32_t *data) {
- core_assert(!getFragment(id));
-
- TBBitmapFragment *frag = nullptr;
-
- // Create a fragment in any of the fragment maps. Doing it in the reverse order
- // would be faster since it's most likely to succeed, but we want to maximize
- // the amount of fragments per map, so do it in the creation order.
- if (!dedicatedMap) {
- for (int i = 0; i < m_fragment_maps.getNumItems(); i++) {
- if ((frag = m_fragment_maps[i]->createNewFragment(dataW, dataH, dataStride, data, m_add_border)) !=
- nullptr) {
- break;
- }
- }
- }
- // If we couldn't create the fragment in any map, create a new map where we know it will fit.
- bool allow_another_map = (m_num_maps_limit == 0 || m_fragment_maps.getNumItems() < m_num_maps_limit);
- if ((frag == nullptr) && allow_another_map && m_fragment_maps.growIfNeeded()) {
- int po2w = TBGetNearestPowerOfTwo(Max(dataW, m_default_map_w));
- int po2h = TBGetNearestPowerOfTwo(Max(dataH, m_default_map_h));
- if (dedicatedMap) {
- po2w = TBGetNearestPowerOfTwo(dataW);
- po2h = TBGetNearestPowerOfTwo(dataH);
- }
- TBBitmapFragmentMap *fm = new TBBitmapFragmentMap();
- if ((fm != nullptr) && fm->init(po2w, po2h)) {
- m_fragment_maps.add(fm);
- frag = fm->createNewFragment(dataW, dataH, dataStride, data, m_add_border);
- } else {
- delete fm;
- }
- }
- // Finally, add the new fragment to the hash.
- if ((frag != nullptr) && m_fragments.add(id, frag)) {
- frag->m_id = id;
- return frag;
- }
- delete frag;
- return nullptr;
-}
-
-void TBBitmapFragmentManager::freeFragment(TBBitmapFragment *frag) {
- if (frag != nullptr) {
- g_renderer->flushBitmapFragment(frag);
-
- TBBitmapFragmentMap *map = frag->m_map;
- frag->m_map->freeFragmentSpace(frag);
- m_fragments.deleteKey(frag->m_id);
-
- // If the map is now empty, delete it.
- if (map->m_allocated_pixels == 0) {
- m_fragment_maps.doDelete(m_fragment_maps.find(map));
- }
- }
-}
-
-TBBitmapFragment *TBBitmapFragmentManager::getFragment(const TBID &id) const {
- return m_fragments.get(id);
-}
-
-void TBBitmapFragmentManager::clear() {
- m_fragment_maps.deleteAll();
- m_fragments.deleteAll();
-}
-
-bool TBBitmapFragmentManager::validateBitmaps() {
- bool success = true;
- for (int i = 0; i < m_fragment_maps.getNumItems(); i++) {
- if (!m_fragment_maps[i]->validateBitmap()) {
- success = false;
- }
- }
- return success;
-}
-
-void TBBitmapFragmentManager::deleteBitmaps() {
- for (int i = 0; i < m_fragment_maps.getNumItems(); i++) {
- m_fragment_maps[i]->deleteBitmap();
- }
-}
-
-void TBBitmapFragmentManager::setNumMapsLimit(int numMapsLimit) {
- m_num_maps_limit = numMapsLimit;
-}
-
-void TBBitmapFragmentManager::setDefaultMapSize(int w, int h) {
- core_assert(TBGetNearestPowerOfTwo(w) == w);
- core_assert(TBGetNearestPowerOfTwo(h) == h);
- m_default_map_w = w;
- m_default_map_h = h;
-}
-
-int TBBitmapFragmentManager::getUseRatio() const {
- int used = 0;
- int total = 0;
- for (int i = 0; i < m_fragment_maps.getNumItems(); i++) {
- used += m_fragment_maps[i]->m_allocated_pixels;
- total += m_fragment_maps[i]->m_bitmap_w * m_fragment_maps[i]->m_bitmap_h;
- }
- return total != 0 ? (used * 100) / total : 0;
-}
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-void TBBitmapFragmentManager::debug() {
- int x = 0;
- for (int i = 0; i < m_fragment_maps.getNumItems(); i++) {
- TBBitmapFragmentMap *fm = m_fragment_maps[i];
- if (TBBitmap *bitmap = fm->getBitmap(TB_VALIDATE_ALWAYS)) {
- g_renderer->drawBitmap(TBRect(x, 0, fm->m_bitmap_w, fm->m_bitmap_h),
- TBRect(0, 0, fm->m_bitmap_w, fm->m_bitmap_h), bitmap);
- }
- x += fm->m_bitmap_w + 5;
- }
-}
-#endif // TB_RUNTIME_DEBUG_INFO
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_bitmap_fragment.h b/src/modules/ui/turbobadger/tb/tb_bitmap_fragment.h
deleted file mode 100644
index d494c6f8d..000000000
--- a/src/modules/ui/turbobadger/tb/tb_bitmap_fragment.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-#include "tb_geometry.h"
-#include "tb_hashtable.h"
-#include "tb_id.h"
-#include "tb_linklist.h"
-#include "tb_list.h"
-
-namespace tb {
-
-class TBBitmapFragment;
-class TBBitmap;
-
-/** Return the nearest power of two from val.
- F.ex 110 -> 128, 256->256, 257->512 etc. */
-int TBGetNearestPowerOfTwo(int val);
-
-/** Allocator of space out of a given available space. */
-class TBSpaceAllocator {
-public:
- /** A chunk of space */
- class Space : public TBLinkOf {
- public:
- int x, width;
- };
-
- TBSpaceAllocator(int availableSpace) : m_available_space(availableSpace) {
- }
-
- /** Return true if no allocations are currently live using this allocator. */
- bool isAllAvailable() const {
- return !m_used_space_list.hasLinks();
- }
-
- /** Return true if the given width is currently available. */
- bool hasSpace(int needed_w) const;
-
- /** Allocate the given space and return the Space, or nullptr on error. */
- Space *allocSpace(int needed_w);
-
- /** Free the given space so it is available for new allocations. */
- void freeSpace(Space *space);
-
-private:
- Space *getSmallestAvailableSpace(int needed_w);
- int m_available_space;
- TBLinkListAutoDeleteOf m_free_space_list;
- TBLinkListAutoDeleteOf m_used_space_list;
-};
-
-/** Allocates space for TBBitmapFragment in a row (used in TBBitmapFragmentMap). */
-class TBFragmentSpaceAllocator : public TBSpaceAllocator {
-public:
- TBFragmentSpaceAllocator(int y, int width, int height) : TBSpaceAllocator(width), y(y), height(height) {
- }
-
- int y, height;
-};
-
-/** Specify when the bitmap should be validated when calling TBBitmapFragmentMap::getBitmap. */
-enum TB_VALIDATE_TYPE {
-
- /** Always validate the bitmap (The bitmap is updated if needed) */
- TB_VALIDATE_ALWAYS,
-
- /** Only validate if the bitmap does not yet exist (Make sure there is
- a valid bitmap pointer, but the data is not necessarily updated) */
- TB_VALIDATE_FIRST_TIME
-};
-
-/** TBBitmapFragmentMap is used to pack multiple bitmaps into a single TBBitmap.
- When initialized (in a size suitable for a TBBitmap) it also creates a software buffer
- that will make up the TBBitmap when all fragments have been added. */
-class TBBitmapFragmentMap {
-public:
- TBBitmapFragmentMap();
- ~TBBitmapFragmentMap();
-
- /** Initialize the map with the given size. The size should be a power of two since
- it will be used to create a TBBitmap (texture memory). */
- bool init(int bitmapW, int bitmapH);
-
- /** Create a new fragment with the given size and data in this map.
- Returns nullptr if there is not enough room in this map or on any other fail. */
- TBBitmapFragment *createNewFragment(int fragW, int fragH, int dataStride, uint32_t *fragData, bool addBorder);
-
- /** Free up the space used by the given fragment, so that other fragments can take its place. */
- void freeFragmentSpace(TBBitmapFragment *frag);
-
- /** Return the bitmap for this map.
- By default, the bitmap is validated if needed before returning (See TB_VALIDATE_TYPE) */
- TBBitmap *getBitmap(TB_VALIDATE_TYPE validate_type);
-
-private:
- friend class TBBitmapFragmentManager;
- bool validateBitmap();
- void deleteBitmap();
- void copyData(TBBitmapFragment *frag, int dataStride, uint32_t *fragData, int border);
- TBListAutoDeleteOf m_rows;
- int m_bitmap_w, m_bitmap_h;
- uint32_t *m_bitmap_data;
- TBBitmap *m_bitmap;
- bool m_need_update;
- int m_allocated_pixels;
-};
-
-/** TBBitmapFragment represents a sub part of a TBBitmap.
- It's owned by TBBitmapFragmentManager which pack multiple
- TBBitmapFragment within TBBitmaps to reduce texture switching. */
-class TBBitmapFragment {
-public:
- /** Return the width of the bitmap fragment. */
- int width() const {
- return m_rect.w;
- }
-
- /** Return the height of the bitmap fragment. */
- int height() const {
- return m_rect.h;
- }
-
- /** Return the bitmap for this fragment.
- By default, the bitmap is validated if needed before returning (See TB_VALIDATE_TYPE) */
- TBBitmap *getBitmap(TB_VALIDATE_TYPE validateType) {
- return m_map->getBitmap(validateType);
- }
-
- /** Return the height allocated to this fragment. This may be larger than Height() depending
- of the internal allocation of fragments in a map. It should rarely be used. */
- int getAllocatedHeight() const {
- return m_row_height;
- }
-
-public:
- TBBitmapFragmentMap *m_map;
- TBRect m_rect;
- TBFragmentSpaceAllocator *m_row;
- TBFragmentSpaceAllocator::Space *m_space;
- TBID m_id;
- int m_row_height;
-
- /** This uint32 is reserved for batching renderer backends. It's not used
- internally, but always initialized to 0xffffffff for all new fragments. */
- uint32_t m_batch_id;
-};
-
-/** TBBitmapFragmentManager manages loading bitmaps of arbitrary size,
- pack as many of them into as few TBBitmap as possible.
-
- It also makes sure that only one instance of each file is loaded,
- so f.ex loading "foo.png" many times still load and allocate one
- TBBitmapFragment. */
-class TBBitmapFragmentManager {
-public:
- TBBitmapFragmentManager();
- ~TBBitmapFragmentManager();
-
- /** Set to true if a 1px border should be added to new fragments so stretched
- drawing won't get filtering artifacts at the edges (default is disabled). */
- void setAddBorder(bool addBorder) {
- m_add_border = addBorder;
- }
- bool getAddBorder() const {
- return m_add_border;
- }
-
- /** Get the fragment with the given image filename. If it's not already loaded,
- it will be loaded into a new fragment with the filename as id.
- returns nullptr on fail. */
- TBBitmapFragment *getFragmentFromFile(const char *filename, bool dedicated_map);
-
- /** Get the fragment with the given id, or nullptr if it doesn't exist. */
- TBBitmapFragment *getFragment(const TBID &id) const;
-
- /** Create a new fragment from the given data.
- @param id The id that should be used to identify the fragment.
- @param dedicatedMap if true, it will get a dedicated map.
- @param dataW the width of the data.
- @param dataH the height of the data.
- @param dataStride the number of pixels in a row of the input data.
- @param data pointer to the data in BGRA32 format. */
- TBBitmapFragment *createNewFragment(const TBID &id, bool dedicatedMap, int dataW, int dataH, int dataStride,
- uint32_t *data);
-
- /** Delete the given fragment and free the space it used in its map,
- so that other fragments can take its place. */
- void freeFragment(TBBitmapFragment *frag);
-
- /** Clear all loaded bitmaps and all created bitmap fragments and maps.
- After this call, do not keep any pointers to any TBBitmapFragment created
- by this fragment manager. */
- void clear();
-
- /** Validate bitmaps on fragment maps that has changed. */
- bool validateBitmaps();
-
- /** Delete all bitmaps in all fragment maps in this manager.
- The bitmaps will be recreated automatically when needed, or when
- calling ValidateBitmaps. You do not need to call this, except when
- the context is lost and all bitmaps must be forgotten. */
- void deleteBitmaps();
-
- /** Get number of fragment maps that is currently used. */
- int getNumMaps() const {
- return m_fragment_maps.getNumItems();
- }
-
- /** Set the number of maps (TBBitmaps) this manager should be allowed to create.
- If a new fragment can't fit into any existing bitmap and the limit is reached,
- the fragment creation will fail. Set to 0 for unlimited (default). */
- void setNumMapsLimit(int num_maps_limit);
-
- /** Set the default size of new fragment maps. These must be power of two. */
- void setDefaultMapSize(int w, int h);
-
- /** Get the amount (in percent) of space that is currently occupied by all maps
- in this fragment manager. */
- int getUseRatio() const;
-#ifdef TB_RUNTIME_DEBUG_INFO
- /** Render the maps on screen, to analyze fragment positioning. */
- void debug();
-#endif
-private:
- TBListOf m_fragment_maps;
- TBHashTableOf m_fragments;
- int m_num_maps_limit;
- bool m_add_border;
- int m_default_map_w;
- int m_default_map_h;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_color.cpp b/src/modules/ui/turbobadger/tb/tb_color.cpp
deleted file mode 100644
index d5f7ef2c0..000000000
--- a/src/modules/ui/turbobadger/tb/tb_color.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_color.h"
-#include
-#include
-#include
-
-namespace tb {
-
-TBColor TBColor::fromVec4(const glm::vec4& c) {
- return TBColor((int)(c.r * 255.0f), (int)(c.g * 255.0f), (int)(c.b * 255.0f), (int)(c.a * 255.0f));
-}
-
-TBColor TBColor::fromVec3(const glm::vec3& c) {
- return TBColor((int)(c.r * 255.0f), (int)(c.g * 255.0f), (int)(c.b * 255.0f));
-}
-
-void TBColor::setFromString(const char *str, int len) {
- int r;
- int g;
- int b;
- int a;
- if (len == 9 && sscanf(str, "#%2x%2x%2x%2x", &r, &g, &b, &a) == 4) { // rrggbbaa
- set(TBColor(r, g, b, a));
- } else if (len == 7 && sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3) { // rrggbb
- set(TBColor(r, g, b));
- } else if (len == 5 && sscanf(str, "#%1x%1x%1x%1x", &r, &g, &b, &a) == 4) { // rgba
- set(TBColor(r + (r << 4), g + (g << 4), b + (b << 4), a + (a << 4)));
- } else if (len == 4 && sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3) { // rgb
- set(TBColor(r + (r << 4), g + (g << 4), b + (b << 4)));
- } else {
- set(TBColor());
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_color.h b/src/modules/ui/turbobadger/tb/tb_color.h
deleted file mode 100644
index 9f4dbc3ac..000000000
--- a/src/modules/ui/turbobadger/tb/tb_color.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_types.h"
-#include "core/GLM.h"
-
-namespace tb {
-
-/** TBColor contains a 32bit color. */
-
-// TODO: replace with glm::u8vec4
-class TBColor {
-public:
- constexpr TBColor() : b(0), g(0), r(0), a(255) {
- }
- constexpr TBColor(int r, int g, int b, int a = 255) : b(b), g(g), r(r), a(a) {
- }
-
- static TBColor fromVec4(const glm::vec4& c);
-
- static TBColor fromVec3(const glm::vec3& c);
-
- uint8_t b, g, r, a;
-
- void set(const TBColor &color) {
- *this = color;
- }
-
- /** Set the color from string in any of the following formats:
- "#rrggbbaa", "#rrggbb", "#rgba", "#rgb" */
- void setFromString(const char *str, int len);
-
- inline operator uint32_t() const {
- return *((uint32_t *)this);
- }
- inline bool operator==(const TBColor &c) const {
- return *this == (uint32_t)c;
- }
- inline bool operator!=(const TBColor &c) const {
- return !(*this == c);
- }
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_config.h b/src/modules/ui/turbobadger/tb/tb_config.h
deleted file mode 100644
index 705fcc3f0..000000000
--- a/src/modules/ui/turbobadger/tb/tb_config.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#ifdef DEBUG
-#define TB_RUNTIME_DEBUG_INFO
-#endif
-#define TB_GLYPH_CACHE_WIDTH 512
-#define TB_GLYPH_CACHE_HEIGHT 512
diff --git a/src/modules/ui/turbobadger/tb/tb_core.cpp b/src/modules/ui/turbobadger/tb/tb_core.cpp
deleted file mode 100644
index 24b5cddb6..000000000
--- a/src/modules/ui/turbobadger/tb/tb_core.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_core.h"
-#include "animation/tb_animation.h"
-#include "image/tb_image_manager.h"
-#include "tb_font_renderer.h"
-#include "tb_language.h"
-#include "tb_skin.h"
-#include "tb_system.h"
-#include "tb_widgets_reader.h"
-
-namespace tb {
-
-TBRenderer *g_renderer = nullptr;
-TBSkin *g_tb_skin = nullptr;
-TBWidgetsReader *g_widgets_reader = nullptr;
-TBLanguage *g_tb_lng = nullptr;
-TBFontManager *g_font_manager = nullptr;
-
-bool tb_core_init(TBRenderer *renderer) {
- Log::debug("Initiating Turbo Badger - version " TB_VERSION_STR);
- g_renderer = renderer;
- g_tb_lng = new TBLanguage;
- g_font_manager = new TBFontManager();
- g_tb_skin = new TBSkin();
- g_widgets_reader = TBWidgetsReader::create();
- g_image_manager = new TBImageManager();
- return true;
-}
-
-void tb_core_shutdown() {
- TBAnimationManager::abortAllAnimations();
- delete g_image_manager;
- g_image_manager = nullptr;
- delete g_widgets_reader;
- g_widgets_reader = nullptr;
- delete g_tb_skin;
- g_tb_skin = nullptr;
- delete g_font_manager;
- g_font_manager = nullptr;
- delete g_tb_lng;
- g_tb_lng = nullptr;
-}
-
-bool tb_core_is_initialized() {
- return g_widgets_reader != nullptr;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_core.h b/src/modules/ui/turbobadger/tb/tb_core.h
deleted file mode 100644
index 313a81285..000000000
--- a/src/modules/ui/turbobadger/tb/tb_core.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_debug.h"
-#include "tb_hash.h"
-#include "tb_types.h"
-
-#define TB_VERSION_MAJOR 0
-#define TB_VERSION_MINOR 1
-#define TB_VERSION_REVISION 1
-#define TB_VERSION_STR "0.1.1"
-
-namespace tb {
-
-class TBRenderer;
-class TBSkin;
-class TBWidgetsReader;
-class TBLanguage;
-class TBFontManager;
-
-extern TBRenderer *g_renderer;
-extern TBSkin *g_tb_skin;
-extern TBWidgetsReader *g_widgets_reader;
-extern TBLanguage *g_tb_lng;
-extern TBFontManager *g_font_manager;
-
-/** Initialize turbo badger. Call this before using any turbo badger API. */
-bool tb_core_init(TBRenderer *renderer);
-
-/** Shutdown turbo badger. Call this after deleting the last widget, to free turbo badger internals. */
-void tb_core_shutdown();
-
-/** Returns true if turbo badger is initialized. */
-bool tb_core_is_initialized();
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_debug.cpp b/src/modules/ui/turbobadger/tb/tb_debug.cpp
deleted file mode 100644
index b8f84b68e..000000000
--- a/src/modules/ui/turbobadger/tb/tb_debug.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_core.h"
-#include "tb_editfield.h"
-#include "tb_font_renderer.h"
-#include "tb_tempbuffer.h"
-#include "tb_widgets_reader.h"
-#include "tb_window.h"
-#include "core/StringUtil.h"
-#include
-
-namespace tb {
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-
-TBDebugInfo g_tb_debug;
-
-TBDebugInfo::TBDebugInfo() {
- SDL_memset(settings, 0, sizeof(int) * NUM_SETTINGS);
-}
-
-/** Window showing runtime debug settings. */
-class DebugSettingsWindow : public TBWindow, public TBWidgetListener {
-public:
- TBEditField *output;
-
- TBOBJECT_SUBCLASS(DebugSettingsWindow, TBWindow);
-
- DebugSettingsWindow(TBWidget *root) {
- setText("Debug settings");
- g_widgets_reader->loadData(this, "TBLayout: axis: y, distribution: available, position: left\n"
- " TBLayout: id: 'container', axis: y, size: available\n"
- " TBTextField: text: 'Event output:'\n"
- " TBEditField: id: 'output', gravity: all, multiline: 1, wrap: 0\n"
- " lp: pref-height: 100dp");
-
- addCheckbox(TBDebugInfo::LAYOUT_BOUNDS, "Layout bounds");
- addCheckbox(TBDebugInfo::LAYOUT_CLIPPING, "Layout clipping");
- addCheckbox(TBDebugInfo::LAYOUT_PS_DEBUGGING, "Layout size calculation");
- addCheckbox(TBDebugInfo::RENDER_BATCHES, "Render batches");
- addCheckbox(TBDebugInfo::RENDER_SKIN_BITMAP_FRAGMENTS, "Render skin bitmap fragments");
- addCheckbox(TBDebugInfo::RENDER_FONT_BITMAP_FRAGMENTS, "Render font bitmap fragments");
-
- output = getWidgetByIDAndType(TBIDC("output"));
-
- TBRect bounds(0, 0, root->getRect().w, root->getRect().h);
- setRect(getResizeToFitContentRect().centerIn(bounds).moveIn(bounds).clip(bounds));
-
- root->addChild(this);
-
- TBWidgetListener::addGlobalListener(this);
- }
-
- ~DebugSettingsWindow() {
- TBWidgetListener::removeGlobalListener(this);
- }
-
- void addCheckbox(TBDebugInfo::SETTING setting, const char *str) {
- TBCheckBox *check = new TBCheckBox();
- check->setValue(g_tb_debug.settings[setting]);
- check->data.setInt(setting);
- check->setID(TBIDC("check"));
-
- TBClickLabel *label = new TBClickLabel();
- label->setText(str);
- label->getContentRoot()->addChild(check, WIDGET_Z_BOTTOM);
-
- getWidgetByID(TBIDC("container"))->addChild(label);
- }
-
- virtual bool onEvent(const TBWidgetEvent &ev) override {
- if (ev.type == EVENT_TYPE_CLICK && ev.target->getID() == TBIDC("check")) {
- // Update setting and invalidate
- g_tb_debug.settings[ev.target->data.getInt()] = ev.target->getValue();
- getParentRoot()->invalidate();
- return true;
- }
- return TBWindow::onEvent(ev);
- }
-
- virtual void onPaint(const PaintProps &paintProps) override {
- // Draw stuff to the right of the debug window
- g_renderer->translate(getRect().w, 0);
-
- // Draw skin bitmap fragments
- if (TB_DEBUG_SETTING(RENDER_SKIN_BITMAP_FRAGMENTS)) {
- g_tb_skin->debug();
- }
-
- // Draw font glyph fragments (the font of the hovered widget)
- if (TB_DEBUG_SETTING(RENDER_FONT_BITMAP_FRAGMENTS)) {
- TBWidget *widget =
- TBWidget::hovered_widget != nullptr ? TBWidget::hovered_widget : TBWidget::focused_widget;
- g_font_manager
- ->getFontFace(widget != nullptr ? widget->getCalculatedFontDescription()
- : g_font_manager->getDefaultFontDescription())
- ->debug();
- }
-
- g_renderer->translate(-getRect().w, 0);
- }
-
- core::String getIdString(const TBID &id) {
- core::String str;
- str = core::string::format("%u", (uint32_t)id);
- return str;
- }
-
- // TBWidgetListener
- virtual bool onWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) override {
- // Skip these events for now
- if (ev.isPointerEvent()) {
- return false;
- }
-
- // Always ignore activity in this window (or we might get endless recursion)
- if (TBWindow *window = widget->getParentWindow()) {
- if (TBSafeCast(window) != nullptr) {
- return false;
- }
- }
-
- TBTempBuffer buf;
- buf.appendString(getEventTypeStr(ev.type));
- buf.appendString(" (");
- buf.appendString(widget->getClassName());
- buf.appendString(")");
-
- buf.appendString(" id: ");
- buf.appendString(getIdString(ev.target->getID()));
-
- if (ev.ref_id != 0U) {
- buf.appendString(", ref_id: ");
- buf.appendString(getIdString(ev.ref_id));
- }
-
- if (ev.type == EVENT_TYPE_CHANGED) {
- core::String extra;
- core::String text;
- if (ev.target->getText(text) && text.size() > 24) {
- sprintf(text.c_str() + 20, "...");
- }
- extra = core::string::format(", value: %.2f (\"%s\")", ev.target->getValueDouble(), text.c_str());
- buf.appendString(extra.c_str());
- }
- buf.appendString("\n");
-
- // Append the line to the output textfield
- TBStyleEdit *se = output->getStyleEdit();
- se->selection.selectNothing();
- se->appendText(buf.getData(), true);
- se->scrollIfNeeded(false, true);
-
- // Remove lines from the top if we exceed the height limit.
- const int height_limit = 2000;
- int current_height = se->getContentHeight();
- if (current_height > height_limit) {
- se->caret.place(TBPoint(0, current_height - height_limit));
- se->selection.selectToCaret(se->blocks.getFirst(), 0);
- se->del();
- }
- return false;
- }
-
- const char *getEventTypeStr(EVENT_TYPE type) const {
- switch (type) {
- case EVENT_TYPE_CLICK:
- return "CLICK";
- case EVENT_TYPE_LONG_CLICK:
- return "LONG_CLICK";
- case EVENT_TYPE_POINTER_DOWN:
- return "POINTER_DOWN";
- case EVENT_TYPE_POINTER_UP:
- return "POINTER_UP";
- case EVENT_TYPE_POINTER_MOVE:
- return "POINTER_MOVE";
- case EVENT_TYPE_TOUCH_DOWN:
- return "TOUCH_DOWN";
- case EVENT_TYPE_TOUCH_UP:
- return "TOUCH_UP";
- case EVENT_TYPE_TOUCH_MOVE:
- return "TOUCH_MOVE";
- case EVENT_TYPE_TOUCH_CANCEL:
- return "TOUCH_CANCEL";
- case EVENT_TYPE_WHEEL:
- return "WHEEL";
- case EVENT_TYPE_CHANGED:
- return "CHANGED";
- case EVENT_TYPE_KEY_DOWN:
- return "KEY_DOWN";
- case EVENT_TYPE_KEY_UP:
- return "KEY_UP";
- case EVENT_TYPE_SHORTCUT:
- return "SHORT_CUT";
- case EVENT_TYPE_CONTEXT_MENU:
- return "CONTEXT_MENU";
- default:
- return "[UNKNOWN]";
- }
- }
-};
-
-void ShowDebugInfoSettingsWindow(TBWidget *root) {
- new DebugSettingsWindow(root);
-}
-
-#endif // TB_RUNTIME_DEBUG_INFO
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_debug.h b/src/modules/ui/turbobadger/tb/tb_debug.h
deleted file mode 100644
index 45abf13c8..000000000
--- a/src/modules/ui/turbobadger/tb/tb_debug.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_types.h"
-
-namespace tb {
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-
-class TBDebugInfo {
-public:
- TBDebugInfo();
-
- enum SETTING {
- /** Show widgets bounds */
- LAYOUT_BOUNDS,
- /** Show child widget clipping set by some widgets. */
- LAYOUT_CLIPPING,
- /** Show highlights on widgets that recalculate their preferred
- size, and those who recalculate their layout. */
- LAYOUT_PS_DEBUGGING,
- /** Show render batch info and log batch info in the debug
- output. It depends on the renderer backend if this is available. */
- RENDER_BATCHES,
- /** Render the bitmap fragments of the skin. */
- RENDER_SKIN_BITMAP_FRAGMENTS,
- /** Render the bitmap fragments of the font that's set on the hovered
- or focused widget. */
- RENDER_FONT_BITMAP_FRAGMENTS,
-
- NUM_SETTINGS
- };
- int settings[NUM_SETTINGS];
-};
-
-extern TBDebugInfo g_tb_debug;
-
-/** Show a window containing runtime debugging settings. */
-void ShowDebugInfoSettingsWindow(class TBWidget *root);
-
-#define TB_DEBUG_SETTING(setting) g_tb_debug.settings[TBDebugInfo::setting]
-#define TB_IF_DEBUG_SETTING(setting, code) \
- if (TB_DEBUG_SETTING(setting)) { \
- code; \
- }
-
-#else // TB_RUNTIME_DEBUG_INFO
-
-/** Show a window containing runtime debugging settings. */
-#define ShowDebugInfoSettingsWindow(root) ((void)0)
-
-#define TB_DEBUG_SETTING(setting) false
-#define TB_IF_DEBUG_SETTING(setting, code)
-
-#endif // TB_RUNTIME_DEBUG_INFO
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_dimension.cpp b/src/modules/ui/turbobadger/tb/tb_dimension.cpp
deleted file mode 100644
index 0168c39ff..000000000
--- a/src/modules/ui/turbobadger/tb/tb_dimension.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_dimension.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-#include "tb_types.h"
-#include "tb_value.h"
-#include "core/StringUtil.h"
-#include
-
-namespace tb {
-
-// == TBDimensionConverter ==================================================================================
-
-void TBDimensionConverter::setDPI(int srcDpi, int dstDpi) {
- m_src_dpi = srcDpi;
- m_dst_dpi = dstDpi;
- m_dst_dpi_str.clear();
- if (needConversion()) {
- m_dst_dpi_str = core::string::format("@%d", m_dst_dpi);
- }
-}
-
-void TBDimensionConverter::getDstDPIFilename(const char *filename, TBTempBuffer *tempbuf) const {
- int dot_pos = 0;
- for (dot_pos = (int)SDL_strlen(filename) - 1; dot_pos > 0; dot_pos--) {
- if (filename[dot_pos] == '.') {
- break;
- }
- }
- tempbuf->resetAppendPos();
- tempbuf->append(filename, dot_pos);
- tempbuf->appendString(getDstDPIStr());
- tempbuf->appendString(filename + dot_pos);
-}
-
-int TBDimensionConverter::dpToPx(int dp) const {
- return (int)roundf(dpToPxF((float)dp));
-}
-
-float TBDimensionConverter::dpToPxF(float dp) const {
- if (dp <= TB_INVALID_DIMENSION || dp == 0 || !needConversion()) {
- return dp;
- }
- return dp * (float)m_dst_dpi / (float)m_src_dpi;
-}
-
-int TBDimensionConverter::mmToPx(int mm) const {
- return (int)roundf(mmToPxF((float)mm));
-}
-
-float TBDimensionConverter::mmToPxF(float mm) const {
- if (mm <= TB_INVALID_DIMENSION || mm == 0) {
- return mm;
- }
- return mm * (float)TBSystem::getDPI() / 25.4F;
-}
-
-int TBDimensionConverter::getPxFromString(const char *str, int defValue) const {
- if ((str == nullptr) || !is_start_of_number(str)) {
- return defValue;
- }
- const int len = SDL_strlen(str);
- const int val = SDL_atoi(str);
- if (len > 2 && SDL_strcmp(str + len - 2, "px") == 0) {
- return val;
- }
- if (len > 2 && SDL_strcmp(str + len - 2, "mm") == 0) {
- return mmToPx(val);
- }
- // "dp", unspecified or unknown unit is treated as dp.
- return dpToPx(val);
-}
-
-float TBDimensionConverter::getPxFromStringF(const char *str, float defValue) const {
- if ((str == nullptr) || !is_start_of_number(str)) {
- return defValue;
- }
- const int len = SDL_strlen(str);
- const float val = (float)SDL_atof(str);
- if (len > 2 && SDL_strcmp(str + len - 2, "px") == 0) {
- return val;
- }
- if (len > 2 && SDL_strcmp(str + len - 2, "mm") == 0) {
- return mmToPxF(val);
- }
- // "dp", unspecified or unknown unit is treated as dp.
- return dpToPxF(val);
-}
-
-int TBDimensionConverter::getPxFromValue(TBValue *value, int defValue) const {
- if (value == nullptr) {
- return defValue;
- }
- if (value->getType() == TBValue::TYPE_INT) {
- return dpToPx(value->getInt());
- }
- if (value->getType() == TBValue::TYPE_FLOAT) {
- return (int)roundf(dpToPxF(value->getFloat()));
- }
- return getPxFromString(value->getString(), defValue);
-}
-
-float TBDimensionConverter::getPxFromValueF(TBValue *value, float defValue) const {
- if (value == nullptr) {
- return defValue;
- }
- if (value->getType() == TBValue::TYPE_INT) {
- return dpToPxF((float)value->getInt());
- }
- if (value->getType() == TBValue::TYPE_FLOAT) {
- return dpToPxF(value->getFloat());
- }
- return getPxFromStringF(value->getString(), defValue);
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_dimension.h b/src/modules/ui/turbobadger/tb/tb_dimension.h
deleted file mode 100644
index 57925c327..000000000
--- a/src/modules/ui/turbobadger/tb/tb_dimension.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_debug.h"
-#include "tb_str.h"
-#include "tb_types.h"
-
-namespace tb {
-
-/** Dimensions <= this value will be untouched by conversion in TBDimensionConverter.
- To preserve special constants, those must be <= this value. */
-#define TB_INVALID_DIMENSION -5555
-
-class TBTempBuffer;
-class TBValue;
-
-/** TBDimensionConverter converts device independant points
- to pixels, based on two DPI values.
- Dimensions in Turbo Badger are normally in pixels (if not specified differently)
- and conversion normally take place when loading skin. */
-class TBDimensionConverter {
- int m_src_dpi; ///< The source DPI (Normally the base_dpi from skin).
- int m_dst_dpi; ///< The destination DPI (Normally the supported skin DPI nearest to TBSystem::getDPI).
- core::String m_dst_dpi_str; ///< The file suffix that should be used to load bitmaps in destinatin DPI.
-public:
- TBDimensionConverter() : m_src_dpi(100), m_dst_dpi(100) {
- }
-
- /** Set the source and destination DPI that will affect the conversion. */
- void setDPI(int srcDpi, int dstDpi);
-
- /** Get the source DPI. */
- int getSrcDPI() const {
- return m_src_dpi;
- }
-
- /** Get the destination DPI. */
- int getDstDPI() const {
- return m_dst_dpi;
- }
-
- /** Get the file name suffix that should be used to load bitmaps in the destination DPI.
- Examples: "@96", "@196" */
- const char *getDstDPIStr() const {
- return m_dst_dpi_str.c_str();
- }
-
- /** Get the file name with destination DPI suffix (F.ex "foo.png" becomes "foo@192.png").
- The temp buffer will contain the resulting file name. */
- void getDstDPIFilename(const char *filename, TBTempBuffer *tempbuf) const;
-
- /** Return true if the source and destinatin DPI are different. */
- bool needConversion() const {
- return m_src_dpi != m_dst_dpi;
- }
-
- /** Convert device independant point to pixel. */
- int dpToPx(int dp) const;
- float dpToPxF(float dp) const;
-
- /** Convert millimeter to pixel. */
- int mmToPx(int mm) const;
- float mmToPxF(float mm) const;
-
- /** Get a pixel value from string in any of the following formats:
- str may be nullptr. def_value is returned on fail.
-
- Device independent point: "1", "1dp"
- Pixel value: "1px"
- */
- int getPxFromString(const char *str, int def_value) const;
- float getPxFromStringF(const char *str, float def_value) const;
-
- /** Get a pixel value from TBValue.
- value may be nullptr. def_value is returned on fail.
-
- Number formats are treated as dp.
- String format is treated like for GetPxFromString.
- */
- int getPxFromValue(TBValue *value, int def_value) const;
- float getPxFromValueF(TBValue *value, float def_value) const;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_editfield.cpp b/src/modules/ui/turbobadger/tb/tb_editfield.cpp
deleted file mode 100644
index 22296189b..000000000
--- a/src/modules/ui/turbobadger/tb/tb_editfield.cpp
+++ /dev/null
@@ -1,615 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_editfield.h"
-#include "tb_font_renderer.h"
-#include "tb_language.h"
-#include "tb_menu_window.h"
-#include "tb_select.h"
-#include "tb_skin_util.h"
-#include "tb_style_edit_content.h"
-#include "tb_system.h"
-#include "tb_widget_skin_condition_context.h"
-#include "tb_widgets_reader.h"
-
-namespace tb {
-
-const int CARET_BLINK_TIME = 500;
-const int SELECTION_SCROLL_DELAY = 1000 / 30;
-
-/** Get the delta that should be scrolled if dragging the pointer outside the range min-max */
-int getSelectionScrollSpeed(int pointerpos, int min, int max) {
- int d = 0;
- if (pointerpos < min) {
- d = pointerpos - min;
- } else if (pointerpos > max) {
- d = pointerpos - max;
- }
- d *= d;
- d /= 40;
- return (pointerpos < min) ? -d : d;
-}
-
-TBEditField::TBEditField() : m_edit_type(EDIT_TYPE_TEXT), m_adapt_to_content_size(false), m_virtual_width(250) {
- setIsFocusable(true);
- setWantLongClick(true);
- addChild(&m_scrollbar_x);
- addChild(&m_scrollbar_y);
- addChild(&m_root);
- m_root.setGravity(WIDGET_GRAVITY_ALL);
- m_scrollbar_x.setGravity(WIDGET_GRAVITY_BOTTOM | WIDGET_GRAVITY_LEFT_RIGHT);
- m_scrollbar_y.setGravity(WIDGET_GRAVITY_RIGHT | WIDGET_GRAVITY_TOP_BOTTOM);
- m_scrollbar_y.setAxis(AXIS_Y);
- int scrollbar_y_w = m_scrollbar_y.getPreferredSize().pref_w;
- int scrollbar_x_h = m_scrollbar_x.getPreferredSize().pref_h;
- m_scrollbar_x.setRect(TBRect(0, -scrollbar_x_h, -scrollbar_y_w, scrollbar_x_h));
- m_scrollbar_y.setRect(TBRect(-scrollbar_y_w, 0, scrollbar_y_w, 0));
- m_scrollbar_x.setOpacity(0);
- m_scrollbar_y.setOpacity(0);
-
- setSkinBg(TBIDC("TBEditField"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- m_style_edit.setListener(this);
-
- m_root.setRect(getVisibleRect());
-
- m_placeholder.setTextAlign(TB_TEXT_ALIGN_LEFT);
-
- m_content_factory.editfield = this;
- m_style_edit.setContentFactory(&m_content_factory);
-}
-
-TBEditField::~TBEditField() {
- removeChild(&m_root);
- removeChild(&m_scrollbar_y);
- removeChild(&m_scrollbar_x);
-}
-
-TBRect TBEditField::getVisibleRect() {
- TBRect rect = getPaddingRect();
- if (m_scrollbar_y.getOpacity() != 0.0F) {
- rect.w -= m_scrollbar_y.getRect().w;
- }
- if (m_scrollbar_x.getOpacity() != 0.0F) {
- rect.h -= m_scrollbar_x.getRect().h;
- }
- return rect;
-}
-
-void TBEditField::updateScrollbarVisibility(bool multiline) {
- bool enable_vertical = multiline && !m_adapt_to_content_size;
- m_scrollbar_y.setOpacity(enable_vertical ? 1.F : 0.F);
- m_root.setRect(getVisibleRect());
-}
-
-void TBEditField::setAdaptToContentSize(bool adapt) {
- if (m_adapt_to_content_size == adapt) {
- return;
- }
- m_adapt_to_content_size = adapt;
- updateScrollbarVisibility(getMultiline());
-}
-
-void TBEditField::setVirtualWidth(int virtualWidth) {
- if (m_virtual_width == virtualWidth) {
- return;
- }
- m_virtual_width = virtualWidth;
-
- if (m_adapt_to_content_size && m_style_edit.packed.wrapping) {
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
- }
-}
-
-void TBEditField::setMultiline(bool multiline) {
- if (multiline == getMultiline()) {
- return;
- }
- updateScrollbarVisibility(multiline);
- m_style_edit.setMultiline(multiline);
- setWrapping(multiline);
- invalidateSkinStates();
- TBWidget::invalidate();
-}
-
-void TBEditField::setStyling(bool styling) {
- m_style_edit.setStyling(styling);
-}
-
-void TBEditField::setReadOnly(bool readonly) {
- if (readonly == getReadOnly()) {
- return;
- }
- m_style_edit.setReadOnly(readonly);
- invalidateSkinStates();
- TBWidget::invalidate();
-}
-
-void TBEditField::setWrapping(bool wrapping) {
- if (wrapping == getWrapping()) {
- return;
- }
-
- m_style_edit.setWrapping(wrapping);
-
- // Invalidate the layout when the wrap mode change and we should adapt our size to it
- if (m_adapt_to_content_size) {
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
- }
-}
-
-void TBEditField::setEditType(EDIT_TYPE type) {
- if (m_edit_type == type) {
- return;
- }
- m_edit_type = type;
- m_style_edit.setPassword(type == EDIT_TYPE_PASSWORD);
- invalidateSkinStates();
- TBWidget::invalidate();
-}
-
-bool TBEditField::getCustomSkinCondition(const TBSkinCondition::CONDITION_INFO &info) {
- if (info.custom_prop == TBIDC("edit-type")) {
- switch (m_edit_type) {
- case EDIT_TYPE_TEXT:
- return info.value == TBIDC("text");
- case EDIT_TYPE_SEARCH:
- return info.value == TBIDC("search");
- case EDIT_TYPE_PASSWORD:
- return info.value == TBIDC("password");
- case EDIT_TYPE_EMAIL:
- return info.value == TBIDC("email");
- case EDIT_TYPE_PHONE:
- return info.value == TBIDC("phone");
- case EDIT_TYPE_URL:
- return info.value == TBIDC("url");
- case EDIT_TYPE_NUMBER:
- return info.value == TBIDC("number");
- }
- } else if (info.custom_prop == TBIDC("multiline")) {
- const bool ml = ((uint32_t)info.value) == 0U;
- return ml == !getMultiline();
- } else if (info.custom_prop == TBIDC("readonly")) {
- const bool ro = ((uint32_t)info.value) == 0U;
- return ro == !getReadOnly();
- }
- return false;
-}
-
-void TBEditField::scrollTo(int x, int y) {
- int old_x = m_scrollbar_x.getValue();
- int old_y = m_scrollbar_y.getValue();
- m_style_edit.setScrollPos(x, y);
- if (old_x != m_scrollbar_x.getValue() || old_y != m_scrollbar_y.getValue()) {
- TBWidget::invalidate();
- }
-}
-
-TBWidget::ScrollInfo TBEditField::getScrollInfo() {
- ScrollInfo info;
- info.min_x = static_cast(m_scrollbar_x.getMinValue());
- info.min_y = static_cast(m_scrollbar_y.getMinValue());
- info.max_x = static_cast(m_scrollbar_x.getMaxValue());
- info.max_y = static_cast(m_scrollbar_y.getMaxValue());
- info.x = m_scrollbar_x.getValue();
- info.y = m_scrollbar_y.getValue();
- return info;
-}
-
-bool TBEditField::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_scrollbar_x) {
- m_style_edit.setScrollPos(m_scrollbar_x.getValue(), m_style_edit.scroll_y);
- onScroll(m_scrollbar_x.getValue(), m_style_edit.scroll_y);
- return true;
- }
- if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_scrollbar_y) {
- m_style_edit.setScrollPos(m_style_edit.scroll_x, m_scrollbar_y.getValue());
- onScroll(m_style_edit.scroll_x, m_scrollbar_y.getValue());
- return true;
- }
- if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE) {
- int old_val = m_scrollbar_y.getValue();
- m_scrollbar_y.setValue(old_val + ev.delta_y * TBSystem::getPixelsPerLine());
- return m_scrollbar_y.getValue() != old_val;
- }
- if (ev.type == EVENT_TYPE_POINTER_DOWN && ev.target == this) {
- TBRect padding_rect = getPaddingRect();
- if (m_style_edit.mouseDown(TBPoint(ev.target_x - padding_rect.x, ev.target_y - padding_rect.y), 1, ev.count,
- TB_MODIFIER_NONE, ev.button_type == TB_TOUCH)) {
- // Post a message to start selection scroll
- postMessageDelayed(TBIDC("selscroll"), nullptr, SELECTION_SCROLL_DELAY);
- return true;
- }
- } else if (ev.type == EVENT_TYPE_POINTER_MOVE && ev.target == this) {
- TBRect padding_rect = getPaddingRect();
- return m_style_edit.mouseMove(TBPoint(ev.target_x - padding_rect.x, ev.target_y - padding_rect.y));
- } else if (ev.type == EVENT_TYPE_POINTER_UP && ev.target == this) {
- TBRect padding_rect = getPaddingRect();
- return m_style_edit.mouseUp(TBPoint(ev.target_x - padding_rect.x, ev.target_y - padding_rect.y), 1,
- TB_MODIFIER_NONE, ev.button_type == TB_TOUCH);
- } else if (ev.type == EVENT_TYPE_KEY_DOWN) {
- if (m_style_edit.keyDown(ev.key, ev.special_key, ev.modifierkeys)) {
- if (_var) {
- _var->setVal(getText().c_str());
- _var->markClean();
- }
- return true;
- }
- return false;
- } else if (ev.type == EVENT_TYPE_KEY_UP) {
- return true;
- } else if ((ev.type == EVENT_TYPE_CLICK && ev.target->getID() == TBIDC("popupmenu")) ||
- (ev.type == EVENT_TYPE_SHORTCUT)) {
- if (ev.ref_id == TBIDC("cut") && !m_style_edit.packed.read_only) {
- m_style_edit.cut();
- if (_var) {
- _var->setVal(getText().c_str());
- _var->markClean();
- }
- } else if (ev.ref_id == TBIDC("copy")) {
- m_style_edit.copy();
- } else if (ev.ref_id == TBIDC("paste") && !m_style_edit.packed.read_only) {
- m_style_edit.paste();
- if (_var) {
- _var->setVal(getText().c_str());
- _var->markClean();
- }
- } else if (ev.ref_id == TBIDC("delete") && !m_style_edit.packed.read_only) {
- m_style_edit.del();
- if (_var) {
- _var->setVal(getText().c_str());
- _var->markClean();
- }
- } else if (ev.ref_id == TBIDC("undo") && !m_style_edit.packed.read_only) {
- m_style_edit.undo();
- if (_var) {
- _var->setVal(getText().c_str());
- _var->markClean();
- }
- } else if (ev.ref_id == TBIDC("redo") && !m_style_edit.packed.read_only) {
- m_style_edit.redo();
- if (_var) {
- _var->setVal(getText().c_str());
- _var->markClean();
- }
- } else if (ev.ref_id == TBIDC("selectall")) {
- m_style_edit.selection.selectAll();
- } else {
- return false;
- }
- return true;
- } else if (ev.type == EVENT_TYPE_CONTEXT_MENU && ev.target == this) {
- TBPoint pos_in_root(ev.target_x, ev.target_y);
- ev.target->convertToRoot(pos_in_root.x, pos_in_root.y);
-
- if (TBMenuWindow *menu = new TBMenuWindow(ev.target, TBIDC("popupmenu"))) {
- TBGenericStringItemSource *source = menu->getList()->getDefaultSource();
- source->addItem(new TBGenericStringItem(g_tb_lng->getString(TBIDC("cut")), TBIDC("cut")));
- source->addItem(new TBGenericStringItem(g_tb_lng->getString(TBIDC("copy")), TBIDC("copy")));
- source->addItem(new TBGenericStringItem(g_tb_lng->getString(TBIDC("paste")), TBIDC("paste")));
- source->addItem(new TBGenericStringItem(g_tb_lng->getString(TBIDC("delete")), TBIDC("delete")));
- source->addItem(new TBGenericStringItem("-"));
- source->addItem(new TBGenericStringItem(g_tb_lng->getString(TBIDC("selectall")), TBIDC("selectall")));
- menu->show(source, TBPopupAlignment(pos_in_root), -1);
- }
- return true;
- }
- return false;
-}
-
-void TBEditField::onPaint(const PaintProps &paintProps) {
- TBRect visible_rect = getVisibleRect();
-
- bool clip = m_scrollbar_x.canScroll() || m_scrollbar_y.canScroll();
- TBRect old_clip;
- if (clip) {
- old_clip = g_renderer->setClipRect(visible_rect, true);
- }
-
- int trans_x = visible_rect.x;
- int trans_y = visible_rect.y;
- g_renderer->translate(trans_x, trans_y);
-
- // Draw text content, caret etc.
- visible_rect.x = visible_rect.y = 0;
- m_style_edit.paint(visible_rect, getCalculatedFontDescription(), paintProps.text_color);
-
- // If empty, draw placeholder text with some opacity.
- if (m_style_edit.isEmpty()) {
- float old_opacity = g_renderer->getOpacity();
- g_renderer->setOpacity(old_opacity * g_tb_skin->getDefaultPlaceholderOpacity());
- TBRect placeholder_rect(visible_rect.x, visible_rect.y, visible_rect.w, getFont()->getHeight());
- m_placeholder.paint(this, placeholder_rect, paintProps.text_color);
- g_renderer->setOpacity(old_opacity);
- }
- g_renderer->translate(-trans_x, -trans_y);
-
- if (clip) {
- g_renderer->setClipRect(old_clip, false);
- }
-}
-
-void TBEditField::setTextFormatted(const char *format, ...) {
- va_list args;
- va_start(args, format);
- char buf[1024];
- SDL_vsnprintf(buf, sizeof(buf), format, args);
- buf[sizeof(buf) - 1] = '\0';
- setText(buf);
- va_end(args);
-}
-
-void TBEditField::onPaintChildren(const PaintProps &paintProps) {
- TBWidget::onPaintChildren(paintProps);
-
- // Draw fadeout skin at the needed edges.
- drawEdgeFadeout(getVisibleRect(), TBIDC("TBEditField.fadeout_x"), TBIDC("TBEditField.fadeout_y"),
- m_scrollbar_x.getValue(), m_scrollbar_y.getValue(),
- (int)(m_scrollbar_x.getMaxValue() - m_scrollbar_x.getValueDouble()),
- (int)(m_scrollbar_y.getMaxValue() - m_scrollbar_y.getValueDouble()));
-}
-
-void TBEditField::onAdded() {
- m_style_edit.setFont(getCalculatedFontDescription());
-}
-
-void TBEditField::onFontChanged() {
- m_style_edit.setFont(getCalculatedFontDescription());
-}
-
-void TBEditField::onFocusChanged(bool focused) {
- m_style_edit.focus(focused);
-}
-
-void TBEditField::onResized(int oldW, int oldH) {
- // Make the scrollbars move
- TBWidget::onResized(oldW, oldH);
-
- TBRect visible_rect = getVisibleRect();
- m_style_edit.setLayoutSize(visible_rect.w, visible_rect.h, false);
-
- updateScrollbars();
-}
-
-PreferredSize TBEditField::onCalculatePreferredContentSize(const SizeConstraints &constraints) {
- int font_height = getFont()->getHeight();
- PreferredSize ps;
- if (m_adapt_to_content_size) {
- int old_layout_width = m_style_edit.layout_width;
- int old_layout_height = m_style_edit.layout_height;
- if (m_style_edit.packed.wrapping) {
- // If we have wrapping enabled, we have to set a virtual width and format the text
- // so we can get the actual content width with a constant result every time.
- // If the layouter does not respect our size constraints in the end, we may
- // get a completly different content height due to different wrapping.
- // To fix that, we need to layout in 2 passes.
-
- // A hacky fix is to do something we probably shouldn't: use the old layout width
- // as virtual width for the new.
- // int layout_width = old_layout_width > 0 ? Max(old_layout_width, m_virtual_width) : m_virtual_width;
- int layout_width = m_virtual_width;
- if (constraints.available_w != SizeConstraints::NO_RESTRICTION) {
- layout_width = constraints.available_w;
- if (TBSkinElement *bg_skin = getSkinBgElement()) {
- layout_width -= bg_skin->padding_left + bg_skin->padding_right;
- }
- }
-
- m_style_edit.setLayoutSize(layout_width, old_layout_height, true);
- ps.size_dependency = SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH;
- }
- int width = m_style_edit.getContentWidth();
- int height = m_style_edit.getContentHeight();
- if (m_style_edit.packed.wrapping) {
- m_style_edit.setLayoutSize(old_layout_width, old_layout_height, true);
- }
- height = Max(height, font_height);
-
- ps.min_w = ps.pref_w /*= ps.max_w*/ = width; // should go with the hack above.
- // ps.min_w = ps.pref_w = ps.max_w = width;
- ps.min_h = ps.pref_h = ps.max_h = height;
- } else {
- ps.pref_h = ps.min_h = font_height;
- if (m_style_edit.packed.multiline_on) {
- ps.pref_w = font_height * 10;
- ps.pref_h = font_height * 5;
- } else {
- ps.max_h = ps.pref_h;
- }
- }
- return ps;
-}
-
-void TBEditField::onMessageReceived(TBMessage *msg) {
- if (msg->message == TBIDC("blink")) {
- m_style_edit.caret.on = !m_style_edit.caret.on;
- m_style_edit.caret.invalidate();
-
- // Post another blink message so we blink again.
- postMessageDelayed(TBIDC("blink"), nullptr, CARET_BLINK_TIME);
- } else if (msg->message == TBIDC("selscroll") && captured_widget == this) {
- // Get scroll speed from where mouse is relative to the padding rect.
- TBRect padding_rect = getVisibleRect().shrink(2, 2);
- int dx = getSelectionScrollSpeed(pointer_move_widget_x, padding_rect.x, padding_rect.x + padding_rect.w);
- int dy = getSelectionScrollSpeed(pointer_move_widget_y, padding_rect.y, padding_rect.y + padding_rect.h);
- m_scrollbar_x.setValue(m_scrollbar_x.getValue() + dx);
- m_scrollbar_y.setValue(m_scrollbar_y.getValue() + dy);
-
- // Handle mouse move at the new scroll position, so selection is updated
- if ((dx != 0) || (dy != 0)) {
- m_style_edit.mouseMove(TBPoint(pointer_move_widget_x, pointer_move_widget_y));
- }
-
- // Post another setscroll message so we continue scrolling if we still should.
- if (m_style_edit.select_state != 0) {
- postMessageDelayed(TBIDC("selscroll"), nullptr, SELECTION_SCROLL_DELAY);
- }
- }
-}
-
-void TBEditField::onChange() {
- // Invalidate the layout when the content change and we should adapt our size to it
- if (m_adapt_to_content_size) {
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
- }
-
- TBWidgetEvent ev(EVENT_TYPE_CHANGED);
- invokeEvent(ev);
-}
-
-bool TBEditField::onEnter() {
- return false;
-}
-
-void TBEditField::invalidate(const TBRect &rect) {
- TBWidget::invalidate();
-}
-
-void TBEditField::drawString(int32_t x, int32_t y, TBFontFace *font, const TBColor &color, const char *str,
- int32_t len) {
- font->drawString(x, y, color, str, len);
-}
-
-void TBEditField::drawRect(const TBRect &rect, const TBColor &color) {
- g_tb_skin->paintRect(rect, color, 1);
-}
-
-void TBEditField::drawRectFill(const TBRect &rect, const TBColor &color) {
- g_tb_skin->paintRectFill(rect, color);
-}
-
-void TBEditField::drawTextSelectionBg(const TBRect &rect) {
- TBWidgetSkinConditionContext context(this);
- g_tb_skin->paintSkin(rect, TBIDC("TBEditField.selection"), static_cast(getAutoState()), context);
-}
-
-void TBEditField::drawContentSelectionFg(const TBRect &rect) {
- TBWidgetSkinConditionContext context(this);
- g_tb_skin->paintSkin(rect, TBIDC("TBEditField.selection"), static_cast(getAutoState()), context);
-}
-
-void TBEditField::drawCaret(const TBRect &rect) {
- if (getIsFocused() && !m_style_edit.packed.read_only) {
- drawTextSelectionBg(rect);
- }
-}
-
-void TBEditField::scroll(int32_t dx, int32_t dy) {
- TBWidget::invalidate();
- m_scrollbar_x.setValue(m_style_edit.scroll_x);
- m_scrollbar_y.setValue(m_style_edit.scroll_y);
-}
-
-void TBEditField::updateScrollbars() {
- int32_t w = m_style_edit.layout_width;
- int32_t h = m_style_edit.layout_height;
- m_scrollbar_x.setLimits(0, m_style_edit.getContentWidth() - w, w);
- m_scrollbar_y.setLimits(0, m_style_edit.getContentHeight() - h, h);
-}
-
-void TBEditField::caretBlinkStart() {
- // Post the delayed blink message if we don't already have one
- if (getMessageByID(TBIDC("blink")) == nullptr) {
- postMessageDelayed(TBIDC("blink"), nullptr, CARET_BLINK_TIME);
- }
-}
-
-void TBEditField::caretBlinkStop() {
- // Remove the blink message if we have one
- if (TBMessage *msg = getMessageByID(TBIDC("blink"))) {
- deleteMessage(msg);
- }
-}
-
-// == TBEditFieldScrollRoot =======================================================================
-
-void TBEditFieldScrollRoot::onPaintChildren(const PaintProps &paintProps) {
- // Avoid setting clipping (can be expensive) if we have no children to paint anyway.
- if (getFirstChild() == nullptr) {
- return;
- }
- // Clip children
- TBRect old_clip_rect = g_renderer->setClipRect(getPaddingRect(), true);
- TBWidget::onPaintChildren(paintProps);
- g_renderer->setClipRect(old_clip_rect, false);
-}
-
-void TBEditFieldScrollRoot::getChildTranslation(int &x, int &y) const {
- TBEditField *edit_field = static_cast(getParent());
- x = (int)-edit_field->getStyleEdit()->scroll_x;
- y = (int)-edit_field->getStyleEdit()->scroll_y;
-}
-
-WIDGET_HIT_STATUS TBEditFieldScrollRoot::getHitStatus(int x, int y) {
- // Return no hit on this widget, but maybe on any of the children.
- if ((TBWidget::getHitStatus(x, y) != 0U) && (getWidgetAt(x, y, false) != nullptr)) {
- return WIDGET_HIT_STATUS_HIT;
- }
- return WIDGET_HIT_STATUS_NO_HIT;
-}
-
-// == TBTextFragmentContentWidget =================================================================
-
-class TBTextFragmentContentWidget : public TBTextFragmentContent {
-public:
- TBTextFragmentContentWidget(TBWidget *parent, TBWidget *widget);
- virtual ~TBTextFragmentContentWidget();
-
- virtual void updatePos(const TBBlock *block, int x, int y);
- virtual int32_t getWidth(const TBBlock *block, TBFontFace *font, TBTextFragment *fragment);
- virtual int32_t getHeight(const TBBlock *block, TBFontFace *font, TBTextFragment *fragment);
- virtual int32_t getBaseline(const TBBlock *block, TBFontFace *font, TBTextFragment *fragment);
-
-private:
- TBWidget *m_widget;
-};
-
-TBTextFragmentContentWidget::TBTextFragmentContentWidget(TBWidget *parent, TBWidget *widget) : m_widget(widget) {
- parent->getContentRoot()->addChild(widget);
-}
-
-TBTextFragmentContentWidget::~TBTextFragmentContentWidget() {
- m_widget->removeFromParent();
- delete m_widget;
-}
-
-void TBTextFragmentContentWidget::updatePos(const TBBlock *block, int x, int y) {
- m_widget->setRect(TBRect(x, y, getWidth(block, nullptr, nullptr), getHeight(block, nullptr, nullptr)));
-}
-
-int32_t TBTextFragmentContentWidget::getWidth(const TBBlock *block, TBFontFace *font, TBTextFragment *fragment) {
- return m_widget->getRect().w != 0 ? m_widget->getRect().w : m_widget->getPreferredSize().pref_w;
-}
-
-int32_t TBTextFragmentContentWidget::getHeight(const TBBlock *block, TBFontFace *font, TBTextFragment *fragment) {
- return m_widget->getRect().h != 0 ? m_widget->getRect().h : m_widget->getPreferredSize().pref_h;
-}
-
-int32_t TBTextFragmentContentWidget::getBaseline(const TBBlock *block, TBFontFace *font, TBTextFragment *fragment) {
- const int height = getHeight(block, font, fragment);
- return (height + block->calculateBaseline(font)) / 2;
-}
-
-// == TBEditFieldContentFactory ===================================================================
-
-int TBEditFieldContentFactory::getContent(const char *text) {
- return TBTextFragmentContentFactory::getContent(text);
-}
-
-TBTextFragmentContent *TBEditFieldContentFactory::createFragmentContent(const char *text, int textLen) {
- if (SDL_strncmp(text, "loadData(widget, text + 8, textLen - 9);
- return cw;
- }
- delete widget;
- }
- }
-
- return TBTextFragmentContentFactory::createFragmentContent(text, textLen);
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_editfield.h b/src/modules/ui/turbobadger/tb/tb_editfield.h
deleted file mode 100644
index ee5d6fd3e..000000000
--- a/src/modules/ui/turbobadger/tb/tb_editfield.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_msg.h"
-#include "tb_style_edit.h"
-#include "tb_widgets_common.h"
-#include "core/Log.h"
-
-namespace tb {
-
-/** EDIT_TYPE - These types does not restrict input (may change in the future).
- They are just hints for virtual keyboard, so it can show special keys. */
-enum EDIT_TYPE {
- EDIT_TYPE_TEXT,
- EDIT_TYPE_SEARCH,
- EDIT_TYPE_PASSWORD,
- EDIT_TYPE_EMAIL,
- EDIT_TYPE_PHONE,
- EDIT_TYPE_URL,
- EDIT_TYPE_NUMBER
-};
-
-/** The default content factory for embedded content in TBEditField with styling enabled.
-
- Creates all that TBTextFragmentContentFactory creates by default,
- and any type of widget from a inline resource string.
-
- Syntax: Where xxx is parsed by TBWidgetsReader.
-
- Example - Create a button with id "hello":
-
-
-
- Example - Create a image from skin element "Icon48":
-
-
-*/
-
-class TBEditFieldContentFactory : public TBTextFragmentContentFactory {
-public:
- class TBEditField *editfield;
- virtual int getContent(const char *text);
- virtual TBTextFragmentContent *createFragmentContent(const char *text, int text_len);
-};
-
-/** TBEditFieldScrollRoot - Internal for TBEditField.
- Acts as a scrollable container for any widget created as embedded content. */
-
-class TBEditFieldScrollRoot : public TBWidget {
-private: // May only be used by TBEditField.
- friend class TBEditField;
- TBEditFieldScrollRoot() {
- }
-
-public:
- virtual void onPaintChildren(const PaintProps &paint_props);
- virtual void getChildTranslation(int &x, int &y) const;
- virtual WIDGET_HIT_STATUS getHitStatus(int x, int y);
-};
-
-/** TBEditField is a one line or multi line textfield that is editable or
- read-only. It can also be a passwordfield by calling
- SetEditType(EDIT_TYPE_PASSWORD).
-
- It may perform styling of text and contain custom embedded content,
- if enabled by SetStyling(true). Disabled by default.
-*/
-
-class TBEditField : public TBWidget, private TBStyleEditListener, public TBMessageHandler {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBEditField, TBWidget);
-
- TBEditField();
- ~TBEditField();
-
- /** Get the visible rect (the GetPaddingRect() minus any scrollbars) */
- TBRect getVisibleRect();
-
- /** Set if multiple lines should be allowed or not.
- Will also set wrapping (to true if multiline, and false if not). */
- void setMultiline(bool multiline);
- bool getMultiline() const {
- return m_style_edit.packed.multiline_on;
- }
-
- /** Set if styling should be enabled or not. Default is disabled. */
- void setStyling(bool styling);
- bool getStyling() const {
- return m_style_edit.packed.styling_on;
- }
-
- /** Set if read only mode should be enabled. Default is disabled.
- In read only mode, editing is disabled and caret is hidden.
- The user is still able to focus, select and copy text. */
- void setReadOnly(bool readonly);
- bool getReadOnly() const {
- return m_style_edit.packed.read_only;
- }
-
- /** Set to true if the text should wrap if multi line is enabled (See SetMultiline). */
- void setWrapping(bool wrapping);
- bool getWrapping() const {
- return m_style_edit.packed.wrapping;
- }
-
- /** Set to true if the preferred size of this editfield should adapt to the
- size of the content (disabled by default).
- If wrapping is enabled, the result is partly dependant on the virtual
- width (See SetVirtualWidth). */
- void setAdaptToContentSize(bool adapt);
- bool getAdaptToContentSize() const {
- return m_adapt_to_content_size;
- }
-
- /** The virtual width is only used if the size is adapting to content size
- (See SetAdaptToContentSize) and wrapping is enabled.
- The virtual width will be used to layout the text and see which resulting
- width and height it takes up. The width that is actually used depends on
- the content. It is also up to the the layouter to decide if the size
- should be respected or not. The default is 250. */
- void setVirtualWidth(int virtual_width);
- int getVirtualWidth() const {
- return m_virtual_width;
- }
-
- /** Get the TBStyleEdit object that contains more functions and settings. */
- TBStyleEdit *getStyleEdit() {
- return &m_style_edit;
- }
-
- /** Set the edit type that is a hint for virtual keyboards about what the
- content should be. */
- void setEditType(EDIT_TYPE type);
- EDIT_TYPE getEditType() const {
- return m_edit_type;
- }
-
- /** Support custom skin condition properties. Currently supported properties are:
- "edit-type", matching those of EDIT_TYPE.
- "multiline", matching 1 if multiline mode is enabled.
- "readonly", matching 1 if readonly mode is enabled. */
- virtual bool getCustomSkinCondition(const TBSkinCondition::CONDITION_INFO &info) override;
-
- /** Set which alignment the text should have if the space
- given when painting is larger than the text.
- This changes the default for new blocks, as wel as the currently selected blocks or the block
- of the current caret position if nothing is selected. */
- void setTextAlign(TB_TEXT_ALIGN align) {
- m_style_edit.setAlign(align);
- }
- TB_TEXT_ALIGN getTextAlign() {
- return m_style_edit.align;
- }
-
- void setTextFormatted(CORE_FORMAT_STRING const char *format, ...) CORE_PRINTF_VARARG_FUNC(2);
-
- virtual bool setText(const char *text) override {
- return setText(text, TB_CARET_POS_BEGINNING);
- }
- virtual bool getText(core::String &text) override {
- return m_style_edit.getText(text);
- }
- virtual void setValue(int value) override {
- setTextFormatted("%i", value);
- }
-
- void onProcess() override {
- TBWidget::onProcess();
- if (!_var || !_var->isDirty()) {
- return;
- }
- setText(_var->strVal().c_str());
- }
-
- using TBWidget::getText; ///< Make all versions in base class available.
-
- using TBWidget::invalidate; ///< Make Invalidate in base class available.
-
- /** Set the text and also specify if the caret should be positioned at the beginning
- or end of the text. */
- bool setText(const char *text, TB_CARET_POS pos) {
- if (_var) {
- _var->setVal(text);
- _var->markClean();
- }
- return m_style_edit.setText(text, pos);
- }
- /** Set the text of the given length and also specify if the caret should be positioned
- at the beginning or end of the text. */
- bool setText(const char *text, int textLen, TB_CARET_POS pos = TB_CARET_POS_BEGINNING) {
- return m_style_edit.setText(text, textLen, pos);
- }
- bool setText(const core::String &text, TB_CARET_POS pos = TB_CARET_POS_BEGINNING) {
- return m_style_edit.setText(text.c_str(), text.size(), pos);
- }
-
- /** Set the placeholder text. It will be visible only when the textfield is empty. */
- virtual bool setPlaceholderText(const char *text) {
- return m_placeholder.setText(text);
- }
- virtual bool getPlaceholderText(core::String &text) {
- return m_placeholder.getText(text);
- }
-
- virtual void scrollTo(int x, int y) override;
- virtual TBWidget::ScrollInfo getScrollInfo() override;
- virtual TBWidget *getScrollRoot() override {
- return &m_root;
- }
-
- virtual bool onEvent(const TBWidgetEvent &ev) override;
- virtual void onPaint(const PaintProps &paint_props) override;
- virtual void onPaintChildren(const PaintProps &paint_props) override;
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual void onAdded() override;
- virtual void onFontChanged() override;
- virtual void onFocusChanged(bool focused) override;
- virtual void onResized(int oldW, int oldH) override;
- virtual TBWidget *getContentRoot() override {
- return &m_root;
- }
-
- virtual PreferredSize onCalculatePreferredContentSize(const SizeConstraints &constraints) override;
-
- virtual void onMessageReceived(TBMessage *msg) override;
-
-private:
- TBScrollBar m_scrollbar_x;
- TBScrollBar m_scrollbar_y;
- TBWidgetString m_placeholder;
- EDIT_TYPE m_edit_type;
- TBEditFieldScrollRoot m_root;
- TBEditFieldContentFactory m_content_factory;
- TBStyleEdit m_style_edit;
- core::VarPtr _var;
- bool m_adapt_to_content_size;
- int m_virtual_width;
- void updateScrollbarVisibility(bool multiline);
-
- // == TBStyleEditListener =======================
- virtual void onChange() override;
- virtual bool onEnter() override;
- virtual void invalidate(const TBRect &rect) override;
- virtual void drawString(int32_t x, int32_t y, TBFontFace *font, const TBColor &color, const char *str,
- int32_t len) override;
- virtual void drawRect(const TBRect &rect, const TBColor &color) override;
- virtual void drawRectFill(const TBRect &rect, const TBColor &color) override;
- virtual void drawTextSelectionBg(const TBRect &rect) override;
- virtual void drawContentSelectionFg(const TBRect &rect) override;
- virtual void drawCaret(const TBRect &rect) override;
- virtual void scroll(int32_t dx, int32_t dy) override;
- virtual void updateScrollbars() override;
- virtual void caretBlinkStart() override;
- virtual void caretBlinkStop() override;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_font_desc.h b/src/modules/ui/turbobadger/tb/tb_font_desc.h
deleted file mode 100644
index 6b8c0b4e5..000000000
--- a/src/modules/ui/turbobadger/tb/tb_font_desc.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_id.h"
-#include "tb_types.h"
-
-namespace tb {
-
-/** TBFontDescription describes a font.
- By default when nothing is set, the font is unspecified and means it should be inherited
- from a parent widget that specifies a font, or use the default font if no parent does. */
-
-class TBFontDescription {
-public:
- /** Set the font ID of the font to use.
- This ID maps to the font names in TBFontInfo, which is managed from
- TBFontManager::AddFontInfo, TBFontManager::getFontInfo.
-
- Example:
- If a font was added to the font manager with the name "Vera", you can
- do font_description.setID(TBIDC("Vera")).
- */
- void setID(const TBID &id) {
- m_id = id;
- }
-
- /** Get the TBID for the font name (See SetID). */
- TBID getID() const {
- return m_id;
- }
-
- /** Get the TBID for the TBFontFace that matches this font description.
- This is a ID combining both the font file, and variation (such as size and style),
- and should be used to identify a certain font face.
-
- If this is 0, the font description is unspecified. For a widget, that means that the font
- should be inherited from the parent widget. */
- TBID getFontFaceID() const {
- return m_id + m_packed_init;
- }
-
- void setSize(uint32_t size) {
- m_packed.size = Min(size, 0x8000U);
- }
- uint32_t getSize() const {
- return m_packed.size;
- }
-
- // not connected to anything yet
- // void setBold(bool bold) { m_packed.bold = bold; }
- // bool getBold() const { return m_packed.bold; }
-
- // not connected to anything yet
- // void setItalic(bool italic) { m_packed.italic = italic; }
- // bool getItalic() const { return m_packed.italic; }
-
- TBFontDescription() : m_packed_init(0) {
- }
- TBFontDescription(const TBFontDescription &src) {
- m_packed_init = src.m_packed_init;
- m_id = src.m_id;
- }
- const TBFontDescription &operator=(const TBFontDescription &src) {
- m_packed_init = src.m_packed_init;
- m_id = src.m_id;
- return *this;
- }
- bool operator==(const TBFontDescription &fd) const {
- return m_packed_init == fd.m_packed_init && m_id == fd.m_id;
- }
- bool operator!=(const TBFontDescription &fd) const {
- return !(*this == fd);
- }
-
-private:
- TBID m_id;
- union {
- struct {
- uint32_t size : 15;
- uint32_t italic : 1;
- uint32_t bold : 1;
- } m_packed;
- uint32_t m_packed_init;
- };
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_font_renderer.cpp b/src/modules/ui/turbobadger/tb/tb_font_renderer.cpp
deleted file mode 100644
index 2fc179916..000000000
--- a/src/modules/ui/turbobadger/tb/tb_font_renderer.cpp
+++ /dev/null
@@ -1,469 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_font_renderer.h"
-#include "tb_renderer.h"
-#include "tb_skin.h"
-#include "tb_system.h"
-#include
-#include
-#if SDL_VERSION_ATLEAST(2, 0, 9)
-#else
-#include
-#define SDL_expf expf
-#endif
-
-namespace tb {
-
-static void blurGlyph(const unsigned char *src, int srcw, int srch, int srcStride, unsigned char *dst, int dstw,
- int dsth, int dstStride, float *temp, const float *kernel, int kernelRadius) {
- for (int y = 0; y < srch; y++) {
- for (int x = 0; x < dstw; x++) {
- float val = 0;
- for (int k_ofs = -kernelRadius; k_ofs <= kernelRadius; k_ofs++) {
- if (x - kernelRadius + k_ofs >= 0 && x - kernelRadius + k_ofs < srcw) {
- val += src[y * srcStride + x - kernelRadius + k_ofs] * kernel[k_ofs + kernelRadius];
- }
- }
- temp[y * dstw + x] = val;
- }
- }
- for (int y = 0; y < dsth; y++) {
- for (int x = 0; x < dstw; x++) {
- float val = 0;
- for (int k_ofs = -kernelRadius; k_ofs <= kernelRadius; k_ofs++) {
- if (y - kernelRadius + k_ofs >= 0 && y - kernelRadius + k_ofs < srch) {
- val += temp[(y - kernelRadius + k_ofs) * dstw + x] * kernel[k_ofs + kernelRadius];
- }
- }
- dst[y * dstStride + x] = (unsigned char)(val + 0.5F);
- }
- }
-}
-
-void TBFontEffect::setBlurRadius(int blurRadius) {
- core_assert(blurRadius >= 0);
- if (m_blur_radius == blurRadius) {
- return;
- }
- m_blur_radius = blurRadius;
- if (m_blur_radius > 0) {
- if (!m_kernel.reserve(sizeof(float) * (m_blur_radius * 2 + 1))) {
- m_blur_radius = 0;
- return;
- }
- float *kernel = (float *)m_kernel.getData();
- float stdDevSq2 = (float)m_blur_radius / 2.F;
- stdDevSq2 = 2.F * stdDevSq2 * stdDevSq2;
- float scale = 1.F / SDL_sqrtf(3.1415F * stdDevSq2);
- float sum = 0;
- for (int k = 0; k < 2 * m_blur_radius + 1; k++) {
- float x = (float)(k - m_blur_radius);
- float kval = scale * SDL_expf(-(x * x / stdDevSq2));
- kernel[k] = kval;
- sum += kval;
- }
- for (int k = 0; k < 2 * m_blur_radius + 1; k++) {
- kernel[k] /= sum;
- }
- }
-}
-
-TBFontGlyphData *TBFontEffect::render(TBGlyphMetrics *metrics, const TBFontGlyphData *src) {
- TBFontGlyphData *effect_glyph_data = nullptr;
- if (m_blur_radius > 0 && (src->data8 != nullptr)) {
- // Create a new TBFontGlyphData for the blurred glyph
- effect_glyph_data = new TBFontGlyphData;
- if (effect_glyph_data == nullptr) {
- return nullptr;
- }
- effect_glyph_data->w = src->w + m_blur_radius * 2;
- effect_glyph_data->h = src->h + m_blur_radius * 2;
- effect_glyph_data->stride = effect_glyph_data->w;
-
- // Reserve memory needed for blurring.
- if (!m_data_dst.reserve(effect_glyph_data->w * effect_glyph_data->h) ||
- !m_blur_temp.reserve(effect_glyph_data->w * effect_glyph_data->h * sizeof(float))) {
- delete effect_glyph_data;
- return nullptr;
- }
- effect_glyph_data->data8 = (uint8_t *)m_data_dst.getData();
-
- // Blur!
- blurGlyph(src->data8, src->w, src->h, src->stride, effect_glyph_data->data8, effect_glyph_data->w,
- effect_glyph_data->h, effect_glyph_data->w, (float *)m_blur_temp.getData(),
- (float *)m_kernel.getData(), m_blur_radius);
-
- // Adjust glyph position to compensate for larger size.
- metrics->x -= m_blur_radius;
- metrics->y -= m_blur_radius;
- }
- return effect_glyph_data;
-}
-
-// == TBFontGlyph =================================================================================
-
-TBFontGlyph::TBFontGlyph(const TBID &hashId, UCS4 cp) : hash_id(hashId), cp(cp), frag(nullptr), has_rgb(false) {
-}
-
-// == TBFontGlyphCache ============================================================================
-
-TBFontGlyphCache::TBFontGlyphCache() {
- // Only use one map for the font face. The glyph cache will start forgetting
- // glyphs that haven't been used for a while if the map gets full.
- m_frag_manager.setNumMapsLimit(1);
- m_frag_manager.setDefaultMapSize(TB_GLYPH_CACHE_WIDTH, TB_GLYPH_CACHE_HEIGHT);
-
- g_renderer->addListener(this);
-}
-
-TBFontGlyphCache::~TBFontGlyphCache() {
- g_renderer->removeListener(this);
-}
-
-TBFontGlyph *TBFontGlyphCache::getGlyph(const TBID &hashId, UCS4 cp) {
- if (TBFontGlyph *glyph = m_glyphs.get(hashId)) {
- // Move the glyph to the end of m_all_rendered_glyphs so we maintain LRU (oldest first)
- if (m_all_rendered_glyphs.containsLink(glyph)) {
- m_all_rendered_glyphs.remove(glyph);
- m_all_rendered_glyphs.addLast(glyph);
- }
- return glyph;
- }
- return nullptr;
-}
-
-TBFontGlyph *TBFontGlyphCache::createAndCacheGlyph(const TBID &hashId, UCS4 cp) {
- core_assert(!getGlyph(hashId, cp));
- TBFontGlyph *glyph = new TBFontGlyph(hashId, cp);
- if ((glyph != nullptr) && m_glyphs.add(glyph->hash_id, glyph)) {
- return glyph;
- }
- delete glyph;
- return nullptr;
-}
-
-TBBitmapFragment *TBFontGlyphCache::createFragment(TBFontGlyph *glyph, int w, int h, int stride, uint32_t *data) {
- core_assert(getGlyph(glyph->hash_id, glyph->cp));
- // Don't bother if the requested glyph is too large.
- if (w > TB_GLYPH_CACHE_WIDTH || h > TB_GLYPH_CACHE_HEIGHT) {
- return nullptr;
- }
-
- bool try_drop_largest = true;
- bool dropped_large_enough_glyph = false;
- do {
- // Attempt creating a fragment for the rendered glyph data
- if (TBBitmapFragment *frag = m_frag_manager.createNewFragment(glyph->hash_id, false, w, h, stride, data)) {
- glyph->frag = frag;
- m_all_rendered_glyphs.addLast(glyph);
- return frag;
- }
- // Drop the oldest glyph that's large enough to free up the space we need.
- if (try_drop_largest) {
- const int check_limit = 20;
- int check_count = 0;
- for (TBFontGlyph *oldest = m_all_rendered_glyphs.getFirst();
- (oldest != nullptr) && check_count < check_limit; oldest = oldest->getNext()) {
- if (oldest->frag->width() >= w && oldest->frag->getAllocatedHeight() >= h) {
- dropGlyphFragment(oldest);
- dropped_large_enough_glyph = true;
- break;
- }
- check_count++;
- }
- try_drop_largest = false;
- }
- // We had no large enough glyph so just drop the oldest one. We will likely
- // spin around the loop, fail and drop again a few times before we succeed.
- if (!dropped_large_enough_glyph) {
- if (TBFontGlyph *oldest = m_all_rendered_glyphs.getFirst()) {
- dropGlyphFragment(oldest);
- } else {
- break;
- }
- }
- } while (true);
- return nullptr;
-}
-
-void TBFontGlyphCache::dropGlyphFragment(TBFontGlyph *glyph) {
- core_assert(glyph->frag);
- m_frag_manager.freeFragment(glyph->frag);
- glyph->frag = nullptr;
- m_all_rendered_glyphs.remove(glyph);
-}
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-void TBFontGlyphCache::debug() {
- m_frag_manager.debug();
-}
-#endif // TB_RUNTIME_DEBUG_INFO
-
-void TBFontGlyphCache::onContextLost() {
- m_frag_manager.deleteBitmaps();
-}
-
-void TBFontGlyphCache::onContextRestored() {
- // No need to do anything. The bitmaps will be created when drawing.
-}
-
-// ================================================================================================
-
-TBFontFace::TBFontFace(TBFontGlyphCache *glyphCache, TBFontRenderer *renderer, const TBFontDescription &fontDesc)
- : m_glyph_cache(glyphCache), m_font_renderer(renderer), m_font_desc(fontDesc), m_bgFont(nullptr), m_bgX(0),
- m_bgY(0) {
- if (m_font_renderer != nullptr) {
- m_metrics = m_font_renderer->getMetrics();
- } else {
- // Invent some metrics for the test font
- int size = m_font_desc.getSize();
- m_metrics.ascent = size - size / 4;
- m_metrics.descent = size / 4;
- m_metrics.height = size;
- }
-}
-
-TBFontFace::~TBFontFace() {
- // It would be nice to drop all glyphs we have live for this font face.
- // Now they only die when they get old and kicked out of the cache.
- // We currently don't drop any font faces either though (except on shutdown)
- delete m_font_renderer;
-}
-
-void TBFontFace::setBackgroundFont(TBFontFace *font, const TBColor &col, int xofs, int yofs) {
- m_bgFont = font;
- m_bgX = xofs;
- m_bgY = yofs;
- m_bgColor = col;
-}
-
-bool TBFontFace::renderGlyphs(const char *glyphStr) {
- if (m_font_renderer == nullptr) {
- return true; // This is the test font
- }
-
- const int glyphStrLen = SDL_strlen(glyphStr);
- bool has_all_glyphs = true;
- int i = 0;
- while (i < glyphStrLen && glyphStr[i] != '\0') {
- UCS4 cp = utf8::decode_next(glyphStr, &i, glyphStrLen);
- if (getGlyph(cp, true) == nullptr) {
- has_all_glyphs = false;
- }
- }
- return has_all_glyphs;
-}
-
-TBFontGlyph *TBFontFace::createAndCacheGlyph(const TBID &hashId, UCS4 cp) {
- if (m_font_renderer == nullptr) {
- return nullptr; // This is the test font
- }
-
- // Create the new glyph
- TBFontGlyph *glyph = m_glyph_cache->createAndCacheGlyph(hashId, cp);
- if (glyph != nullptr) {
- m_font_renderer->getGlyphMetrics(&glyph->metrics, cp);
- }
- return glyph;
-}
-
-void TBFontFace::renderGlyph(TBFontGlyph *glyph) {
- core_assert(!glyph->frag);
- TBFontGlyphData glyph_data;
- if (m_font_renderer->renderGlyph(&glyph_data, glyph->cp)) {
- TBFontGlyphData *effect_glyph_data = m_effect.render(&glyph->metrics, &glyph_data);
- TBFontGlyphData *result_glyph_data = effect_glyph_data != nullptr ? effect_glyph_data : &glyph_data;
-
- // The glyph data may be in uint8 format, which we have to convert since we always
- // create fragments (and TBBitmap) in 32bit format.
- uint32_t *glyph_dsta_src = result_glyph_data->data32;
- if ((glyph_dsta_src == nullptr) && (result_glyph_data->data8 != nullptr)) {
- if (m_temp_buffer.reserve(result_glyph_data->w * result_glyph_data->h * sizeof(uint32_t))) {
- glyph_dsta_src = (uint32_t *)m_temp_buffer.getData();
- for (int y = 0; y < result_glyph_data->h; y++) {
- for (int x = 0; x < result_glyph_data->w; x++) {
-#ifdef TB_PREMULTIPLIED_ALPHA
- uint8_t opacity = result_glyph_data->data8[x + y * result_glyph_data->stride];
- glyph_dsta_src[x + y * result_glyph_data->w] = TBColor(opacity, opacity, opacity, opacity);
-#else
- glyph_dsta_src[x + y * result_glyph_data->w] =
- TBColor(255, 255, 255, result_glyph_data->data8[x + y * result_glyph_data->stride]);
-#endif
- }
- }
- }
- }
-
- // Finally, the glyph data is ready and we can create a bitmap fragment.
- if (glyph_dsta_src != nullptr) {
- glyph->has_rgb = result_glyph_data->rgb;
- m_glyph_cache->createFragment(glyph, result_glyph_data->w, result_glyph_data->h, result_glyph_data->stride,
- glyph_dsta_src);
- }
-
- delete effect_glyph_data;
- }
-#ifdef TB_RUNTIME_DEBUG_INFO
- // char glyph_str[9];
- // int len = utf8::encode(cp, glyph_str);
- // glyph_str[len] = 0;
- // Log::debug("Created glyph %d (\"%s\"). Cache contains %d glyphs (%d%% full) using %d bitmaps.",
- // cp, glyph_str, m_all_glyphs.CountLinks(), m_frag_manager.getUseRatio(), m_frag_manager.getNumMaps());
-#endif
-}
-
-TBID TBFontFace::getHashId(UCS4 cp) const {
- return cp * 3111 + m_font_desc.getFontFaceID();
-}
-
-TBFontGlyph *TBFontFace::getGlyph(UCS4 cp, bool renderIfNeeded) {
- const TBID &hash_id = getHashId(cp);
- TBFontGlyph *glyph = m_glyph_cache->getGlyph(hash_id, cp);
- if (glyph == nullptr) {
- glyph = createAndCacheGlyph(hash_id, cp);
- }
- if ((glyph != nullptr) && (glyph->frag == nullptr) && renderIfNeeded) {
- renderGlyph(glyph);
- }
- return glyph;
-}
-
-void TBFontFace::drawString(int x, int y, const TBColor &color, const char *str, int len) {
- if (m_bgFont != nullptr) {
- m_bgFont->drawString(x + m_bgX, y + m_bgY, m_bgColor, str, len);
- }
-
- if (m_font_renderer != nullptr) {
- g_renderer->beginBatchHint(TBRenderer::BATCH_HINT_DRAW_BITMAP_FRAGMENT);
- }
-
- int i = 0;
- while (i < len && str[i] != '\0') {
- UCS4 cp = utf8::decode_next(str, &i, len);
- if (cp == 0xFFFF) {
- continue;
- }
- if (TBFontGlyph *glyph = getGlyph(cp, true)) {
- if (glyph->frag != nullptr) {
- TBRect dst_rect(x + glyph->metrics.x, y + glyph->metrics.y + getAscent(), glyph->frag->width(),
- glyph->frag->height());
- TBRect src_rect(0, 0, glyph->frag->width(), glyph->frag->height());
- if (glyph->has_rgb) {
- g_renderer->drawBitmap(dst_rect, src_rect, glyph->frag);
- } else {
- g_renderer->drawBitmapColored(dst_rect, src_rect, color, glyph->frag);
- }
- }
- x += glyph->metrics.advance;
- } else if (m_font_renderer == nullptr) // This is the test font. Use same glyph width as height and draw square.
- {
- g_tb_skin->paintRect(TBRect(x, y, m_metrics.height / 3, m_metrics.height), color, 1);
- x += m_metrics.height / 3 + 1;
- }
- }
-
- if (m_font_renderer != nullptr) {
- g_renderer->endBatchHint();
- }
-}
-
-int TBFontFace::getStringWidth(const char *str, int len) {
- int width = 0;
- int i = 0;
- while (i < len && str[i] != '\0') {
- UCS4 cp = utf8::decode_next(str, &i, len);
- if (cp == 0xFFFF) {
- continue;
- }
- if (m_font_renderer == nullptr) { // This is the test font. Use same glyph width as height.
- width += m_metrics.height / 3 + 1;
- } else if (TBFontGlyph *glyph = getGlyph(cp, false)) {
- width += glyph->metrics.advance;
- }
- }
- return width;
-}
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-void TBFontFace::debug() {
- m_glyph_cache->debug();
-}
-#endif // TB_RUNTIME_DEBUG_INFO
-
-// == TBFontManager ===============================================================================
-
-TBFontManager::TBFontManager() {
- // Add the test dummy font with empty name (Equals to ID 0)
- addFontInfo("-test-font-dummy-", "");
- m_test_font_desc.setSize(16);
- createFontFace(m_test_font_desc);
-
- // Use the test dummy font as default by default
- m_default_font_desc = m_test_font_desc;
-}
-
-TBFontManager::~TBFontManager() {
-}
-
-TBFontInfo *TBFontManager::addFontInfo(const char *filename, const char *name) {
- if (TBFontInfo *fi = new TBFontInfo(filename, name)) {
- if (m_font_info.add(fi->getID(), fi)) {
- return fi;
- }
- delete fi;
- }
- return nullptr;
-}
-
-TBFontInfo *TBFontManager::getFontInfo(const TBID &id) const {
- return m_font_info.get(id);
-}
-
-bool TBFontManager::hasFontFace(const TBFontDescription &fontDesc) const {
- return m_fonts.get(fontDesc.getFontFaceID()) != nullptr;
-}
-
-TBFontFace *TBFontManager::getFontFace(const TBFontDescription &fontDesc) {
- if (TBFontFace *font = m_fonts.get(fontDesc.getFontFaceID())) {
- return font;
- }
- if (TBFontFace *font = m_fonts.get(getDefaultFontDescription().getFontFaceID())) {
- return font;
- }
- return m_fonts.get(m_test_font_desc.getFontFaceID());
-}
-
-TBFontFace *TBFontManager::createFontFace(const TBFontDescription &fontDesc) {
- core_assert(!hasFontFace(fontDesc)); // There is already a font added with this description!
-
- TBFontInfo *fi = getFontInfo(fontDesc.getID());
- if (fi == nullptr) {
- return nullptr;
- }
-
- if (fi->getID() == 0) // Is this the test dummy font
- {
- if (TBFontFace *font = new TBFontFace(&m_glyph_cache, nullptr, fontDesc)) {
- if (m_fonts.add(fontDesc.getFontFaceID(), font)) {
- return font;
- }
- delete font;
- }
- return nullptr;
- }
-
- // Iterate through font renderers until we find one capable of creating a font for this file.
- for (TBFontRenderer *fr = m_font_renderers.getFirst(); fr != nullptr; fr = fr->getNext()) {
- if (TBFontFace *font = fr->create(this, fi->getFilename(), fontDesc)) {
- if (m_fonts.add(fontDesc.getFontFaceID(), font)) {
- return font;
- }
- delete font;
- }
- }
- return nullptr;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_font_renderer.h b/src/modules/ui/turbobadger/tb/tb_font_renderer.h
deleted file mode 100644
index 5fb15d1e8..000000000
--- a/src/modules/ui/turbobadger/tb/tb_font_renderer.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_bitmap_fragment.h"
-#include "tb_core.h"
-#include "tb_font_desc.h"
-#include "tb_linklist.h"
-#include "tb_renderer.h"
-#include "tb_tempbuffer.h"
-#include "utf8/utf8.h"
-
-namespace tb {
-
-class TBBitmap;
-class TBFontFace;
-
-/** TBFontGlyphData is rendering info used during glyph rendering by TBFontRenderer.
- It does not own the data pointers. */
-class TBFontGlyphData {
-public:
- TBFontGlyphData() : data8(nullptr), data32(nullptr), w(0), h(0), stride(0), rgb(false) {
- }
- ~TBFontGlyphData() {
- }
-
- uint8_t *data8;
- uint32_t *data32;
- int w, h, stride;
- bool rgb;
-};
-
-/** TBGlyphMetrics contains metrics for a font glyph. */
-class TBGlyphMetrics {
-public:
- TBGlyphMetrics() : advance(0), x(0), y(0) {
- }
- int16_t advance, x, y;
-};
-
-/** TBFontMetrics contains metrics for a font face. */
-class TBFontMetrics {
-public:
- TBFontMetrics() : ascent(0), descent(0), height(0) {
- }
- int16_t ascent; ///< Ascent. See TBFontFace::getAscent()
- int16_t descent; ///< Descent. See TBFontFace::getDescent()
- int16_t height; ///< Height. See TBFontFace::getHeight()
-};
-
-/** TBFontRenderer renders glyphs from a font file. */
-class TBFontRenderer : public TBLinkOf {
-public:
- virtual ~TBFontRenderer() {
- }
-
- /** Open the given font file with this renderer and return a new TBFontFace with it.
- return nullptr if the file can't be opened by this renderer. */
- virtual TBFontFace *create(TBFontManager *fontManager, const char *filename, const TBFontDescription &fontDesc) = 0;
-
- virtual bool renderGlyph(TBFontGlyphData *data, UCS4 cp) = 0;
- virtual void getGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp) = 0;
- virtual TBFontMetrics getMetrics() = 0;
- // virtual int getKernAdvance(UCS4 cp1, UCS4 cp2) = 0;
-};
-
-/** TBFontGlyph holds glyph metrics and bitmap fragment.
- There's one of these for all rendered (both successful
- and missing) glyphs in TBFontFace. */
-class TBFontGlyph : public TBLinkOf {
-public:
- TBFontGlyph(const TBID &hash_id, UCS4 cp);
- TBID hash_id;
- UCS4 cp;
- TBGlyphMetrics metrics; ///< The glyph metrics.
- TBBitmapFragment *frag; ///< The bitmap fragment, or nullptr if missing.
- bool has_rgb; ///< if true, drawing should ignore text color.
-};
-
-/** TBFontGlyphCache caches glyphs for font faces.
- Rendered glyphs use bitmap fragments from its fragment manager. */
-class TBFontGlyphCache : private TBRendererListener {
-public:
- TBFontGlyphCache();
- ~TBFontGlyphCache();
-
- /** Get the glyph or nullptr if it is not in the cache. */
- TBFontGlyph *getGlyph(const TBID &hash_id, UCS4 cp);
-
- /** Create the glyph and put it in the cache. Returns the glyph, or nullptr on fail. */
- TBFontGlyph *createAndCacheGlyph(const TBID &hash_id, UCS4 cp);
-
- /** Create a bitmap fragment for the given glyph and render data. This may drop other
- rendered glyphs from the fragment map. Returns the fragment, or nullptr on fail. */
- TBBitmapFragment *createFragment(TBFontGlyph *glyph, int w, int h, int stride, uint32_t *data);
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- /** Render the glyph bitmaps on screen, to analyze fragment positioning. */
- void debug();
-#endif
-
- // Implementing TBRendererListener
- void onContextLost() override;
- void onContextRestored() override;
-
-private:
- void dropGlyphFragment(TBFontGlyph *glyph);
- TBBitmapFragmentManager m_frag_manager;
- TBHashTableAutoDeleteOf m_glyphs;
- TBLinkListOf m_all_rendered_glyphs;
-};
-
-/** TBFontEffect applies an effect on each glyph that is rendered in a TBFontFace. */
-class TBFontEffect {
-public:
- TBFontEffect() : m_blur_radius(0) {
- }
- ~TBFontEffect() {
- }
-
- /** Set blur radius. 0 means no blur. */
- void setBlurRadius(int blur_radius);
-
- /** Returns true if the result is in RGB and should not be painted using the color parameter
- given to DrawString. In other words: It's a color glyph. */
- bool rendersInRGB() const {
- return false;
- }
-
- TBFontGlyphData *render(TBGlyphMetrics *metrics, const TBFontGlyphData *src);
-
-private:
- // Blur data
- int m_blur_radius;
- TBTempBuffer m_kernel;
- TBTempBuffer m_blur_temp;
- TBTempBuffer m_data_dst;
-};
-
-/** TBFontFace represents a loaded font that can measure and render strings. */
-class TBFontFace {
-public:
- TBFontFace(TBFontGlyphCache *glyphCache, TBFontRenderer *renderer, const TBFontDescription &fontDesc);
- ~TBFontFace();
-
- /** Render all glyphs needed to display the string. */
- bool renderGlyphs(const char *glyphStr);
-
- /** Get the vertical distance (positive) from the horizontal baseline to the highest character coordinate
- in a font face. */
- int getAscent() const {
- return m_metrics.ascent;
- }
-
- /** Get the vertical distance (positive) from the horizontal baseline to the lowest character coordinate
- in the font face. */
- int getDescent() const {
- return m_metrics.descent;
- }
-
- /** Get height of the font in pixels. */
- int getHeight() const {
- return m_metrics.height;
- }
-
- /** Get the font description that was used to create this font. */
- TBFontDescription getFontDescription() const {
- return m_font_desc;
- }
-
- /** Get the effect object, so the effect can be changed.
- Note: No glyphs are re-rendered. Only new glyphs are affected. */
- TBFontEffect *getEffect() {
- return &m_effect;
- }
-
- /** Draw string at position x, y (marks the upper left corner of the text). */
- void drawString(int x, int y, const TBColor &color, const char *str, int len);
-
- /** Measure the width of the given string. Should measure len characters or to the null
- termination (whatever comes first). */
- int getStringWidth(const char *str, int len);
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- /** Render the glyph bitmaps on screen, to analyze fragment positioning. */
- void debug();
-#endif
-
- /** Set a background font which will always be rendered behind this one
- when calling DrawString. Very usefull to add a shadow effect to a font. */
- void setBackgroundFont(TBFontFace *font, const TBColor &col, int xofs, int yofs);
-
-private:
- TBID getHashId(UCS4 cp) const;
- TBFontGlyph *getGlyph(UCS4 cp, bool render_if_needed);
- TBFontGlyph *createAndCacheGlyph(const TBID &hash_id, UCS4 cp);
- void renderGlyph(TBFontGlyph *glyph);
- TBFontGlyphCache *m_glyph_cache;
- TBFontRenderer *m_font_renderer;
- TBFontDescription m_font_desc;
- TBFontMetrics m_metrics;
- TBFontEffect m_effect;
- TBTempBuffer m_temp_buffer;
-
- TBFontFace *m_bgFont;
- int m_bgX;
- int m_bgY;
- TBColor m_bgColor;
-};
-
-/** TBFontInfo provides information about a font file associated with a font id. */
-class TBFontInfo {
-public:
- /** Get the font filename. */
- const char *getFilename() const {
- return m_filename.c_str();
- }
-
- /** Get the font name. */
- const char *getName() const {
- return m_name.c_str();
- }
-
- /** Get the font ID that can be used to create this font from a
- TBFontDescription (See TBFontDescription::setID) */
- TBID getID() const {
- return m_id;
- }
-
-private:
- friend class TBFontManager;
- TBFontInfo(const char *filename, const char *name) : m_filename(filename), m_name(name), m_id(name) {
- }
- core::String m_filename;
- core::String m_name;
- TBID m_id;
-};
-
-/** TBFontManager creates and owns font faces (TBFontFace) which are looked up from
- TBFontDescription using GetFontFace.
-
- The fonts it can return must first have their file added and indexed (AddFontInfo),
- and then created CreateFontFace. Otherwise when asking for a font and it doesn't
- exist, it will use the default font.
-
- Font ID 0 is always populated with a dummy font that draws squares. This font is
- generally not used for other things than unit testing or as fallback when there is
- no font backend implemented yet. Since there is always at least the test font, no
- nullptr checks are needed.
-*/
-class TBFontManager {
-public:
- TBFontManager();
- ~TBFontManager();
-
- /** Add a renderer so fonts supported by the renderer can be created. Ownership of the
- renderer is taken, until calling RemoveRenderer. */
- void addRenderer(TBFontRenderer *renderer) {
- m_font_renderers.addLast(renderer);
- }
- void removeRenderer(TBFontRenderer *renderer) {
- m_font_renderers.remove(renderer);
- }
-
- /** Add TBFontInfo for the given font filename, so it can be loaded and identified
- using the font id in a TBFontDescription. */
- TBFontInfo *addFontInfo(const char *filename, const char *name);
-
- /** Get TBFontInfo for the given font id, or nullptr if there is no match. */
- TBFontInfo *getFontInfo(const TBID &id) const;
-
- /** Return true if there is a font loaded that match the given font description. */
- bool hasFontFace(const TBFontDescription &font_desc) const;
-
- /** Get a loaded font matching the description, or the default font if there is no exact match.
- If there is not even any default font loaded, it will return the test dummy font (rendering
- only squares). */
- TBFontFace *getFontFace(const TBFontDescription &font_desc);
-
- /** Create and add a font with the given description. Returns the created font face, or
- nullptr on fail. The font is owned by this TBFontManager, and can be recieved from
- GetFontFace using the same TBFontDescription. */
- TBFontFace *createFontFace(const TBFontDescription &font_desc);
-
- /** Set the default font description. This is the font description that will be used by default
- for widgets. By default, the default description is using the test dummy font. */
- void setDefaultFontDescription(const TBFontDescription &fontDesc) {
- m_default_font_desc = fontDesc;
- }
- TBFontDescription getDefaultFontDescription() const {
- return m_default_font_desc;
- }
-
- /** Return the glyph cache used for fonts created by this font manager. */
- TBFontGlyphCache *getGlyphCache() {
- return &m_glyph_cache;
- }
-
-private:
- TBHashTableAutoDeleteOf m_font_info;
- TBHashTableAutoDeleteOf m_fonts;
- TBLinkListAutoDeleteOf m_font_renderers;
- TBFontGlyphCache m_glyph_cache;
- TBFontDescription m_default_font_desc;
- TBFontDescription m_test_font_desc;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_font_renderer_stb.cpp b/src/modules/ui/turbobadger/tb/tb_font_renderer_stb.cpp
deleted file mode 100644
index d087f605c..000000000
--- a/src/modules/ui/turbobadger/tb/tb_font_renderer_stb.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * @file
- */
-
-#include "core/Assert.h"
-#include "tb_font_renderer.h"
-#include "tb_renderer.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-
-using namespace tb;
-
-#define STBTT_assert core_assert
-#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
-#include "thirdparty/stb_truetype.h"
-#undef STB_TRUETYPE_IMPLEMENTATION
-
-/** STBFontRenderer renders fonts using stb_truetype.h (http://nothings.org/) */
-
-class STBFontRenderer : public TBFontRenderer {
-public:
- STBFontRenderer();
- ~STBFontRenderer();
-
- bool load(const char *filename, int size);
-
- virtual TBFontFace *create(TBFontManager *fontManager, const char *filename, const TBFontDescription &fontDesc);
-
- virtual TBFontMetrics getMetrics();
- virtual bool renderGlyph(TBFontGlyphData *data, UCS4 cp);
- virtual void getGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp);
-
-private:
- stbtt_fontinfo font;
- TBTempBuffer ttf_buffer;
- unsigned char *render_data = nullptr;
- int font_size = 0;
- float scale = 0.0F;
-};
-
-STBFontRenderer::STBFontRenderer() {
-}
-
-STBFontRenderer::~STBFontRenderer() {
- STBTT_free(render_data, 0);
-}
-
-TBFontMetrics STBFontRenderer::getMetrics() {
- TBFontMetrics metrics;
- int ascent;
- int descent;
- int lineGap;
- stbtt_GetFontVMetrics(&font, &ascent, &descent, &lineGap);
- metrics.ascent = (int)(ascent * scale + 0.5F);
- metrics.descent = (int)((-descent) * scale + 0.5F);
- metrics.height = (int)((ascent - descent + lineGap) * scale + 0.5F);
- return metrics;
-}
-
-bool STBFontRenderer::renderGlyph(TBFontGlyphData *data, UCS4 cp) {
- STBTT_free(render_data, 0);
- render_data = stbtt_GetCodepointBitmap(&font, 0, scale, cp, &data->w, &data->h, 0, 0);
- data->data8 = render_data;
- data->stride = data->w;
- data->rgb = false;
- return data->data8 != nullptr;
-}
-
-void STBFontRenderer::getGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp) {
- int advanceWidth;
- int leftSideBearing;
- stbtt_GetCodepointHMetrics(&font, cp, &advanceWidth, &leftSideBearing);
- metrics->advance = (int)(advanceWidth * scale + 0.5F);
- int ix0;
- int iy0;
- int ix1;
- int iy1;
- stbtt_GetCodepointBitmapBox(&font, cp, 0, scale, &ix0, &iy0, &ix1, &iy1);
- metrics->x = ix0;
- metrics->y = iy0;
-}
-
-bool STBFontRenderer::load(const char *filename, int size) {
- if (!ttf_buffer.appendFile(filename)) {
- return false;
- }
-
- const unsigned char *ttf_ptr = (const unsigned char *)ttf_buffer.getData();
- stbtt_InitFont(&font, ttf_ptr, stbtt_GetFontOffsetForIndex(ttf_ptr, 0));
-
- font_size = (int)(size * 1.3F); // FIX: Constant taken out of thin air because fonts get too small.
- scale = stbtt_ScaleForPixelHeight(&font, (float)font_size);
- return true;
-}
-
-TBFontFace *STBFontRenderer::create(TBFontManager *fontManager, const char *filename,
- const TBFontDescription &fontDesc) {
- if (STBFontRenderer *fr = new STBFontRenderer()) {
- if (fr->load(filename, (int)fontDesc.getSize())) {
- if (TBFontFace *font = new TBFontFace(fontManager->getGlyphCache(), fr, fontDesc)) {
- return font;
- }
- }
- delete fr;
- }
- return nullptr;
-}
-
-void register_stb_font_renderer() {
- if (STBFontRenderer *fr = new STBFontRenderer) {
- g_font_manager->addRenderer(fr);
- }
-}
diff --git a/src/modules/ui/turbobadger/tb/tb_font_renderer_tbbf.cpp b/src/modules/ui/turbobadger/tb/tb_font_renderer_tbbf.cpp
deleted file mode 100644
index d5510824d..000000000
--- a/src/modules/ui/turbobadger/tb/tb_font_renderer_tbbf.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * @file
- */
-
-#include "image/Image.h"
-#include "tb_font_renderer.h"
-#include "tb_hashtable.h"
-#include "tb_node_tree.h"
-#include "tb_renderer.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-
-using namespace tb;
-
-struct GLYPH {
- int x, w;
-};
-
-/** TBBFRenderer renders a bitmap font.
-
- A font is loaded from a text file and at least one image that contains
- glyphs for a given size. The number of glyphs that the font contains is
- defined by the glyph string defined in the text file.
-
- Text file format (in tb.txt format parsed by parser/tb_parser.h):
-
- - info>glyph_str Should specify which characters the image
- file contains.
- - info>rgb Set to 1 for color fonts that should never
- care about the text color when drawing.
- Set to 0 to let drawing blend using the text
- color. Default 0.
- - size xx Specify font size xx. Should contain the
- following nodes:
- - bitmap The image file name (in the same folder).
- - ascent The ascent. Default 0.
- - descent The descent. Default 0.
- - x_ofs The x offset for all glyph. This can be
- used in combination with advance_delta to
- compensate for f.ex glow that extend
- around the glyph. Default 0.
- - advance_delta The advance delta for all glyphs. This can
- be used to compensate for f.ex shadow that
- should not add to each glyphs horizontal
- advance. Default 0.
- - space_advance The advance for the space character.
-
- Image file format
-
- Should contain the characters specified in the glyph_str.
-
- All characters should be placed on one long line. Each glyph will be
- found, measured and cropped automatically. In order for this to work,
- each glyph must touch pixels somewhere from the left to the right edge.
- So if you f.ex have a quotation mark, you will have to make sure there
- is pixels with alpha > 0 between the two dots, otherwise the dots will
- be identified as different glyphs.
-*/
-class TBBFRenderer : public TBFontRenderer {
-public:
- TBBFRenderer();
- ~TBBFRenderer();
-
- bool load(const char *filename, int size);
- bool findGlyphs();
- GLYPH *findNext(UCS4 cp, int x);
-
- virtual TBFontFace *create(TBFontManager *fontManager, const char *filename, const TBFontDescription &fontDesc);
-
- virtual TBFontMetrics getMetrics();
- virtual bool renderGlyph(TBFontGlyphData *data, UCS4 cp);
- virtual void getGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp);
-
-private:
- TBNode m_node;
- TBFontMetrics m_metrics;
- image::ImagePtr m_img;
- int m_size;
- int m_x_ofs;
- int m_advance_delta;
- int m_space_advance;
- int m_rgb;
- TBHashTableAutoDeleteOf m_glyph_table;
-};
-
-TBBFRenderer::TBBFRenderer() : m_size(0), m_x_ofs(0), m_advance_delta(0), m_space_advance(0), m_rgb(0) {
-}
-
-TBBFRenderer::~TBBFRenderer() {
-}
-
-TBFontMetrics TBBFRenderer::getMetrics() {
- return m_metrics;
-}
-
-bool TBBFRenderer::renderGlyph(TBFontGlyphData *data, UCS4 cp) {
- if (cp == ' ') {
- return false;
- }
- GLYPH *glyph;
- if (((glyph = m_glyph_table.get(cp)) != nullptr) || ((glyph = m_glyph_table.get('?')) != nullptr)) {
- data->w = glyph->w;
- data->h = m_img->height();
- data->stride = m_img->width();
- data->data32 = (uint32_t *)(m_img->data()) + glyph->x;
- data->rgb = m_rgb != 0;
- return true;
- }
- return false;
-}
-
-void TBBFRenderer::getGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp) {
- metrics->x = m_x_ofs;
- metrics->y = -m_metrics.ascent;
- if (cp == ' ') {
- metrics->advance = m_space_advance;
- } else if (GLYPH *glyph = m_glyph_table.get(cp)) {
- metrics->advance = glyph->w + m_advance_delta;
- } else if (GLYPH *glyph = m_glyph_table.get('?')) {
- metrics->advance = glyph->w + m_advance_delta;
- }
-}
-
-bool TBBFRenderer::load(const char *filename, int size) {
- m_size = size;
- if (!m_node.readFile(filename)) {
- return false;
- }
-
- // Check for size nodes and get the one closest to the size we want.
- TBNode *size_node = nullptr;
- for (TBNode *n = m_node.getFirstChild(); n != nullptr; n = n->getNext()) {
- if (SDL_strcmp(n->getName(), "size") == 0) {
- if ((size_node == nullptr) ||
- Abs(m_size - n->getValue().getInt()) < Abs(m_size - size_node->getValue().getInt())) {
- size_node = n;
- }
- }
- }
- if (size_node == nullptr) {
- return false;
- }
-
- // Metrics
- m_metrics.ascent = size_node->getValueInt("ascent", 0);
- m_metrics.descent = size_node->getValueInt("descent", 0);
- m_metrics.height = m_metrics.ascent + m_metrics.descent;
-
- // Other data
- m_advance_delta = size_node->getValueInt("advance_delta", 0);
- m_space_advance = size_node->getValueInt("space_advance", 0);
- m_x_ofs = size_node->getValueInt("x_ofs", 0);
-
- // Info
- m_rgb = m_node.getValueInt("info>rgb", 0);
-
- // Get the path for the bitmap file.
- TBTempBuffer bitmap_filename;
- if (!bitmap_filename.appendPath(filename)) {
- return false;
- }
-
- // Append the bitmap filename for the given size.
- bitmap_filename.appendString(size_node->getValueString("bitmap", ""));
-
- m_img = image::loadImage(bitmap_filename.getData(), false);
-
- return findGlyphs();
-}
-
-inline unsigned char getAlpha(uint32_t color) {
- return (color & 0xff000000) >> 24;
-}
-
-bool TBBFRenderer::findGlyphs() {
- if (!m_img) {
- return false;
- }
-
- const char *glyph_str = m_node.getValueString("info>glyph_str", nullptr);
- if (glyph_str == nullptr) {
- return false;
- }
-
- int glyph_str_len = SDL_strlen(glyph_str);
- int i = 0;
- int x = 0;
- while (UCS4 uc = utf8::decode_next(glyph_str, &i, glyph_str_len)) {
- if (GLYPH *glyph = findNext(uc, x)) {
- m_glyph_table.add(uc, glyph); // OOM!
- x = glyph->x + glyph->w + 1;
- } else {
- break;
- }
- }
- return true;
-}
-
-GLYPH *TBBFRenderer::findNext(UCS4 cp, int x) {
- int width = m_img->width();
- int height = m_img->height();
- uint32_t *data32 = (uint32_t *)m_img->data();
-
- if (x >= width) {
- return nullptr;
- }
-
- GLYPH *glyph = new GLYPH;
- if (glyph == nullptr) {
- return nullptr;
- }
-
- glyph->x = -1;
- glyph->w = -1;
-
- // Find the left edge of the glyph
- for (int i = x; i < width && glyph->x == -1; i++) {
- for (int j = 0; j < height; j++) {
- if (getAlpha(data32[i + j * width]) != 0U) {
- glyph->x = x = i;
- break;
- }
- }
- }
-
- // Find the right edge of the glyph
- for (int i = x; i < width; i++) {
- int j;
- for (j = 0; j < height; j++) {
- if (getAlpha(data32[i + j * width]) != 0U) {
- break;
- }
- }
- if (j == height) // The whole col was clear, so we found the edge
- {
- glyph->w = i - glyph->x;
- break;
- }
- }
-
- if (glyph->x == -1 || glyph->w == -1) {
- delete glyph;
- return nullptr;
- }
- return glyph;
-}
-
-TBFontFace *TBBFRenderer::create(TBFontManager *fontManager, const char *filename, const TBFontDescription &fontDesc) {
- if (strstr(filename, ".tb.txt") == nullptr) {
- return nullptr;
- }
- if (TBBFRenderer *fr = new TBBFRenderer()) {
- if (fr->load(filename, (int)fontDesc.getSize())) {
- if (TBFontFace *font = new TBFontFace(fontManager->getGlyphCache(), fr, fontDesc)) {
- return font;
- }
- }
- delete fr;
- }
- return nullptr;
-}
-
-void register_tbbf_font_renderer() {
- if (TBBFRenderer *fr = new TBBFRenderer) {
- g_font_manager->addRenderer(fr);
- }
-}
diff --git a/src/modules/ui/turbobadger/tb/tb_geometry.cpp b/src/modules/ui/turbobadger/tb/tb_geometry.cpp
deleted file mode 100644
index fbca41f38..000000000
--- a/src/modules/ui/turbobadger/tb/tb_geometry.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_geometry.h"
-#include "core/Assert.h"
-
-namespace tb {
-
-bool TBRect::intersects(const TBRect &rect) const {
- if (isEmpty() || rect.isEmpty()) {
- return false;
- }
- return x + w > rect.x && x < rect.x + rect.w && y + h > rect.y && y < rect.y + rect.h;
-}
-
-TBRect TBRect::moveIn(const TBRect &boundingRect) const {
- return TBRect(ClampClipMax(x, boundingRect.x, boundingRect.x + boundingRect.w - w),
- ClampClipMax(y, boundingRect.y, boundingRect.y + boundingRect.h - h), w, h);
-}
-
-TBRect TBRect::centerIn(const TBRect &boundingRect) const {
- return TBRect(boundingRect.x + (boundingRect.w - w) / 2, boundingRect.y + (boundingRect.h - h) / 2, w, h);
-}
-
-TBRect TBRect::join(const TBRect &rect) const {
- core_assert(!isInsideOut());
- core_assert(!rect.isInsideOut());
-
- if (isEmpty()) {
- return rect;
- }
- if (rect.isEmpty()) {
- return *this;
- }
-
- int minx = Min(x, rect.x);
- int miny = Min(y, rect.y);
- int maxx = x + w > rect.x + rect.w ? x + w : rect.x + rect.w;
- int maxy = y + h > rect.y + rect.h ? y + h : rect.y + rect.h;
- return TBRect(minx, miny, maxx - minx, maxy - miny);
-}
-
-TBRect TBRect::clip(const TBRect &clipRect) const {
- core_assert(!clipRect.isInsideOut());
- TBRect tmp;
- if (!intersects(clipRect)) {
- return tmp;
- }
- tmp.x = Max(x, clipRect.x);
- tmp.y = Max(y, clipRect.y);
- tmp.w = Min(x + w, clipRect.x + clipRect.w) - tmp.x;
- tmp.h = Min(y + h, clipRect.y + clipRect.h) - tmp.y;
- return tmp;
-}
-
-// == TBRegion ==========================================================================
-
-TBRegion::TBRegion() : m_rects(nullptr), m_num_rects(0), m_capacity(0) {
-}
-
-TBRegion::~TBRegion() {
- removeAll(true);
-}
-
-void TBRegion::removeRect(int index) {
- core_assert(index >= 0 && index < m_num_rects);
- for (int i = index; i < m_num_rects - 1; i++) {
- m_rects[i] = m_rects[i + 1];
- }
- m_num_rects--;
-}
-
-void TBRegion::removeRectFast(int index) {
- core_assert(index >= 0 && index < m_num_rects);
- m_rects[index] = m_rects[--m_num_rects];
-}
-
-void TBRegion::removeAll(bool freeMemory) {
- m_num_rects = 0;
- if (freeMemory) {
- delete[] m_rects;
- m_rects = nullptr;
- m_capacity = 0;
- }
-}
-
-bool TBRegion::set(const TBRect &rect) {
- removeAll();
- return addRect(rect, false);
-}
-
-bool TBRegion::growIfNeeded() {
- if (m_num_rects == m_capacity) {
- int new_m_capacity = Clamp(4, m_capacity * 2, 1024);
- TBRect *new_rects = new TBRect[new_m_capacity];
- if (new_rects == nullptr) {
- return false;
- }
- if (m_rects != nullptr) {
- memmove(new_rects, m_rects, sizeof(TBRect) * m_capacity);
- }
- delete[] m_rects;
- m_rects = new_rects;
- m_capacity = new_m_capacity;
- }
- return true;
-}
-
-bool TBRegion::addRect(const TBRect &rect, bool coalesce) {
- if (coalesce) {
- // If the rect can coalesce with any existing rect,
- // just replace it with the union of both, doing coalesce
- // check again recursively.
- // Searching backwards is most likely to give a hit quicker
- // in many usage scenarios.
- for (int i = m_num_rects - 1; i >= 0; i--) {
- if ( // Can coalesce vertically
- (rect.x == m_rects[i].x && rect.w == m_rects[i].w &&
- (rect.y == m_rects[i].y + m_rects[i].h ||
- rect.y + rect.h == m_rects[i].y)) || // Can coalesce horizontally
- (rect.y == m_rects[i].y && rect.h == m_rects[i].h &&
- (rect.x == m_rects[i].x + m_rects[i].w || rect.x + rect.w == m_rects[i].x))) {
- TBRect union_rect = m_rects[i].join(rect);
- removeRectFast(i);
- return addRect(union_rect, true);
- }
- }
- }
-
- if (!growIfNeeded()) {
- return false;
- }
- m_rects[m_num_rects++] = rect;
- return true;
-}
-
-bool TBRegion::includeRect(const TBRect &rect) {
- for (int i = 0; i < m_num_rects; i++) {
- if (rect.intersects(m_rects[i])) {
- // Make a region containing the non intersecting parts and then include
- // those recursively (they might still intersect some other part of the region).
- TBRegion inclusion_region;
- if (!inclusion_region.addExcludingRects(rect, m_rects[i], false)) {
- return false;
- }
- for (int j = 0; j < inclusion_region.m_num_rects; j++) {
- if (!includeRect(inclusion_region.m_rects[j])) {
- return false;
- }
- }
- return true;
- }
- }
- // Now we know that the rect can be added without overlap.
- // Add it with coalesce checking to keep the number of rects down.
- return addRect(rect, true);
-}
-
-bool TBRegion::excludeRect(const TBRect &excludeRect) {
- int num_rects_to_check = m_num_rects;
- for (int i = 0; i < num_rects_to_check; i++) {
- if (m_rects[i].intersects(excludeRect)) {
- // Remove the existing rectangle we found we intersect
- // and add the pieces we don't intersect. New rects
- // will be added at the end of the list, so we can decrease
- // num_rects_to_check.
- TBRect rect = m_rects[i];
- removeRect(i);
- num_rects_to_check--;
- i--;
-
- if (!addExcludingRects(rect, excludeRect, true)) {
- return false;
- }
- }
- }
- return true;
-}
-
-bool TBRegion::addExcludingRects(const TBRect &rect, const TBRect &excludeRect, bool coalesce) {
- core_assert(rect.intersects(excludeRect));
- TBRect remove = excludeRect.clip(rect);
-
- if (remove.y > rect.y) {
- if (!addRect(TBRect(rect.x, rect.y, rect.w, remove.y - rect.y), coalesce)) {
- return false;
- }
- }
- if (remove.x > rect.x) {
- if (!addRect(TBRect(rect.x, remove.y, remove.x - rect.x, remove.h), coalesce)) {
- return false;
- }
- }
- if (remove.x + remove.w < rect.x + rect.w) {
- if (!addRect(TBRect(remove.x + remove.w, remove.y, rect.x + rect.w - (remove.x + remove.w), remove.h),
- coalesce)) {
- return false;
- }
- }
- if (remove.y + remove.h < rect.y + rect.h) {
- if (!addRect(TBRect(rect.x, remove.y + remove.h, rect.w, rect.y + rect.h - (remove.y + remove.h)), coalesce)) {
- return false;
- }
- }
- return true;
-}
-
-const TBRect &TBRegion::getRect(int index) const {
- core_assert(index >= 0 && index < m_num_rects);
- return m_rects[index];
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_geometry.h b/src/modules/ui/turbobadger/tb/tb_geometry.h
deleted file mode 100644
index 9231ca6aa..000000000
--- a/src/modules/ui/turbobadger/tb/tb_geometry.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-
-namespace tb {
-
-/** Simple point class. */
-
-class TBPoint {
-public:
- int x, y;
- TBPoint() : x(0), y(0) {
- }
- TBPoint(int x, int y) : x(x), y(y) {
- }
-};
-
-/** Simple rectangle class. */
-
-class TBRect {
-public:
- int x, y, w, h;
- TBRect() : x(0), y(0), w(0), h(0) {
- }
- TBRect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {
- }
-
- inline bool isEmpty() const {
- return w <= 0 || h <= 0;
- }
- inline bool isInsideOut() const {
- return w < 0 || h < 0;
- }
- inline bool equals(const TBRect &rect) const {
- return rect.x == x && rect.y == y && rect.w == w && rect.h == h;
- }
- bool intersects(const TBRect &rect) const;
- bool contains(const TBPoint &p) const {
- return p.x >= x && p.y >= y && p.x < x + w && p.y < y + h;
- }
-
- inline void reset() {
- x = y = w = h = 0;
- }
- inline void set(int x, int y, int w, int h) {
- this->x = x;
- this->y = y;
- this->w = w;
- this->h = h;
- }
-
- inline TBRect shrink(int left, int top, int right, int bottom) const {
- return TBRect(x + left, y + top, w - left - right, h - top - bottom);
- }
- inline TBRect expand(int left, int top, int right, int bottom) const {
- return shrink(-left, -top, -right, -bottom);
- }
- inline TBRect shrink(int tx, int ty) const {
- return TBRect(x + tx, y + ty, w - tx * 2, h - ty * 2);
- }
- inline TBRect expand(int tx, int ty) const {
- return shrink(-tx, -ty);
- }
- inline TBRect offset(int dx, int dy) const {
- return TBRect(x + dx, y + dy, w, h);
- }
-
- /** Return a rect moved inside bounding_rect. If the rect doesn't fit inside
- bounding_rect, it will be placed so the x and/or y matches bounding_rect. */
- TBRect moveIn(const TBRect &bounding_rect) const;
-
- /** Return a rect centered in bounding_rect. */
- TBRect centerIn(const TBRect &bounding_rect) const;
-
- TBRect join(const TBRect &rect) const;
- TBRect clip(const TBRect &clip_rect) const;
-};
-
-/** TBRegion does calculations on regions represented by a list of rectangles. */
-
-class TBRegion {
-public:
- TBRegion();
- ~TBRegion();
-
- /** Remove the rect at the given index. */
- void removeRect(int index);
-
- /** Remove the rect at the given index.
- This method will change the order of rectangles after index. */
- void removeRectFast(int index);
-
- /** Remove all rectangles so the region becomes empty.
- If free_memory is false, the internal buffers will be reused
- if more rectangles are added again under its life time. */
- void removeAll(bool free_memory = true);
-
- /** Set the region to the given rect. */
- bool set(const TBRect &rect);
-
- /** Add the rect without doing any overlap check.
- If coalesce is true, it will coalesce the rectangle
- with existing rectangles if possible (until there's
- nothing more to coalesce it with). */
- bool addRect(const TBRect &rect, bool coalesce);
-
- /** Include the rect in the region.
- This will add only the parts that's not already in the region so the result doesn't
- contain overlap parts. This assumes there's no overlap in the region already! */
- bool includeRect(const TBRect &includeRect);
-
- /** Exclude the rect from the region. */
- bool excludeRect(const TBRect &exclude_rect);
-
- /** Add the rectangles that's left of rect after excluding exclude_rect. */
- bool addExcludingRects(const TBRect &rect, const TBRect &exclude_rect, bool coalesce);
-
- bool isEmpty() const {
- return m_num_rects == 0;
- }
- int getNumRects() const {
- return m_num_rects;
- }
- const TBRect &getRect(int index) const;
-
-private:
- TBRect *m_rects;
- int m_num_rects;
- int m_capacity;
- bool growIfNeeded();
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_hash.h b/src/modules/ui/turbobadger/tb/tb_hash.h
deleted file mode 100644
index a9db43e7e..000000000
--- a/src/modules/ui/turbobadger/tb/tb_hash.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_types.h"
-
-namespace tb {
-
-// On C++ compilers that support it, use constexpr for hash so that
-// TBID comparisons turn into simple uint32 comparisons compile time.
-
-// FNV constants
-static constexpr uint32_t basis = 2166136261U;
-static constexpr uint32_t prime = 16777619U;
-
-// compile-time hash helper function
-constexpr uint32_t TBGetHash_one(char c, const char *remain, uint32_t value) {
- return c == 0 ? value : TBGetHash_one(remain[0], remain + 1, (value ^ c) * prime);
-}
-
-// compile-time hash
-constexpr uint32_t TBGetHash(const char *str) {
- return ((str != nullptr) && (*str != 0)) ? TBGetHash_one(str[0], str + 1, basis) : 0;
-}
-
-#define TBIDC(str) tb::TBGetHash(str)
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_hashtable.cpp b/src/modules/ui/turbobadger/tb/tb_hashtable.cpp
deleted file mode 100644
index 5c3baaaea..000000000
--- a/src/modules/ui/turbobadger/tb/tb_hashtable.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_hashtable.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-
-namespace tb {
-
-// FIX: reduce memory (block allocation of ITEM)
-// FIX: should shrink when deleting single items (but not when adding items!)
-// FIX: should grow when about 70% full instead of 100%
-
-TBHashTable::TBHashTable() : m_buckets(nullptr), m_num_buckets(0), m_num_items(0) {
-}
-
-TBHashTable::~TBHashTable() {
- removeAll();
-}
-
-void TBHashTable::removeAll(bool delContent) {
- for (uint32_t i = 0; i < m_num_buckets; i++) {
- ITEM *item = m_buckets[i];
- while (item != nullptr) {
- ITEM *item_next = item->next;
- if (delContent) {
- deleteContent(item->content);
- }
- delete item;
- item = item_next;
- }
- }
- delete[] m_buckets;
- m_buckets = nullptr;
- m_num_buckets = m_num_items = 0;
-}
-
-bool TBHashTable::rehash(uint32_t newNumBuckets) {
- if (newNumBuckets == m_num_buckets) {
- return true;
- }
- if (ITEM **new_buckets = new ITEM *[newNumBuckets]) {
- SDL_memset(new_buckets, 0, sizeof(ITEM *) * newNumBuckets);
- // Rehash all items into the new buckets
- for (uint32_t i = 0; i < m_num_buckets; i++) {
- ITEM *item = m_buckets[i];
- while (item != nullptr) {
- ITEM *item_next = item->next;
- // Add it to new_buckets
- uint32_t bucket = item->key & (newNumBuckets - 1);
- item->next = new_buckets[bucket];
- new_buckets[bucket] = item;
- item = item_next;
- }
- }
- // Delete old buckets and update
- delete[] m_buckets;
- m_buckets = new_buckets;
- m_num_buckets = newNumBuckets;
- return true;
- }
- return false;
-}
-
-uint32_t TBHashTable::getSuitableBucketsCount() const {
- // As long as we use FNV for TBID (in TBGetHash), power of two hash sizes are the best.
- if (m_num_items == 0U) {
- return 16;
- }
- return m_num_items * 2;
-}
-
-void *TBHashTable::get(uint32_t key) const {
- if (m_num_buckets == 0U) {
- return nullptr;
- }
- uint32_t bucket = key & (m_num_buckets - 1);
- ITEM *item = m_buckets[bucket];
- while (item != nullptr) {
- if (item->key == key) {
- return item->content;
- }
- item = item->next;
- }
- return nullptr;
-}
-
-bool TBHashTable::add(uint32_t key, void *content) {
- if (needRehash() && !rehash(getSuitableBucketsCount())) {
- return false;
- }
- core_assert(!get(key));
- if (ITEM *item = new ITEM) {
- uint32_t bucket = key & (m_num_buckets - 1);
- item->key = key;
- item->content = content;
- item->next = m_buckets[bucket];
- m_buckets[bucket] = item;
- m_num_items++;
- return true;
- }
- return false;
-}
-
-void *TBHashTable::remove(uint32_t key) {
- if (m_num_buckets == 0U) {
- return nullptr;
- }
- uint32_t bucket = key & (m_num_buckets - 1);
- ITEM *item = m_buckets[bucket];
- ITEM *prev_item = nullptr;
- while (item != nullptr) {
- if (item->key == key) {
- if (prev_item != nullptr) {
- prev_item->next = item->next;
- } else {
- m_buckets[bucket] = item->next;
- }
- m_num_items--;
- void *content = item->content;
- delete item;
- return content;
- }
- prev_item = item;
- item = item->next;
- }
- core_assert(!"This hash table didn't contain the given key!");
- return nullptr;
-}
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-
-void TBHashTable::debug() {
- Log::debug("Hash table: ");
- int total_count = 0;
- for (uint32_t i = 0; i < m_num_buckets; i++) {
- int count = 0;
- ITEM *item = m_buckets[i];
- while (item != nullptr) {
- count++;
- item = item->next;
- }
- Log::debug("%d ", count);
- total_count += count;
- }
- Log::debug(" (total: %d of %d buckets)", total_count, m_num_buckets);
-}
-
-#endif // TB_RUNTIME_DEBUG_INFO
-
-TBHashTableIterator::TBHashTableIterator(TBHashTable *hashTable)
- : m_hash_table(hashTable), m_current_bucket(0), m_current_item(nullptr) {
-}
-
-void *TBHashTableIterator::getNextContent() {
- if (m_current_bucket == m_hash_table->m_num_buckets) {
- return nullptr;
- }
- if ((m_current_item != nullptr) && (m_current_item->next != nullptr)) {
- m_current_item = m_current_item->next;
- } else {
- if (m_current_item != nullptr) {
- m_current_bucket++;
- }
- if (m_current_bucket == m_hash_table->m_num_buckets) {
- return nullptr;
- }
- while (m_current_bucket < m_hash_table->m_num_buckets) {
- m_current_item = m_hash_table->m_buckets[m_current_bucket];
- if (m_current_item != nullptr) {
- break;
- }
- m_current_bucket++;
- }
- }
- return m_current_item != nullptr ? m_current_item->content : nullptr;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_hashtable.h b/src/modules/ui/turbobadger/tb/tb_hashtable.h
deleted file mode 100644
index ccfcf3e12..000000000
--- a/src/modules/ui/turbobadger/tb/tb_hashtable.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "core/Assert.h"
-#include "tb_core.h"
-
-namespace tb {
-
-/** TBHashTable is a minimal hash table, for hashing anything using a uint32 key. */
-
-class TBHashTable {
-public:
- TBHashTable();
- virtual ~TBHashTable();
-
- /** Remove all items without deleting the content. */
- inline void removeAll() {
- removeAll(false);
- }
-
- /** Remove all items and delete the content.
- This requires TBHashTable to be subclassed and implementing DeleteContent.
- You would typically do this by using TBHashTableOf or TBHashTableAutoDeleteOf. */
- inline void deleteAll() {
- removeAll(true);
- }
-
- /** Get the content for the given key, or nullptr if not found. */
- void *get(uint32_t key) const;
-
- /** Add content with the given key.
- Returns false if out of memory. */
- bool add(uint32_t key, void *content);
-
- /** Remove the content with the given key. */
- void *remove(uint32_t key);
-
- /** Delete the content with the given key. */
- inline void deleteKey(uint32_t key) {
- deleteContent(remove(key));
- }
-
- /** Rehash the table so use the given number of buckets.
- Returns false if out of memory. */
- bool rehash(uint32_t num_buckets);
-
- /** Return true if the hashtable itself think it's time to rehash. */
- inline bool needRehash() const {
- // Grow if more items than buckets
- return (m_num_buckets == 0U) || m_num_items >= m_num_buckets;
- }
-
- /** Get the number of buckets the hashtable itself thinks is suitable for
- the current number of items. */
- uint32_t getSuitableBucketsCount() const;
-
- /** Get the number of items in the hash table. */
- inline uint32_t getNumItems() const {
- return m_num_items;
- }
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- /** Print out some debug info about the hash table. */
- void debug();
-#endif
-
-protected:
- /** Delete the content of a item. This is called if calling deleteAll(), and must be
- implemented in a subclass that knows about the content type. */
- virtual void deleteContent(void *content) {
- core_assert(!"You need to subclass and implement!");
- }
-
-private:
- friend class TBHashTableIterator;
- void removeAll(bool delete_content);
- struct ITEM {
- uint32_t key;
- ITEM *next;
- void *content;
- } * *m_buckets;
- uint32_t m_num_buckets;
- uint32_t m_num_items;
-};
-
-/** TBHashTableIterator is a iterator for stepping through all content stored in a TBHashTable. */
-// FIX: make it safe in case the current item is removed from the hashtable
-class TBHashTableIterator {
-public:
- TBHashTableIterator(TBHashTable *hash_table);
- void *getNextContent();
-
-private:
- TBHashTable *m_hash_table;
- uint32_t m_current_bucket;
- TBHashTable::ITEM *m_current_item;
-};
-
-/** TBHashTableIteratorOf is a TBHashTableIterator which auto cast to the class type. */
-template class TBHashTableIteratorOf : private TBHashTableIterator {
-public:
- TBHashTableIteratorOf(TBHashTable *hashTable) : TBHashTableIterator(hashTable) {
- }
- inline T *getNextContent() {
- return (T *)TBHashTableIterator::getNextContent();
- }
-};
-
-/** TBHashTableOf is a TBHashTable with the given class type as content. */
-template class TBHashTableOf : public TBHashTable {
- // FIX: Don't do public inheritance! Either inherit privately and forward, or use a private member backend!
-public:
- inline T *get(uint32_t key) const {
- return (T *)TBHashTable::get(key);
- }
- inline T *remove(uint32_t key) {
- return (T *)TBHashTable::remove(key);
- }
-
-protected:
- virtual void deleteContent(void *content) {
- delete (T *)content;
- }
-};
-
-/** TBHashTableOf is a TBHashTable with the given class type as content.
- It will delete all content automaticallt on destruction. */
-template class TBHashTableAutoDeleteOf : public TBHashTable {
-public:
- ~TBHashTableAutoDeleteOf() {
- deleteAll();
- }
-
- inline T *get(uint32_t key) const {
- return (T *)TBHashTable::get(key);
- }
-
-protected:
- virtual void deleteContent(void *content) {
- delete (T *)content;
- }
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_id.h b/src/modules/ui/turbobadger/tb/tb_id.h
deleted file mode 100644
index 404cf7cf8..000000000
--- a/src/modules/ui/turbobadger/tb/tb_id.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_hash.h"
-#include "tb_str.h"
-#include "tb_types.h"
-
-namespace tb {
-
-/** TBID is a wrapper for a uint32 to be used as ID.
- The uint32 can be set directly to any uint32, or it can be
- set from a string which will be hashed into the uint32. */
-class TBID {
-public:
- constexpr TBID(uint32_t newid = 0) : id(newid) {
- }
- constexpr TBID(const char *string) : id(TBGetHash(string)) {
- }
- constexpr TBID(const TBID &newid) : id(newid.id) {
- }
- void set(uint32_t newid) {
- id = newid;
- }
- void set(const TBID &newid) {
- id = newid;
- }
- void set(const char *string) {
- id = TBGetHash(string);
- }
-
- operator uint32_t() const {
- return id;
- }
- const TBID &operator=(const TBID &newid) {
- set(newid);
- return *this;
- }
-
-private:
- uint32_t id;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_inline_select.cpp b/src/modules/ui/turbobadger/tb/tb_inline_select.cpp
deleted file mode 100644
index 8b083dd82..000000000
--- a/src/modules/ui/turbobadger/tb/tb_inline_select.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_inline_select.h"
-#include "core/Assert.h"
-#include "core/StringUtil.h"
-
-namespace tb {
-
-// FIX: axis should affect the buttons arrow skin!
-// FIX: unfocus should set the correct text!
-
-TBInlineSelectBase::TBInlineSelectBase() {
- setSkinBg(TBIDC("TBInlineSelect"));
- addChild(&m_layout);
- m_layout.addChild(&m_buttons[0]);
- m_layout.addChild(&m_editfield);
- m_layout.addChild(&m_buttons[1]);
- m_layout.setRect(getPaddingRect());
- m_layout.setGravity(WIDGET_GRAVITY_ALL);
- m_layout.setSpacing(0);
- m_buttons[0].setSkinBg(TBIDC("TBButton.flat"));
- m_buttons[1].setSkinBg(TBIDC("TBButton.flat"));
- m_buttons[0].getContentRoot()->addChild(new TBSkinImage(TBIDC("arrow.left")));
- m_buttons[1].getContentRoot()->addChild(new TBSkinImage(TBIDC("arrow.right")));
- m_buttons[0].setIsFocusable(false);
- m_buttons[1].setIsFocusable(false);
- m_buttons[0].setID(TBIDC("dec"));
- m_buttons[1].setID(TBIDC("inc"));
- m_buttons[0].setAutoRepeat(true);
- m_buttons[1].setAutoRepeat(true);
- m_editfield.setTextAlign(TB_TEXT_ALIGN_RIGHT);
- m_editfield.setEditType(EDIT_TYPE_NUMBER);
- m_editfield.setText("0");
-}
-
-TBInlineSelectBase::~TBInlineSelectBase() {
- m_layout.removeChild(&m_buttons[1]);
- m_layout.removeChild(&m_editfield);
- m_layout.removeChild(&m_buttons[0]);
- removeChild(&m_layout);
-}
-
-void TBInlineSelectBase::onSkinChanged() {
- m_layout.setRect(getPaddingRect());
-}
-
-void TBInlineSelect::setLimits(int min, int max) {
- core_assert(min <= max);
- m_min = min;
- m_max = max;
- setValue(m_value);
-}
-
-void TBInlineSelect::onProcess() {
- Super::onProcess();
- if (!_var || !_var->isDirty()) {
- return;
- }
- setValue(_var->intVal());
-}
-
-void TBInlineSelect::setValueInternal(int value, bool updateText) {
- value = Clamp(value, m_min, m_max);
- if (value == m_value) {
- return;
- }
- m_value = value;
- if (_var) {
- _var->setVal(value);
- _var->markClean();
- }
-
- if (updateText) {
- const core::String& strval = core::string::format("%d", m_value);
- m_editfield.setText(strval);
- }
-
- TBWidgetEvent ev(EVENT_TYPE_CHANGED);
- invokeEvent(ev);
-
- // Warning: Do nothing here since the event might have deleted us.
- // If needed, check if we are alive using a safe pointer first.
-}
-
-bool TBInlineSelect::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_KEY_DOWN) {
- if (ev.special_key == TB_KEY_UP || ev.special_key == TB_KEY_DOWN) {
- int dv = ev.special_key == TB_KEY_UP ? m_delta : -m_delta;
- setValue(getValue() + dv);
- return true;
- }
- } else if (ev.type == EVENT_TYPE_CLICK && ev.target->getID() == TBIDC("dec")) {
- setValue(getValue() - m_delta);
- return true;
- } else if (ev.type == EVENT_TYPE_CLICK && ev.target->getID() == TBIDC("inc")) {
- setValue(getValue() + m_delta);
- return true;
- } else if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_editfield) {
- core::String text;
- m_editfield.getText(text);
- setValueInternal(core::string::toInt(text), false);
- }
- return false;
-}
-
-
-void TBInlineSelectDouble::setLimits(double min, double max) {
- core_assert(min <= max);
- m_min = min;
- m_max = max;
- setValueDouble(m_value);
-}
-
-void TBInlineSelectDouble::onProcess() {
- Super::onProcess();
- if (!_var || !_var->isDirty()) {
- return;
- }
- setValueDouble(_var->floatVal());
-}
-
-void TBInlineSelectDouble::setValueInternal(double value, bool updateText) {
- value = Clamp(value, m_min, m_max);
- if (value == m_value) {
- return;
- }
- m_value = value;
- if (_var) {
- _var->setVal((float)value);
- _var->markClean();
- }
-
- if (updateText) {
- const core::String& strval = core::string::format("%.3f", (float)m_value);
- m_editfield.setText(strval);
- }
-
- TBWidgetEvent ev(EVENT_TYPE_CHANGED);
- invokeEvent(ev);
-
- // Warning: Do nothing here since the event might have deleted us.
- // If needed, check if we are alive using a safe pointer first.
-}
-
-bool TBInlineSelectDouble::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_KEY_DOWN) {
- if (ev.special_key == TB_KEY_UP || ev.special_key == TB_KEY_DOWN) {
- double dv = ev.special_key == TB_KEY_UP ? m_delta : -m_delta;
- setValueDouble(getValueDouble() + dv);
- return true;
- }
- } else if (ev.type == EVENT_TYPE_CLICK && ev.target->getID() == TBIDC("dec")) {
- setValueDouble(getValueDouble() - m_delta);
- return true;
- } else if (ev.type == EVENT_TYPE_CLICK && ev.target->getID() == TBIDC("inc")) {
- setValueDouble(getValueDouble() + m_delta);
- return true;
- } else if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_editfield) {
- core::String text;
- m_editfield.getText(text);
- setValueInternal(SDL_atof(text.c_str()), false);
- }
- return false;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_inline_select.h b/src/modules/ui/turbobadger/tb/tb_inline_select.h
deleted file mode 100644
index a5ac9e809..000000000
--- a/src/modules/ui/turbobadger/tb/tb_inline_select.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_editfield.h"
-#include "tb_select_item.h"
-#include "tb_widgets_listener.h"
-
-namespace tb {
-
-/** TBSelectList is a select widget with no popups. Instead it has two
- arrow buttons that cycle between the choices.
- By default it is a number widget.
-
- FIX: Should also be possible to set a list of strings that will be
- shown instead of numbers.
-*/
-class TBInlineSelectBase : public TBWidget {
-public:
- TBOBJECT_SUBCLASS(TBInlineSelectBase, TBWidget);
-
- TBInlineSelectBase();
- virtual ~TBInlineSelectBase();
-
- /** Set along which axis the content should layouted. */
- virtual void setAxis(AXIS axis) override {
- m_layout.setAxis(axis);
- }
- virtual AXIS getAxis() const override {
- return m_layout.getAxis();
- }
-
- virtual void onSkinChanged() override;
- virtual void onInflate(const INFLATE_INFO &info) override;
-
-protected:
- TBButton m_buttons[2];
- TBLayout m_layout;
- TBEditField m_editfield;
-
- core::VarPtr _var;
- core::String _command;
-};
-
-class TBInlineSelect : public TBInlineSelectBase {
-public:
- TBOBJECT_SUBCLASS(TBInlineSelect, TBInlineSelectBase);
-
- void setLimits(int min, int max);
- int getMinValue() const {
- return m_min;
- }
- int getMaxValue() const {
- return m_max;
- }
-
- virtual void setValue(int value) override {
- setValueInternal(value, true);
- }
- virtual int getValue() const override {
- return m_value;
- }
-
- virtual void onProcess() override;
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual bool onEvent(const TBWidgetEvent &ev) override;
-
-protected:
- int m_value = 0;
- int m_min = 0, m_max = 100;
- int m_delta = 1;
- void setValueInternal(int value, bool update_text);
-};
-
-class TBInlineSelectDouble : public TBInlineSelectBase {
-public:
- TBOBJECT_SUBCLASS(TBInlineSelectDouble, TBInlineSelectBase);
-
- void setLimits(double min, double max);
- double getMinValue() const {
- return m_min;
- }
- double getMaxValue() const {
- return m_max;
- }
-
- virtual void setValueDouble(double value) override {
- setValueInternal(value, true);
- }
- virtual double getValueDouble() const override {
- return m_value;
- }
-
- virtual void onProcess() override;
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual bool onEvent(const TBWidgetEvent &ev) override;
-
-protected:
- double m_value = 0.0;
- double m_min = 0.0, m_max = 100.0;
- double m_delta = 1.0;
- void setValueInternal(double value, bool update_text);
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_language.cpp b/src/modules/ui/turbobadger/tb/tb_language.cpp
deleted file mode 100644
index d38c4cdcb..000000000
--- a/src/modules/ui/turbobadger/tb/tb_language.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_language.h"
-#include "tb_node_tree.h"
-#include "tb_system.h"
-
-namespace tb {
-
-TBLanguage::~TBLanguage() {
- clear();
-}
-
-bool TBLanguage::load(const char *filename) {
- // Read the file into a node tree (even though it's only a flat list)
- TBNode node;
- if (!node.readFile(filename)) {
- return false;
- }
-
- // Go through all nodes and add to the strings hash table
- TBNode *n = node.getFirstChild();
- while (n != nullptr) {
- const char *str = n->getValue().getString();
- core::String *new_str = new core::String(str);
- if ((new_str == nullptr) || !strings.add(TBID(n->getName()), new_str)) {
- delete new_str;
- return false;
- }
- n = n->getNext();
- }
- return true;
-}
-
-void TBLanguage::clear() {
- strings.deleteAll();
-}
-
-const char *TBLanguage::getString(const TBID &id) {
- if (core::String *str = strings.get(id)) {
- return str->c_str();
- }
- return "";
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_language.h b/src/modules/ui/turbobadger/tb/tb_language.h
deleted file mode 100644
index ce47d1f11..000000000
--- a/src/modules/ui/turbobadger/tb/tb_language.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-#include "tb_hashtable.h"
-#include "tb_id.h"
-
-namespace tb {
-
-/** TBLanguage is a basic language string manager.
- Strings read into it can be looked up from a TBID, so either by a number
- or the hash number from a string (done by TBID).
-
- Ex: GetString(10) (Get the string with id 10)
- Ex: GetString("new") (Get the string with id new)
-
- In UI resources, you can refer to strings from language lookup by preceding a string with @.
-
- Ex: TBButton: text: @close (Create a button with text from lookup of "close")
-*/
-
-class TBLanguage {
-public:
- ~TBLanguage();
-
- /** Load a file into this language manager.
- Note: This *adds* strings read from the file, without clearing any existing
- strings first. */
- bool load(const char *filename);
-
- /** Clear the list of strings. */
- void clear();
-
- /** Return the string with the given id.
- If there is no string with that id, "" will be returned
- in release builds, and "" (populated with the id) will
- be returned in debug builds. */
- const char *getString(const TBID &id);
-
-private:
- TBHashTableOf strings;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_layout.cpp b/src/modules/ui/turbobadger/tb/tb_layout.cpp
deleted file mode 100644
index 82d8c918b..000000000
--- a/src/modules/ui/turbobadger/tb/tb_layout.cpp
+++ /dev/null
@@ -1,492 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_layout.h"
-#include "core/Assert.h"
-#include "tb_skin_util.h"
-#include "tb_system.h"
-
-namespace tb {
-
-TBLayout::TBLayout(AXIS axis)
- : m_axis(axis), m_spacing(SPACING_FROM_SKIN), m_overflow(0), m_overflow_scroll(0), m_packed_init(0) {
- m_packed.layout_mode_size = LAYOUT_SIZE_GRAVITY;
- m_packed.layout_mode_pos = LAYOUT_POSITION_CENTER;
- m_packed.layout_mode_overflow = LAYOUT_OVERFLOW_CLIP;
- m_packed.layout_mode_dist = LAYOUT_DISTRIBUTION_PREFERRED;
- m_packed.layout_mode_dist_pos = LAYOUT_DISTRIBUTION_POSITION_CENTER;
- m_packed.paint_overflow_fadeout = 1;
-}
-
-void TBLayout::setAxis(AXIS axis) {
- if (axis == m_axis) {
- return;
- }
- m_axis = axis;
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
- invalidateSkinStates();
-}
-
-void TBLayout::setSpacing(int spacing) {
- if (spacing == m_spacing) {
- return;
- }
- m_spacing = spacing;
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
-}
-
-void TBLayout::setOverflowScroll(int overflowScroll) {
- overflowScroll = Min(overflowScroll, m_overflow);
- overflowScroll = Max(overflowScroll, 0);
- if (overflowScroll == m_overflow_scroll) {
- return;
- }
- m_overflow_scroll = overflowScroll;
- invalidate();
- if (m_axis == AXIS_X) {
- onScroll(m_overflow_scroll, 0);
- } else {
- onScroll(0, m_overflow_scroll);
- }
-}
-
-void TBLayout::setLayoutSize(LAYOUT_SIZE size) {
- if (size == m_packed.layout_mode_size) {
- return;
- }
- m_packed.layout_mode_size = size;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBLayout::setLayoutPosition(LAYOUT_POSITION pos) {
- if (pos == m_packed.layout_mode_pos) {
- return;
- }
- m_packed.layout_mode_pos = pos;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBLayout::setLayoutOverflow(LAYOUT_OVERFLOW overflow) {
- if (overflow == m_packed.layout_mode_overflow) {
- return;
- }
- m_packed.layout_mode_overflow = overflow;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBLayout::setLayoutDistribution(LAYOUT_DISTRIBUTION distribution) {
- if (distribution == m_packed.layout_mode_dist) {
- return;
- }
- m_packed.layout_mode_dist = distribution;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBLayout::setLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION distributionPos) {
- if (distributionPos == m_packed.layout_mode_dist_pos) {
- return;
- }
- m_packed.layout_mode_dist_pos = distributionPos;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBLayout::setLayoutOrder(LAYOUT_ORDER order) {
- bool reversed = (order == LAYOUT_ORDER_TOP_TO_BOTTOM);
- if (static_cast(reversed) == m_packed.mode_reverse_order) {
- return;
- }
- m_packed.mode_reverse_order = reversed;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBLayout::invalidateLayout(INVALIDATE_LAYOUT il) {
- m_packed.layout_is_invalid = 1;
- // Continue invalidating parents (depending on il)
- TBWidget::invalidateLayout(il);
-}
-
-PreferredSize RotPreferredSize(const PreferredSize &ps, AXIS axis) {
- if (axis == AXIS_X) {
- return ps;
- }
- PreferredSize psr;
- psr.max_w = ps.max_h;
- psr.max_h = ps.max_w;
- psr.min_w = ps.min_h;
- psr.min_h = ps.min_w;
- psr.pref_w = ps.pref_h;
- psr.pref_h = ps.pref_w;
- psr.size_dependency =
- ((ps.size_dependency & SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT) != 0U ? SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH
- : SIZE_DEP_NONE) |
- ((ps.size_dependency & SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH) != 0U ? SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT
- : SIZE_DEP_NONE);
- return psr;
-}
-
-SizeConstraints RotSizeConstraints(const SizeConstraints &sc, AXIS axis) {
- return axis == AXIS_X ? sc : SizeConstraints(sc.available_h, sc.available_w);
-}
-
-TBRect RotRect(const TBRect &rect, AXIS axis) {
- if (axis == AXIS_X) {
- return rect;
- }
- return TBRect(rect.y, rect.x, rect.h, rect.w);
-}
-
-WIDGET_GRAVITY RotGravity(WIDGET_GRAVITY gravity, AXIS axis) {
- if (axis == AXIS_X) {
- return gravity;
- }
- WIDGET_GRAVITY r = WIDGET_GRAVITY_NONE;
- r |= (gravity & WIDGET_GRAVITY_LEFT) != 0U ? WIDGET_GRAVITY_TOP : WIDGET_GRAVITY_NONE;
- r |= (gravity & WIDGET_GRAVITY_TOP) != 0U ? WIDGET_GRAVITY_LEFT : WIDGET_GRAVITY_NONE;
- r |= (gravity & WIDGET_GRAVITY_RIGHT) != 0U ? WIDGET_GRAVITY_BOTTOM : WIDGET_GRAVITY_NONE;
- r |= (gravity & WIDGET_GRAVITY_BOTTOM) != 0U ? WIDGET_GRAVITY_RIGHT : WIDGET_GRAVITY_NONE;
- return r;
-}
-
-bool TBLayout::qualifyForExpansion(WIDGET_GRAVITY gravity) const {
- if (m_packed.layout_mode_dist == LAYOUT_DISTRIBUTION_AVAILABLE) {
- return true;
- }
- if (m_packed.layout_mode_dist == LAYOUT_DISTRIBUTION_GRAVITY &&
- (((gravity & WIDGET_GRAVITY_LEFT) != 0U) && ((gravity & WIDGET_GRAVITY_RIGHT) != 0U))) {
- return true;
- }
- return false;
-}
-
-int TBLayout::getWantedHeight(WIDGET_GRAVITY gravity, const PreferredSize &ps, int availableHeight) const {
- int height = 0;
- switch (m_packed.layout_mode_size) {
- case LAYOUT_SIZE_GRAVITY:
- height = (((gravity & WIDGET_GRAVITY_TOP) != 0U) && ((gravity & WIDGET_GRAVITY_BOTTOM) != 0U))
- ? availableHeight
- : Min(availableHeight, ps.pref_h);
- break;
- case LAYOUT_SIZE_PREFERRED:
- height = Min(availableHeight, ps.pref_h);
- break;
- case LAYOUT_SIZE_AVAILABLE:
- height = Min(availableHeight, ps.max_h);
- break;
- }
- height = Min(height, ps.max_h);
- return height;
-}
-
-TBWidget *TBLayout::getNextNonCollapsedWidget(TBWidget *child) const {
- TBWidget *next = getNextInLayoutOrder(child);
- while ((next != nullptr) && next->getVisibility() == WIDGET_VISIBILITY_GONE) {
- next = getNextInLayoutOrder(next);
- }
- return next;
-}
-
-int TBLayout::getTrailingSpace(TBWidget *child, int spacing) const {
- if (spacing == 0) {
- return 0;
- }
- if (getNextNonCollapsedWidget(child) == nullptr) {
- return 0;
- }
- return spacing;
-}
-
-int TBLayout::calculateSpacing() {
- // Get spacing from skin, if not specified
- int spacing = m_spacing;
- if (spacing == SPACING_FROM_SKIN) {
- if (TBSkinElement *e = getSkinBgElement()) {
- spacing = e->spacing;
- }
-
- core_assert(SPACING_FROM_SKIN == SKIN_VALUE_NOT_SPECIFIED);
- if (spacing == SPACING_FROM_SKIN /*|| spacing == SKIN_VALUE_NOT_SPECIFIED*/) {
- spacing = g_tb_skin->getDefaultSpacing();
- }
- }
- return spacing;
-}
-
-TBWidget *TBLayout::getFirstInLayoutOrder() const {
- return m_packed.mode_reverse_order ? getLastChild() : getFirstChild();
-}
-
-TBWidget *TBLayout::getNextInLayoutOrder(TBWidget *child) const {
- return m_packed.mode_reverse_order ? child->getPrev() : child->getNext();
-}
-
-void TBLayout::validateLayout(const SizeConstraints &constraints, PreferredSize *calculatePs) {
- // Layout notes:
- // -All layout code is written for AXIS_X layout.
- // Instead of duplicating the layout code for both AXIS_X and AXIS_Y, we simply
- // rotate the in data (rect, gravity, preferred size) and the outdata (rect).
-
- if (calculatePs == nullptr) {
- if (!m_packed.layout_is_invalid) {
- return;
- }
- m_packed.layout_is_invalid = 0;
- } else {
- // Maximum size will grow below depending of the childrens maximum size
- calculatePs->max_w = calculatePs->max_h = 0;
- }
-
- const int spacing = calculateSpacing();
- const TBRect padding_rect = getPaddingRect();
- const TBRect layout_rect = RotRect(padding_rect, m_axis);
-
- const SizeConstraints inner_sc =
- constraints.constrainByPadding(getRect().w - padding_rect.w, getRect().h - padding_rect.h);
-
- // Calculate totals for minimum and preferred width that we need for layout.
- int total_preferred_w = 0;
- int total_min_pref_diff_w = 0;
- int total_max_pref_diff_w = 0;
- for (TBWidget *child = getFirstInLayoutOrder(); child != nullptr; child = getNextInLayoutOrder(child)) {
- if (child->getVisibility() == WIDGET_VISIBILITY_GONE) {
- continue;
- }
-
- const int ending_space = getTrailingSpace(child, spacing);
- const PreferredSize ps = RotPreferredSize(child->getPreferredSize(inner_sc), m_axis);
- const WIDGET_GRAVITY gravity = RotGravity(child->getGravity(), m_axis);
-
- total_preferred_w += ps.pref_w + ending_space;
- total_min_pref_diff_w += ps.pref_w - ps.min_w;
-
- if (qualifyForExpansion(gravity)) {
- int capped_max_w = Min(layout_rect.w, ps.max_w);
- total_max_pref_diff_w += capped_max_w - ps.pref_w;
- }
-
- if (calculatePs != nullptr) {
- calculatePs->min_h = Max(calculatePs->min_h, ps.min_h);
- calculatePs->pref_h = Max(calculatePs->pref_h, ps.pref_h);
- calculatePs->min_w += ps.min_w + ending_space;
- calculatePs->pref_w += ps.pref_w + ending_space;
- calculatePs->max_w += ps.max_w + ending_space;
-
- // The widget height depends on layout and widget properties, so get what
- // it would actually use if it was given max_h as available height.
- // If we just used its max_h, that could increase the whole layout size
- // even if the widget wouldn't actually use it.
- int height = getWantedHeight(gravity, ps, ps.max_h);
- calculatePs->max_h = Max(calculatePs->max_h, height);
-
- calculatePs->size_dependency |= ps.size_dependency;
- }
- }
-
- if (calculatePs != nullptr) {
- // We just wanted to calculate preferred size, so return without layouting.
- *calculatePs = RotPreferredSize(*calculatePs, m_axis);
- return;
- }
-
- TB_IF_DEBUG_SETTING(LAYOUT_PS_DEBUGGING, last_layout_time = TBSystem::getTimeMS());
-
- // Pre Layout step (calculate distribution position)
- int missing_space = Max(total_preferred_w - layout_rect.w, 0);
- int extra_space = Max(layout_rect.w - total_preferred_w, 0);
-
- int offset = layout_rect.x;
- if ((extra_space != 0) && m_packed.layout_mode_dist_pos != LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP) {
- // To calculate the offset we need to predict the used space. We can do that by checking
- // the distribution mode and total_max_pref_diff_w. That's how much the widgets could possible
- // expand in the layout below.
-
- int used_space = total_preferred_w;
- if (m_packed.layout_mode_dist != LAYOUT_DISTRIBUTION_PREFERRED) {
- used_space += Min(extra_space, total_max_pref_diff_w);
- }
-
- if (m_packed.layout_mode_dist_pos == LAYOUT_DISTRIBUTION_POSITION_CENTER) {
- offset += (layout_rect.w - used_space) / 2;
- } else { // LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM
- offset += layout_rect.w - used_space;
- }
- }
-
- // Layout
- int used_space = 0;
- for (TBWidget *child = getFirstInLayoutOrder(); child != nullptr; child = getNextInLayoutOrder(child)) {
- if (child->getVisibility() == WIDGET_VISIBILITY_GONE) {
- continue;
- }
-
- const int ending_space = getTrailingSpace(child, spacing);
- const PreferredSize ps = RotPreferredSize(child->getPreferredSize(inner_sc), m_axis);
- const WIDGET_GRAVITY gravity = RotGravity(child->getGravity(), m_axis);
-
- // Calculate width. May shrink if space is missing, or grow if we have extra space.
- int width = ps.pref_w;
- if ((missing_space != 0) && (total_min_pref_diff_w != 0)) {
- int diff_w = ps.pref_w - ps.min_w;
- float factor = (float)diff_w / (float)total_min_pref_diff_w;
- int removed = (int)(missing_space * factor);
- removed = Min(removed, diff_w);
- width -= removed;
-
- total_min_pref_diff_w -= diff_w;
- missing_space -= removed;
- } else if ((extra_space != 0) && (total_max_pref_diff_w != 0) && qualifyForExpansion(gravity)) {
- int capped_max_w = Min(layout_rect.w, ps.max_w);
- int diff_w = capped_max_w - ps.pref_w;
- float factor = (float)diff_w / (float)total_max_pref_diff_w;
- int added = (int)(extra_space * factor);
- added = Min(added, diff_w);
- width += added;
-
- total_max_pref_diff_w -= capped_max_w - ps.pref_w;
- extra_space -= added;
- }
-
- // Calculate height
- int available_height = layout_rect.h;
- int height = getWantedHeight(gravity, ps, available_height);
-
- // Calculate position
- int pos = layout_rect.y;
- switch (m_packed.layout_mode_pos) {
- case LAYOUT_POSITION_CENTER:
- pos += (available_height - height) / 2;
- break;
- case LAYOUT_POSITION_RIGHT_BOTTOM:
- pos += available_height - height;
- break;
- case LAYOUT_POSITION_GRAVITY:
- if (((gravity & WIDGET_GRAVITY_TOP) != 0U) && ((gravity & WIDGET_GRAVITY_BOTTOM) != 0U)) {
- pos += (available_height - height) / 2;
- } else if ((gravity & WIDGET_GRAVITY_BOTTOM) != 0U) {
- pos += available_height - height;
- }
- break;
- default: // LAYOUT_POSITION_LEFT_TOP
- break;
- }
-
- // Done! Set rect and increase used space
- TBRect rect(used_space + offset, pos, width, height);
- used_space += width + ending_space;
-
- child->setRect(RotRect(rect, m_axis));
- }
- // Update overflow and overflow scroll
- m_overflow = Max(0, used_space - layout_rect.w);
- setOverflowScroll(m_overflow_scroll);
-}
-
-PreferredSize TBLayout::onCalculatePreferredContentSize(const SizeConstraints &constraints) {
- // Do a layout pass (without layouting) to check childrens preferences.
- PreferredSize ps;
- validateLayout(constraints, &ps);
- return ps;
-}
-
-bool TBLayout::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE) {
- int old_scroll = getOverflowScroll();
- setOverflowScroll(m_overflow_scroll + ev.delta_y * TBSystem::getPixelsPerLine());
- return m_overflow_scroll != old_scroll;
- }
- return false;
-}
-
-void TBLayout::onPaintChildren(const PaintProps &paintProps) {
- TBRect padding_rect = getPaddingRect();
- if (padding_rect.isEmpty()) {
- return;
- }
-
- // If we overflow the layout, apply clipping when painting children
- TBRect old_clip_rect;
- if (m_overflow != 0) {
- // We only want clipping in one axis (the overflowing one) so we
- // don't damage any expanded skins on the other axis. Add some fluff.
- TBRect clip_rect = padding_rect;
- const int fluff = 100;
-
- if (m_axis == AXIS_X) {
- clip_rect = clip_rect.expand(m_overflow_scroll == 0 ? fluff : 0, fluff,
- m_overflow_scroll == m_overflow ? fluff : 0, fluff);
- } else {
- clip_rect = clip_rect.expand(fluff, m_overflow_scroll == 0 ? fluff : 0, fluff,
- m_overflow_scroll == m_overflow ? fluff : 0);
- }
-
- old_clip_rect = g_renderer->setClipRect(clip_rect, true);
-
- TB_IF_DEBUG_SETTING(LAYOUT_CLIPPING, g_tb_skin->paintRect(clip_rect, TBColor(255, 0, 0, 200), 1));
- }
-
- // Paint children
- TBWidget::onPaintChildren(paintProps);
-
- // Paint fadeout image over the overflowed edges
- // to the indicate to used that it's overflowed.
- if ((m_overflow != 0) && m_packed.paint_overflow_fadeout) {
- TBID skin_x;
- TBID skin_y;
- if (m_axis == AXIS_X) {
- skin_x = TBIDC("TBLayout.fadeout_x");
- } else {
- skin_y = TBIDC("TBLayout.fadeout_y");
- }
-
- drawEdgeFadeout(padding_rect, skin_x, skin_y, m_overflow_scroll, m_overflow_scroll,
- m_overflow - m_overflow_scroll, m_overflow - m_overflow_scroll);
- }
-
- // Restore clipping
- if (m_overflow != 0) {
- g_renderer->setClipRect(old_clip_rect, false);
- }
-}
-
-void TBLayout::onProcess() {
- SizeConstraints sc(getRect().w, getRect().h);
- validateLayout(sc);
-}
-
-void TBLayout::onResized(int oldW, int oldH) {
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
- SizeConstraints sc(getRect().w, getRect().h);
- validateLayout(sc);
-}
-
-void TBLayout::onInflateChild(TBWidget *child) {
- // Do nothing since we're going to layout the child soon.
-}
-
-void TBLayout::getChildTranslation(int &x, int &y) const {
- if (m_axis == AXIS_X) {
- x = -m_overflow_scroll;
- y = 0;
- } else {
- x = 0;
- y = -m_overflow_scroll;
- }
-}
-
-void TBLayout::scrollTo(int x, int y) {
- setOverflowScroll(m_axis == AXIS_X ? x : y);
-}
-
-TBWidget::ScrollInfo TBLayout::getScrollInfo() {
- ScrollInfo info;
- if (m_axis == AXIS_X) {
- info.max_x = m_overflow;
- info.x = m_overflow_scroll;
- } else {
- info.max_y = m_overflow;
- info.y = m_overflow_scroll;
- }
- return info;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_layout.h b/src/modules/ui/turbobadger/tb/tb_layout.h
deleted file mode 100644
index 244e1beda..000000000
--- a/src/modules/ui/turbobadger/tb/tb_layout.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_widgets.h"
-
-namespace tb {
-
-/** This means the spacing should be the default, read from the skin. */
-#define SPACING_FROM_SKIN TB_INVALID_DIMENSION
-
-/** Specifies which height widgets in a AXIS_X layout should have,
- or which width widgets in a AXIS_Y layout should have.
- No matter what, it will still prioritize minimum and maximum for each widget. */
-enum LAYOUT_SIZE {
- LAYOUT_SIZE_GRAVITY, ///< Sizes depend on the gravity for each widget. (If the widget pulls
- ///< towards both directions, it should grow to all available space)
- LAYOUT_SIZE_PREFERRED, ///< Size will be the preferred so each widget may be sized differently. [default]
- LAYOUT_SIZE_AVAILABLE ///< Size should grow to all available space
-};
-
-/** Specifies which y position widgets in a AXIS_X layout should have,
- or which x position widgets in a AXIS_Y layout should have. */
-enum LAYOUT_POSITION {
- LAYOUT_POSITION_CENTER, ///< Position is centered. [default]
- LAYOUT_POSITION_LEFT_TOP, ///< Position is to the left for AXIS_Y layout and top for AXIS_X layout.
- LAYOUT_POSITION_RIGHT_BOTTOM, ///< Position is to the right for AXIS_Y layout and bottom for AXIS_X layout.
- LAYOUT_POSITION_GRAVITY, ///< Position depend on the gravity for each widget. (If the widget pulls
- ///< towards both directions, it will be centered)
-};
-
-/** Specifies which width widgets in a AXIS_X layout should have,
- or which height widgets in a AXIS_Y layout should have. */
-enum LAYOUT_DISTRIBUTION {
- LAYOUT_DISTRIBUTION_PREFERRED, ///< Size will be the preferred so each widget may be sized differently. [default]
- LAYOUT_DISTRIBUTION_AVAILABLE, ///< Size should grow to all available space
- LAYOUT_DISTRIBUTION_GRAVITY ///< Sizes depend on the gravity for each widget. (If the widget pulls
- ///< towards both directions, it should grow to all available space)
-};
-
-/** Specifies how widgets should be moved horizontally in a AXIS_X
- layout (or vertically in a AXIS_Y layout) if there is extra space
- available. */
-enum LAYOUT_DISTRIBUTION_POSITION {
- LAYOUT_DISTRIBUTION_POSITION_CENTER, ///< Position centered. [default]
- LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP, ///< Position to the upper left.
- LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM ///< Position to the lower right.
-};
-
-/** Layout order parameter for TBLayout::setLayoutOrder. */
-enum LAYOUT_ORDER {
- LAYOUT_ORDER_BOTTOM_TO_TOP, ///< From bottom to top widget (default creation order).
- LAYOUT_ORDER_TOP_TO_BOTTOM ///< From top to bottom widget.
-};
-
-/** Specifies what happens when there is not enough room for the layout, even
- when all the children have been shrunk to their minimum size. */
-enum LAYOUT_OVERFLOW {
- LAYOUT_OVERFLOW_CLIP, ///< Clip the chilren widgtes. [default]
- LAYOUT_OVERFLOW_SCROLL ///< Create a scroller.
- // LAYOUT_OVERFLOW_WRAP
-};
-
-/** TBLayout layouts its children along the given axis.
-
- Each widgets size depend on its preferred size (See TBWidget::getPreferredSize),
- gravity, and the specified layout settings (See SetLayoutSize, SetLayoutPosition
- SetLayoutOverflow, SetLayoutDistribution, SetLayoutDistributionPosition), and
- the available size.
-
- Each widget is also separated by the specified spacing (See SetSpacing).
-*/
-
-class TBLayout : public TBWidget {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBLayout, TBWidget);
-
- TBLayout(AXIS axis = AXIS_X);
-
- /** Set along which axis the content should be layouted */
- virtual void setAxis(AXIS axis) override;
- virtual AXIS getAxis() const override {
- return m_axis;
- }
-
- /** Set the spacing between widgets in this layout. Setting the default (SPACING_FROM_SKIN)
- will make it use the spacing specified in the skin. */
- void setSpacing(int spacing);
- int getSpacing() const {
- return m_spacing;
- }
-
- /** Set the overflow scroll. If there is not enough room for all children in this layout,
- it can scroll in the axis it's laid out. It does so automatically by wheel or panning also
- for other LAYOUT_OVERFLOW than LAYOUT_OVERFLOW_SCROLL. */
- void setOverflowScroll(int overflow_scroll);
- int getOverflowScroll() const {
- return m_overflow_scroll;
- }
-
- /** Set if a fadeout should be painter where the layout overflows or not. */
- void setPaintOverflowFadeout(bool paintFadeout) {
- m_packed.paint_overflow_fadeout = paintFadeout;
- }
-
- /** Set the layout size mode. See LAYOUT_SIZE. */
- void setLayoutSize(LAYOUT_SIZE size);
-
- /** Set the layout position mode. See LAYOUT_POSITION. */
- void setLayoutPosition(LAYOUT_POSITION pos);
-
- /** Set the layout size mode. See LAYOUT_OVERFLOW. */
- void setLayoutOverflow(LAYOUT_OVERFLOW overflow);
-
- /** Set the layout distribution mode. See LAYOUT_DISTRIBUTION. */
- void setLayoutDistribution(LAYOUT_DISTRIBUTION distribution);
-
- /** Set the layout distribution position mode. See LAYOUT_DISTRIBUTION_POSITION. */
- void setLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION distribution_pos);
-
- /** Set the layout order. The default is LAYOUT_ORDER_BOTTOM_TO_TOP, which begins
- from bottom to top (default creation order). */
- void setLayoutOrder(LAYOUT_ORDER order);
-
- virtual void invalidateLayout(INVALIDATE_LAYOUT il) override;
-
- virtual PreferredSize onCalculatePreferredContentSize(const SizeConstraints &constraints) override;
-
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual bool onEvent(const TBWidgetEvent &ev) override;
- virtual void onPaintChildren(const PaintProps &paint_props) override;
- virtual void onProcess() override;
- virtual void onResized(int oldW, int oldH) override;
- virtual void onInflateChild(TBWidget *child) override;
- virtual void getChildTranslation(int &x, int &y) const override;
- virtual void scrollTo(int x, int y) override;
- virtual TBWidget::ScrollInfo getScrollInfo() override;
-
-protected:
- AXIS m_axis;
- int m_spacing;
- int m_overflow;
- int m_overflow_scroll;
- union {
- struct {
- uint32_t layout_is_invalid : 1;
- uint32_t layout_mode_size : 4;
- uint32_t layout_mode_pos : 4;
- uint32_t layout_mode_overflow : 4;
- uint32_t layout_mode_dist : 4;
- uint32_t layout_mode_dist_pos : 4;
- uint32_t mode_reverse_order : 1;
- uint32_t paint_overflow_fadeout : 1;
- } m_packed;
- uint32_t m_packed_init;
- };
- void validateLayout(const SizeConstraints &constraints, PreferredSize *calculate_ps = nullptr);
- /** Can this TBLayout expand in its direction? */
- bool qualifyForExpansion(WIDGET_GRAVITY gravity) const;
- int getWantedHeight(WIDGET_GRAVITY gravity, const PreferredSize &ps, int available_height) const;
- TBWidget *getNextNonCollapsedWidget(TBWidget *child) const;
- int getTrailingSpace(TBWidget *child, int spacing) const;
- int calculateSpacing();
- TBWidget *getFirstInLayoutOrder() const;
- TBWidget *getNextInLayoutOrder(TBWidget *child) const;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_linklist.cpp b/src/modules/ui/turbobadger/tb/tb_linklist.cpp
deleted file mode 100644
index 34643d9d5..000000000
--- a/src/modules/ui/turbobadger/tb/tb_linklist.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_linklist.h"
-
-namespace tb {
-
-TBLinkListIterator::TBLinkListIterator(TBLinkList *linklist, TBLink *currentLink, bool forward)
- : m_linklist(linklist), m_current_link(currentLink), m_forward(forward) {
- doRegister();
-}
-
-TBLinkListIterator::TBLinkListIterator(const TBLinkListIterator &iter)
- : m_linklist(iter.m_linklist), m_current_link(iter.m_current_link), m_forward(iter.m_forward) {
- doRegister();
-}
-
-TBLinkListIterator::~TBLinkListIterator() {
- unregister();
-}
-
-void TBLinkListIterator::doRegister() {
- m_prev = nullptr;
- m_next = m_linklist->first_iterator;
- if (m_linklist->first_iterator != nullptr) {
- m_linklist->first_iterator->m_prev = this;
- }
- m_linklist->first_iterator = this;
-}
-
-void TBLinkListIterator::unregister() {
- if (m_linklist == nullptr) { // Already unregistered
- return;
- }
- if (m_prev != nullptr) {
- m_prev->m_next = m_next;
- }
- if (m_next != nullptr) {
- m_next->m_prev = m_prev;
- }
- if (m_linklist->first_iterator == this) {
- m_linklist->first_iterator = m_next;
- }
-}
-
-void TBLinkListIterator::unregisterAndClear() {
- unregister();
- m_linklist = nullptr;
- m_current_link = nullptr;
- m_prev = nullptr;
- m_next = nullptr;
-}
-
-const TBLinkListIterator &TBLinkListIterator::operator=(const TBLinkListIterator &iter) {
- if (m_linklist != iter.m_linklist) {
- // Change where we are registered if we change linklist.
- unregister();
- m_linklist = iter.m_linklist;
- doRegister();
- }
- m_linklist = iter.m_linklist;
- m_current_link = iter.m_current_link;
- m_forward = iter.m_forward;
- return *this;
-}
-
-void TBLinkListIterator::reset() {
- if (m_linklist != nullptr) {
- m_current_link = m_forward ? m_linklist->first : m_linklist->last;
- } else {
- m_current_link = nullptr;
- }
-}
-
-TBLink *TBLinkListIterator::getAndStep() {
- if (m_current_link == nullptr) {
- return nullptr;
- }
- TBLink *current = m_current_link;
- m_current_link = m_forward ? m_current_link->next : m_current_link->prev;
- return current;
-}
-
-void TBLinkListIterator::removeLink(TBLink *link) {
- // If the current link is being removed, step away from it
- if (m_current_link == link) {
- getAndStep();
- }
-}
-
-TBLinkList::~TBLinkList() {
- removeAll();
-
- // Make sure any live iterators for this linklist are cleared!
- while (first_iterator != nullptr) {
- first_iterator->unregisterAndClear();
- }
-}
-
-void TBLinkList::addFirst(TBLink *link) {
- core_assert(!link->linklist); // Link is already in some list!
- link->linklist = this;
- link->next = first;
- if (first != nullptr) {
- first->prev = link;
- }
- first = link;
- if (last == nullptr) {
- last = link;
- }
-}
-
-void TBLinkList::addLast(TBLink *link) {
- core_assert(!link->linklist); // Link is already in some list!
- link->linklist = this;
- link->prev = last;
- if (last != nullptr) {
- last->next = link;
- }
- last = link;
- if (first == nullptr) {
- first = link;
- }
-}
-
-void TBLinkList::addBefore(TBLink *link, TBLink *reference) {
- core_assert(reference->linklist == this); // Reference is not added to this list!
- link->linklist = this;
- link->prev = reference->prev;
- link->next = reference;
- if (reference->prev != nullptr) {
- reference->prev->next = link;
- } else {
- first = link;
- }
- reference->prev = link;
-}
-
-void TBLinkList::addAfter(TBLink *link, TBLink *reference) {
- core_assert(reference->linklist == this); // Reference is not added to this list!
- link->linklist = this;
- link->prev = reference;
- link->next = reference->next;
- if (reference->next != nullptr) {
- reference->next->prev = link;
- } else {
- last = link;
- }
- reference->next = link;
-}
-
-void TBLinkList::remove(TBLink *link) {
- core_assert(link->linklist == this); // Link is not added to this list!
-
- // Go through iterators and make sure there are no pointers
- // to the link we remove.
- TBLinkListIterator *iter = first_iterator;
- while (iter != nullptr) {
- iter->removeLink(link);
- iter = iter->m_next;
- }
- // Remove the link
- if (link->next != nullptr) {
- link->next->prev = link->prev;
- }
- if (link->prev != nullptr) {
- link->prev->next = link->next;
- }
- if (first == link) {
- first = link->next;
- }
- if (last == link) {
- last = link->prev;
- }
- link->linklist = nullptr;
- link->prev = nullptr;
- link->next = nullptr;
-}
-
-void TBLinkList::removeAll() {
- // Reset all iterators.
- TBLinkListIterator *iter = first_iterator;
- while (iter != nullptr) {
- iter->m_current_link = nullptr;
- iter = iter->m_next;
- }
- // Remove all links
- TBLink *link = first;
- while (link != nullptr) {
- TBLink *next = link->next;
- link->linklist = nullptr;
- link->prev = nullptr;
- link->next = nullptr;
- link = next;
- }
- first = nullptr;
- last = nullptr;
-}
-
-int TBLinkList::countLinks() const {
- int count = 0;
- for (TBLink *link = first; link != nullptr; link = link->next) {
- count++;
- }
- return count;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_linklist.h b/src/modules/ui/turbobadger/tb/tb_linklist.h
deleted file mode 100644
index 8415e2fc5..000000000
--- a/src/modules/ui/turbobadger/tb/tb_linklist.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "core/Assert.h"
-#include "tb_core.h"
-
-namespace tb {
-
-class TBLinkList;
-class TBLink;
-
-/** TBLinkListIterator - The backend class for a safe iteration of a TBLinkList.
-
- You would normally recieve a typed iterator from a TBLinkListOf::iterateForward
- or TBLinkListOf::iterateBackward, instead of creating this object directly.
-
- Safe iteration means that if a link is removed from a linked list, _all_ iterators that currently
- point to that link will automatically step to the next link in the iterators direction. */
-
-class TBLinkListIterator {
-public:
- TBLinkListIterator(const TBLinkListIterator &iter);
- TBLinkListIterator(TBLinkList *linklist, TBLink *current_link, bool forward);
- ~TBLinkListIterator();
-
- /** Set the iterator to the first link in we iterate forward,
- or set it to the last link if we iterate backward. */
- void reset();
-
- /** Get the current link or nullptr if out of bounds. */
- TBLink *get() const {
- return m_current_link;
- }
-
- /** Get the current link and step the iterator to the next (forward or backward). */
- TBLink *getAndStep();
-
- operator TBLink *() const {
- return m_current_link;
- }
-
- const TBLinkListIterator &operator=(const TBLinkListIterator &iter);
-
-private:
- TBLinkList *m_linklist; ///< The linklist we are iterating.
- TBLink *m_current_link; ///< The current link, or nullptr.
- bool m_forward; ///< true if we iterate from first to last item.
-
- TBLinkListIterator *m_prev; ///< Link in list of iterators for m_linklist
- TBLinkListIterator *m_next; ///< Link in list of iterators for m_linklist
-
- /** RemoveLink is called when removing/deleting links in the target linklist.
- This will make sure iterators skip the deleted item. */
- void removeLink(TBLink *link);
- friend class TBLinkList;
-
- /** Add ourself to the chain of iterators in the linklist. */
- void doRegister();
-
- /** Unlink ourself from the chain of iterators in the linklist. */
- void unregister();
- void unregisterAndClear();
-};
-
-/** TBLink - The backend class to be inserted in TBLinkList.
- Use the typed TBLinkOf for object storing! */
-
-class TBLink {
-public:
- TBLink() : prev(nullptr), next(nullptr), linklist(nullptr) {
- }
-
- /** Return true if the link is currently added to a list. */
- bool isInList() const {
- return linklist != nullptr;
- }
-
-public:
- TBLink *prev;
- TBLink *next;
- TBLinkList *linklist;
-};
-
-template class TBLinkOf : public TBLink {
-public:
- inline T *getPrev() const {
- return (T *)prev;
- }
- inline T *getNext() const {
- return (T *)next;
- }
-};
-
-/** TBLinkList - This is the backend for TBLinkListOf and TBLinkListAutoDeleteOf.
- You should use the typed TBLinkListOf or TBLinkListAutoDeleteOf for object storing! */
-
-class TBLinkList {
-public:
- TBLinkList() : first(nullptr), last(nullptr), first_iterator(nullptr) {
- }
- ~TBLinkList();
-
- void remove(TBLink *link);
- void removeAll();
-
- void addFirst(TBLink *link);
- void addLast(TBLink *link);
-
- void addBefore(TBLink *link, TBLink *reference);
- void addAfter(TBLink *link, TBLink *reference);
-
- bool containsLink(TBLink *link) const {
- return link->linklist == this;
- }
-
- bool hasLinks() const {
- return first != nullptr;
- }
-
- int countLinks() const;
-
-public:
- TBLink *first;
- TBLink *last;
- TBLinkListIterator *first_iterator;
-};
-
-/** TBLinkListOf is a double linked linklist. */
-
-template class TBLinkListOf {
-public:
- /** Remove link from this linklist. */
- void remove(T *link) {
- m_linklist.remove(static_cast *>(link));
- }
-
- /** Remove link from this linklist and delete it. */
- void doDelete(T *link) {
- m_linklist.remove(static_cast *>(link));
- delete link;
- }
-
- /** Remove all links without deleting them. */
- void removeAll() {
- m_linklist.removeAll();
- }
-
- /** Delete all links in this linklist. */
- void deleteAll() {
- while (T *t = getFirst()) {
- doDelete(t);
- }
- }
-
- /** Add link first in this linklist. */
- void addFirst(T *link) {
- m_linklist.addFirst(static_cast *>(link));
- }
-
- /** Add link last in this linklist. */
- void addLast(T *link) {
- m_linklist.addLast(static_cast *>(link));
- }
-
- /** Add link before the reference link (which must be added to this linklist). */
- void addBefore(T *link, T *reference) {
- m_linklist.addBefore(static_cast *>(link), reference);
- }
-
- /** Add link after the reference link (which must be added to this linklist). */
- void addAfter(T *link, T *reference) {
- m_linklist.addAfter(static_cast *>(link), reference);
- }
-
- /** Return true if the link is currently added to this linklist. */
- bool containsLink(T *link) const {
- return m_linklist.containsLink(static_cast *>(link));
- }
-
- /** Get the first link, or nullptr. */
- T *getFirst() const {
- return (T *)static_cast *>(m_linklist.first);
- }
-
- /** Get the last link, or nullptr. */
- T *getLast() const {
- return (T *)static_cast *>(m_linklist.last);
- }
-
- /** Return true if this linklist contains any links. */
- bool hasLinks() const {
- return m_linklist.hasLinks();
- }
-
- /** Count the number of links in this list by iterating through all links. */
- int countLinks() const {
- return m_linklist.countLinks();
- }
-
- /** Typed iterator for safe iteration. For more info, see TBLinkListIterator. */
- class Iterator : public TBLinkListIterator {
- public:
- Iterator(TBLinkListOf *linklistof, bool forward)
- : TBLinkListIterator(&linklistof->m_linklist,
- forward ? linklistof->m_linklist.first : linklistof->m_linklist.last, forward) {
- }
- Iterator(TBLinkListOf *linklistof, T *link, bool forward)
- : TBLinkListIterator(&linklistof->m_linklist, link, forward) {
- }
- inline T *get() const {
- return (T *)static_cast *>(TBLinkListIterator::get());
- }
- inline T *getAndStep() {
- return (T *)static_cast *>(TBLinkListIterator::getAndStep());
- }
- inline operator T *() const {
- return (T *)static_cast *>(get());
- }
- };
-
- /** Get a forward iterator that starts with the first link. */
- Iterator iterateForward() {
- return Iterator(this, true);
- }
-
- /** Get a forward iterator that starts with the given link. */
- Iterator iterateForward(T *link) {
- return Iterator(this, link, true);
- }
-
- /** Get a backward iterator that starts with the last link. */
- Iterator iterateBackward() {
- return Iterator(this, false);
- }
-
- /** Get a backward iterator that starts with the given link. */
- Iterator iterateBackward(T *link) {
- return Iterator(this, link, false);
- }
-
-private:
- TBLinkList m_linklist;
-};
-
-/** TBLinkListAutoDeleteOf is a double linked linklist that deletes all links on destruction. */
-
-template class TBLinkListAutoDeleteOf : public TBLinkListOf {
-public:
- ~TBLinkListAutoDeleteOf() {
- TBLinkListOf::deleteAll();
- }
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_list.cpp b/src/modules/ui/turbobadger/tb/tb_list.cpp
deleted file mode 100644
index 5e4fbdb27..000000000
--- a/src/modules/ui/turbobadger/tb/tb_list.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_list.h"
-#include "core/Assert.h"
-#include "core/StandardLib.h"
-#include "tb_core.h"
-
-namespace tb {
-
-bool TBListBackend::add(void *data) {
- if (!growIfNeeded()) {
- return false;
- }
- m_data->list[m_data->num] = data;
- m_data->num++;
- return true;
-}
-
-bool TBListBackend::add(void *data, int index) {
- core_assert(index >= 0 && index <= getNumItems());
- if (!growIfNeeded()) {
- return false;
- }
- if (index < m_data->num) {
- SDL_memmove(&m_data->list[index + 1], &m_data->list[index], (m_data->num - index) * sizeof(void *));
- }
- m_data->list[index] = data;
- m_data->num++;
- return true;
-}
-
-void TBListBackend::set(void *data, int index) {
- core_assert(index >= 0 && index < getNumItems());
- m_data->list[index] = data;
-}
-
-void *TBListBackend::removeFast(int index) {
- core_assert(index >= 0 && index < getNumItems());
- void *data = m_data->list[index];
- m_data->list[index] = m_data->list[m_data->num - 1];
- m_data->num--;
- return data;
-}
-
-void *TBListBackend::remove(int index) {
- core_assert(index >= 0 && index < getNumItems());
- void *data = m_data->list[index];
- if (index < m_data->num - 1) {
- SDL_memmove(&m_data->list[index], &m_data->list[index + 1], (m_data->num - index - 1) * sizeof(void *));
- }
- m_data->num--;
- return data;
-}
-
-void TBListBackend::removeAll() {
- core_free(m_data);
- m_data = nullptr;
-}
-
-void TBListBackend::swap(int index1, int index2) {
- core_assert(index1 >= 0 && index1 < getNumItems());
- core_assert(index2 >= 0 && index2 < getNumItems());
- void *tmp = m_data->list[index1];
- m_data->list[index1] = m_data->list[index2];
- m_data->list[index2] = tmp;
-}
-
-int TBListBackend::find(const void *data) const {
- int num = getNumItems();
- for (int i = 0; i < num; i++) {
- if (get(i) == data) {
- return i;
- }
- }
- return -1;
-}
-
-void *TBListBackend::get(int index) const {
- core_assert(index >= 0 && index < getNumItems());
- return m_data->list[index];
-}
-
-bool TBListBackend::reserve(int newCapacity) {
- core_assert(newCapacity > 0);
- if (newCapacity > getCapacity()) {
- int num = getNumItems();
- if (char *new_data = (char *)core_realloc(m_data, sizeof(TBLIST_DATA) + sizeof(void *) * (newCapacity))) {
- m_data = (TBLIST_DATA *)new_data;
- m_data->num = num;
- m_data->capacity = newCapacity;
- m_data->list = (void **)(new_data + sizeof(TBLIST_DATA));
- return true;
- }
- return false;
- }
- return true;
-}
-
-bool TBListBackend::growIfNeeded() {
- int capacity = getCapacity();
- if (getNumItems() == capacity) {
- return reserve(capacity == 0 ? 4 : capacity * 2);
- }
- return true;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_list.h b/src/modules/ui/turbobadger/tb/tb_list.h
deleted file mode 100644
index 57d3f45a9..000000000
--- a/src/modules/ui/turbobadger/tb/tb_list.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-namespace tb {
-
-/** TBList is a list (array) of pointers to any kind of objects.
- This is the backend for TBListOf and TBListAutoDeleteOf.
- You should use the typed TBListOf or TBListAutoDeleteOf for object storing! */
-class TBListBackend {
-public:
- TBListBackend() : m_data(nullptr) {
- }
- ~TBListBackend() {
- removeAll();
- }
- bool reserve(int newCapacity);
- bool growIfNeeded();
- bool add(void *data);
- bool add(void *data, int index);
- void set(void *data, int index);
- void *get(int index) const;
- void *operator[](int index) const {
- return get(index);
- }
- void *removeFast(int index);
- void *remove(int index);
- void removeAll();
- void swap(int index1, int index2);
- int find(const void *data) const;
- int getNumItems() const {
- return m_data != nullptr ? m_data->num : 0;
- }
- int getCapacity() const {
- return m_data != nullptr ? m_data->capacity : 0;
- }
-
-private:
- struct TBLIST_DATA {
- int num;
- int capacity;
- void **list;
- };
- TBLIST_DATA *m_data;
-};
-
-/** TBListOf is a list (array) of pointers to the specified object type.
- Note: The objects won't be deleted automatically. If you want that,
- use TBListAutoDeleteOf! */
-template class TBListOf {
-public:
- /** Make sure there is space for at least num items in the list. Returns false on OOM failure. */
- bool reserve(int num) {
- return m_list.reserve(num);
- }
-
- /** Make sure there is space for at least one more item in the list. Returns false on OOM failure.
- There's no need to call this, but it can make OOM handling easier in some situations since you
- can guarantee there is space is in a list *before* you allocate an object to insert into it. */
- bool growIfNeeded() {
- return m_list.growIfNeeded();
- }
-
- /** Add data at the end of the list. Returns false on OOM failure. */
- bool add(T *data) {
- return m_list.add(data);
- }
-
- /** Add data at the given index in the list. Returns false on OOM failure. */
- bool add(T *data, int index) {
- return m_list.add(data, index);
- }
-
- /** Replace the item at the index with the new data */
- void set(T *data, int index) {
- m_list.set(data, index);
- }
-
- /** Returns the content at position index. */
- T *get(int index) const {
- return (T *)m_list.get(index);
- }
-
- /** Returns the content at position index. */
- T *operator[](int index) const {
- return (T *)m_list.get(index);
- }
-
- /** Remove the item at position index from the list and returns the pointer.
- This method should only be used when the order of the list is not important.
- If the order is important, use Remove() */
- T *removeFast(int index) {
- return (T *)m_list.removeFast(index);
- }
-
- /** Remove the item at position index from the list and returns the pointer. */
- T *remove(int index) {
- return (T *)m_list.remove(index);
- }
-
- /** Deletes the item at position index after removing it from the list.
- This method should only be used when the order of the list is not important.
- If the order is important, use Delete() */
- void deleteFast(int index) {
- delete (T *)m_list.removeFast(index);
- }
-
- /** Deletes the item at position index after removing it from the list. */
- void doDelete(int index) {
- delete (T *)m_list.remove(index);
- }
-
- /** Remove all items without deleding them. */
- void removeAll() {
- m_list.removeAll();
- }
-
- /** Remove and delete all items from the list. */
- void deleteAll() {
- for (int i = 0; i < getNumItems(); i++) {
- delete (T *)get(i);
- }
- m_list.removeAll();
- }
-
- /** Swap the items at index1 and index2 */
- void swap(int index1, int index2) {
- m_list.swap(index1, index2);
- }
-
- /** Search for the item with the given data and return the found index, or -1 if not found. */
- int find(const T *data) const {
- return m_list.find(data);
- }
-
- /** Get the number of items in the list. */
- int getNumItems() const {
- return m_list.getNumItems();
- }
-
- /** Get the capacity of the list number of items it can hold without allocating more memory) */
- int getCapacity() const {
- return m_list.getCapacity();
- }
-
-private:
- TBListBackend m_list;
-};
-
-/** TBListAutoDeleteOf is a list (array) of pointers to the specified object type.
- The objects will be deleted automatically on destruction. */
-template class TBListAutoDeleteOf : public TBListOf {
-public:
- ~TBListAutoDeleteOf() {
- TBListOf::deleteAll();
- }
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_menu_window.cpp b/src/modules/ui/turbobadger/tb/tb_menu_window.cpp
deleted file mode 100644
index 52455b353..000000000
--- a/src/modules/ui/turbobadger/tb/tb_menu_window.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_menu_window.h"
-#include "tb_widgets_listener.h"
-
-namespace tb {
-
-TBMenuWindow::TBMenuWindow(TBWidget *target, const TBID &id) : TBPopupWindow(target) {
- setID(id);
- setSkinBg(TBIDC("TBMenuWindow"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- m_select_list.getScrollContainer()->setAdaptToContentSize(true);
- m_select_list.setIsFocusable(false); ///< Avoid it autoclosing its window on click
- m_select_list.setSkinBg("");
- m_select_list.setRect(getPaddingRect());
- m_select_list.setGravity(WIDGET_GRAVITY_ALL);
- addChild(&m_select_list);
-}
-
-TBMenuWindow::~TBMenuWindow() {
- removeChild(&m_select_list);
-}
-
-void TBMenuWindow::onDie() {
- m_select_list.setSource(nullptr);
-}
-
-bool TBMenuWindow::show(TBSelectItemSource *source, const TBPopupAlignment &alignment, int initialValue) {
- m_select_list.setValue(initialValue);
- m_select_list.setSource(source);
- m_select_list.validateList();
-
- return TBPopupWindow::show(alignment);
-}
-
-bool TBMenuWindow::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_CLICK && &m_select_list == ev.target) {
- TBWidgetSafePointer this_widget(this);
-
- // Invoke the click on the target
- TBWidgetEvent target_ev(EVENT_TYPE_CLICK);
- target_ev.ref_id = ev.ref_id;
- invokeEvent(target_ev);
-
- // If target not deleted, close
- if (this_widget.get() != nullptr) {
- close();
- }
- return true;
- }
- return TBPopupWindow::onEvent(ev);
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_menu_window.h b/src/modules/ui/turbobadger/tb/tb_menu_window.h
deleted file mode 100644
index 94489e521..000000000
--- a/src/modules/ui/turbobadger/tb/tb_menu_window.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_popup_window.h"
-#include "tb_select.h"
-
-namespace tb {
-
-/** TBMenuWindow is a popup window that shows a list of items (TBSelectList).
-
- When selected it will invoke a click with the id given to the menu,
- and the id of the clicked item as ref_id, and then close itself.
-
- It may open sub items as new windows at the same time as this window is open.*/
-
-class TBMenuWindow : public TBPopupWindow {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBMenuWindow, TBPopupWindow);
-
- TBMenuWindow(TBWidget *target, const TBID &id);
- ~TBMenuWindow();
-
- bool show(TBSelectItemSource *source, const TBPopupAlignment &alignment, int initial_value = -1);
-
- TBSelectList *getList() {
- return &m_select_list;
- }
-
- virtual bool onEvent(const TBWidgetEvent &ev) override;
- virtual void onDie() override;
-
-private:
- TBSelectList m_select_list;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_message_window.cpp b/src/modules/ui/turbobadger/tb/tb_message_window.cpp
deleted file mode 100644
index 7e31b564c..000000000
--- a/src/modules/ui/turbobadger/tb/tb_message_window.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_message_window.h"
-#include "core/Assert.h"
-#include "tb_editfield.h"
-#include "tb_language.h"
-#include "tb_widgets_reader.h"
-
-namespace tb {
-
-// == TBMessageWindow =======================================================================================
-
-TBMessageWindow::TBMessageWindow(TBWidget *target, const TBID &id) : m_target(target) {
- TBWidgetListener::addGlobalListener(this);
- setID(id);
-}
-
-TBMessageWindow::~TBMessageWindow() {
- TBWidgetListener::removeGlobalListener(this);
- if (TBWidget *dimmer = m_dimmer.get()) {
- dimmer->removeFromParent();
- delete dimmer;
- }
-}
-
-bool TBMessageWindow::show(const char *title, const char *message, TBMessageWindowSettings *settings) {
- TBWidget *target = m_target.get();
- if (target == nullptr) {
- return false;
- }
-
- TBMessageWindowSettings default_settings;
- if (settings == nullptr) {
- settings = &default_settings;
- }
-
- TBWidget *root = target->getParentRoot();
-
- const char *source = "TBLayout: axis: y, distribution: available\n"
- " TBLayout: distribution: available, size: available\n"
- " TBSkinImage: id: 2\n"
- " TBEditField: multiline: 1, readonly: 1, id: 1\n"
- " TBLayout: distribution-position: right bottom, id: 3\n";
- if (!g_widgets_reader->loadData(getContentRoot(), source)) {
- return false;
- }
-
- setText(title);
-
- getWidgetByIDAndType(2)->setSkinBg(settings->icon_skin);
-
- TBEditField *editfield = getWidgetByIDAndType(1);
- editfield->setStyling(settings->styling);
- editfield->setText(message);
- editfield->setTextAlign(settings->align);
- editfield->setSkinBg("");
-
- // Create buttons
- if (settings->msg == TB_MSG_OK) {
- addButton("TBMessageWindow.ok", true);
- } else if (settings->msg == TB_MSG_OK_CANCEL) {
- addButton("TBMessageWindow.ok", true);
- addButton("TBMessageWindow.cancel", false);
- } else if (settings->msg == TB_MSG_YES_NO) {
- addButton("TBMessageWindow.yes", true);
- addButton("TBMessageWindow.no", false);
- } else if (settings->msg == TB_MSG_YES_NO_CANCEL) {
- addButton("TBMessageWindow.yes", true);
- addButton("TBMessageWindow.no", false);
- addButton("TBMessageWindow.cancel", false);
- }
-
- // Size to fit content. This will use the default size of the textfield.
- resizeToFitContent();
- TBRect rect = getRect();
-
- // Get how much we overflow the textfield has given the current width, and grow our height to show all we can.
- // FIX: It would be better to use adapt-to-content on the editfield to achieve the most optimal size.
- // At least when we do full blown multi pass size checking.
- rect.h += editfield->getStyleEdit()->getOverflowY();
-
- // Create background dimmer
- if (settings->dimmer) {
- if (TBDimmer *dimmer = new TBDimmer) {
- root->addChild(dimmer);
- m_dimmer.set(dimmer);
- }
- }
-
- // Center and size to the new height
- TBRect bounds(0, 0, root->getRect().w, root->getRect().h);
- setRect(rect.centerIn(bounds).moveIn(bounds).clip(bounds));
- root->addChild(this);
- return true;
-}
-
-void TBMessageWindow::addButton(const TBID &id, bool focused) {
- TBLayout *layout = getWidgetByIDAndType(3);
- if (layout == nullptr) {
- return;
- }
- if (TBButton *btn = new TBButton) {
- btn->setID(id);
- btn->setText(g_tb_lng->getString(btn->getID()));
- layout->addChild(btn);
- if (focused) {
- btn->setFocus(WIDGET_FOCUS_REASON_UNKNOWN);
- }
- }
-}
-
-bool TBMessageWindow::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_CLICK && ev.target->isOfType()) {
- TBWidgetSafePointer this_widget(this);
-
- // Invoke the click on the target
- TBWidgetEvent target_ev(EVENT_TYPE_CLICK);
- target_ev.ref_id = ev.target->getID();
- invokeEvent(target_ev);
-
- // If target got deleted, close
- if (this_widget.get() != nullptr) {
- close();
- }
- return true;
- }
- if (ev.type == EVENT_TYPE_KEY_DOWN && ev.special_key == TB_KEY_ESC) {
- TBWidgetEvent click_ev(EVENT_TYPE_CLICK);
- m_close_button.invokeEvent(click_ev);
- return true;
- }
- return TBWindow::onEvent(ev);
-}
-
-void TBMessageWindow::onDie() {
- if (TBWidget *dimmer = m_dimmer.get()) {
- dimmer->die();
- }
-}
-
-void TBMessageWindow::onWidgetDelete(TBWidget *widget) {
- // If the target widget is deleted, close!
- if (m_target.get() == nullptr) {
- close();
- }
-}
-
-bool TBMessageWindow::onWidgetDying(TBWidget *widget) {
- // If the target widget or an ancestor of it is dying, close!
- if (widget == m_target.get() || widget->isAncestorOf(m_target.get())) {
- close();
- }
- return false;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_message_window.h b/src/modules/ui/turbobadger/tb/tb_message_window.h
deleted file mode 100644
index 78f6211a3..000000000
--- a/src/modules/ui/turbobadger/tb/tb_message_window.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_widgets_listener.h"
-#include "tb_window.h"
-
-namespace tb {
-
-enum TB_MSG {
- TB_MSG_OK,
- TB_MSG_OK_CANCEL,
- TB_MSG_YES_NO,
- TB_MSG_YES_NO_CANCEL,
-};
-
-/** TBMessageWindowSettings contains additional settings for TBMessageWindow. */
-class TBMessageWindowSettings {
-public:
- TBMessageWindowSettings() : msg(TB_MSG_OK), dimmer(false), styling(false) {
- }
- TBMessageWindowSettings(TB_MSG msg, const TBID &iconSkin)
- : msg(msg), icon_skin(iconSkin), dimmer(false), styling(false), align(TB_TEXT_ALIGN_LEFT) {
- }
-
-public:
- TB_MSG msg; ///< The type of response for the message.
- TBID icon_skin; ///< The icon skin (0 for no icon)
- bool dimmer; ///< Set to true to dim background widgets by a TBDimmer.
- bool styling; ///< Enable styling in the textfield.
- TB_TEXT_ALIGN align = TB_TEXT_ALIGN_LEFT; ///< Text alignment in message box.
-};
-
-/** TBMessageWindow is a window for showing simple messages.
- Events invoked in this window will travel up through the target widget.
-
- When the user click any of its buttons, it will invoke a click event
- (with the window ID), with the clicked buttons id as ref_id.
- Then it will delete itself.
-
- If the target widget is deleted while this window is alive, the
- window will delete itself. */
-class TBMessageWindow : public TBWindow, private TBWidgetListener {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBMessageWindow, TBWindow);
-
- TBMessageWindow(TBWidget *target, const TBID &id);
- virtual ~TBMessageWindow();
-
- bool show(const char *title, const char *message, TBMessageWindowSettings *settings = nullptr);
-
- virtual TBWidget *getEventDestination() const override {
- return m_target.get();
- }
-
- virtual bool onEvent(const TBWidgetEvent &ev) override;
- virtual void onDie() override;
-
-private:
- void addButton(const TBID &id, bool focused);
- // TBWidgetListener
- virtual void onWidgetDelete(TBWidget *widget) override;
- virtual bool onWidgetDying(TBWidget *widget) override;
- TBWidgetSafePointer m_dimmer;
- TBWidgetSafePointer m_target;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_msg.cpp b/src/modules/ui/turbobadger/tb/tb_msg.cpp
deleted file mode 100644
index 126352a01..000000000
--- a/src/modules/ui/turbobadger/tb/tb_msg.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_msg.h"
-#include "tb_system.h"
-#include
-
-namespace tb {
-
-/** List of all delayed messages */
-TBLinkListOf g_all_delayed_messages;
-
-/** List of all nondelayed messages. */
-TBLinkListOf g_all_normal_messages;
-
-TBMessage::TBMessage(const TBID &message, TBMessageData *data, double fireTimeMs, TBMessageHandler *mh)
- : message(message), data(data), fire_time_ms(fireTimeMs), mh(mh) {
-}
-
-TBMessage::~TBMessage() {
- delete data;
-}
-
-TBMessageHandler::TBMessageHandler() {
-}
-
-TBMessageHandler::~TBMessageHandler() {
- deleteAllMessages();
-}
-
-bool TBMessageHandler::postMessageDelayed(const TBID &message, TBMessageData *data, uint32_t delayInMs) {
- return postMessageOnTime(message, data, TBSystem::getTimeMS() + (double)delayInMs);
-}
-
-bool TBMessageHandler::postMessageOnTime(const TBID &message, TBMessageData *data, double fireTime) {
- if (TBMessage *msg = new TBMessage(message, data, fireTime, this)) {
- // Find the message that is already in the list that should fire later, so we can
- // insert msg just before that. (Always keep the list ordered after fire time)
-
- // NOTE: If another message is added during OnMessageReceived, it might or might not be fired
- // in the right order compared to other delayed messages, depending on if it's inserted before or
- // after the message being processed!
-
- TBMessage *later_msg = nullptr;
- TBMessageLink *link = g_all_delayed_messages.getFirst();
- while (link != nullptr) {
- TBMessage *msg_in_list = static_cast(link);
- if (msg_in_list->fire_time_ms > msg->fire_time_ms) {
- later_msg = msg_in_list;
- break;
- }
- link = link->getNext();
- }
-
- // Add it to the global list in the right order.
- if (later_msg != nullptr) {
- g_all_delayed_messages.addBefore(msg, later_msg);
- } else {
- g_all_delayed_messages.addLast(msg);
- }
-
- // Add it to the list in messagehandler.
- m_messages.addLast(msg);
-
- // If we added it first and there's no normal messages, the next fire time has
- // changed and we have to reschedule the timer.
- if ((g_all_normal_messages.getFirst() == nullptr) && g_all_delayed_messages.getFirst() == msg) {
- TBSystem::rescheduleTimer(msg->fire_time_ms);
- }
- return true;
- }
- return false;
-}
-
-bool TBMessageHandler::postMessage(const TBID &message, TBMessageData *data) {
- if (TBMessage *msg = new TBMessage(message, data, 0, this)) {
- g_all_normal_messages.addLast(msg);
- m_messages.addLast(msg);
-
- // If we added it and there was no messages, the next fire time has
- // changed and we have to reschedule the timer.
- if (g_all_normal_messages.getFirst() == msg) {
- TBSystem::rescheduleTimer(0);
- }
- return true;
- }
- return false;
-}
-
-TBMessage *TBMessageHandler::getMessageByID(const TBID &message) {
- TBLinkListOf::Iterator iter = m_messages.iterateForward();
- while (TBMessage *msg = iter.getAndStep()) {
- if (msg->message == message) {
- return msg;
- }
- }
- return nullptr;
-}
-
-void TBMessageHandler::deleteMessage(TBMessage *msg) {
- core_assert(msg->mh == this); // This is not the message handler owning the message!
-
- // Remove from global list (g_all_delayed_messages or g_all_normal_messages)
- if (g_all_delayed_messages.containsLink(msg)) {
- g_all_delayed_messages.remove(msg);
- } else if (g_all_normal_messages.containsLink(msg)) {
- g_all_normal_messages.remove(msg);
- }
-
- // Remove from local list
- m_messages.remove(msg);
-
- delete msg;
-
- // Note: We could call TBSystem::RescheduleTimer if we think that deleting
- // this message changed the time for the next message.
-}
-
-void TBMessageHandler::deleteAllMessages() {
- while (TBMessage *msg = m_messages.getFirst()) {
- deleteMessage(msg);
- }
-}
-
-// static
-void TBMessageHandler::processMessages() {
- // Handle delayed messages
- TBLinkListOf::Iterator iter = g_all_delayed_messages.iterateForward();
- while (TBMessage *msg = static_cast(iter.getAndStep())) {
- if (TBSystem::getTimeMS() >= msg->fire_time_ms) {
- // Remove from global list
- g_all_delayed_messages.remove(msg);
- // Remove from local list
- msg->mh->m_messages.remove(msg);
-
- msg->mh->onMessageReceived(msg);
-
- delete msg;
- } else {
- break; // Since the list is sorted, all remaining messages should fire later
- }
- }
-
- // Handle normal messages
- iter = g_all_normal_messages.iterateForward();
- while (TBMessage *msg = static_cast(iter.getAndStep())) {
- // Remove from global list
- g_all_normal_messages.remove(msg);
- // Remove from local list
- msg->mh->m_messages.remove(msg);
-
- msg->mh->onMessageReceived(msg);
-
- delete msg;
- }
-}
-
-// static
-double TBMessageHandler::getNextMessageFireTime() {
- if (g_all_normal_messages.getFirst() != nullptr) {
- return 0;
- }
-
- if (g_all_delayed_messages.getFirst() != nullptr) {
- TBMessage *first_delayed_msg = static_cast(g_all_delayed_messages.getFirst());
- return first_delayed_msg->fire_time_ms;
- }
-
- return TB_NOT_SOON;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_msg.h b/src/modules/ui/turbobadger/tb/tb_msg.h
deleted file mode 100644
index 2b58e10fd..000000000
--- a/src/modules/ui/turbobadger/tb/tb_msg.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-#include "tb_id.h"
-#include "tb_linklist.h"
-#include "tb_object.h"
-#include "tb_value.h"
-
-namespace tb {
-
-class TBMessageHandler;
-
-/** TB_NOT_SOON is returned from TBMessageHandler::getNextMessageFireTime
- and means that there is currently no more messages to process. */
-#define TB_NOT_SOON 0xffffffff
-
-/** TBMessageData holds custom data to send with a posted message. */
-
-class TBMessageData : public TBTypedObject {
-public:
- TBMessageData() {
- }
- TBMessageData(int v1, int v2) : v1(v1), v2(v2) {
- }
- virtual ~TBMessageData() {
- }
-
-public:
- TBValue v1; ///< Use for anything
- TBValue v2; ///< Use for anything
- TBID id1; ///< Use for anything
- TBID id2; ///< Use for anything
-};
-
-/** TBMessageLink should never be created or subclassed anywhere except in TBMessage.
- It's only purpose is to add a extra typed link for TBMessage, since it needs to be
- added in multiple lists. */
-class TBMessageLink : public TBLinkOf {};
-
-/** TBMessage is a message created and owned by TBMessageHandler.
- It carries a message id, and may also carry a TBMessageData with
- additional parameters. */
-
-class TBMessage : public TBLinkOf, public TBMessageLink {
-private:
- TBMessage(const TBID &message, TBMessageData *data, double fire_time_ms, TBMessageHandler *mh);
- ~TBMessage();
-
-public:
- TBID message; ///< The message id
- TBMessageData *data; ///< The message data, or nullptr if no data is set
-
- /** The time which a delayed message should have fired (0 for non delayed messages) */
- double getFireTime() {
- return fire_time_ms;
- }
-
-private:
- friend class TBMessageHandler;
- double fire_time_ms;
- TBMessageHandler *mh;
-};
-
-/** TBMessageHandler handles a list of pending messages posted to itself.
- Messages can be delivered immediately or after a delay.
- Delayed message are delivered as close as possible to the time they should fire.
- Immediate messages are put on a queue and delivered as soon as possible, after any delayed
- messages that has passed their delivery time. This queue is global (among all TBMessageHandlers) */
-
-class TBMessageHandler {
-public:
- TBMessageHandler();
- virtual ~TBMessageHandler();
-
- /** Posts a message to the target after a delay.
- data may be nullptr if no extra data need to be sent. It will be deleted
- automatically when the message is deleted. */
- bool postMessageDelayed(const TBID &message, TBMessageData *data, uint32_t delay_in_ms);
-
- /** Posts a message to the target at the given time (relative to TBSystem::getTimeMS()).
- data may be nullptr if no extra data need to be sent. It will be deleted
- automatically when the message is deleted. */
- bool postMessageOnTime(const TBID &message, TBMessageData *data, double fire_time);
-
- /** Posts a message to the target.
- data may be nullptr if no extra data need to be sent. It will be deleted
- automatically when the message is deleted. */
- bool postMessage(const TBID &message, TBMessageData *data);
-
- /** Check if this messagehandler has a pending message with the given id.
- Returns the message if found, or nullptr.
- If you want to delete the message, call DeleteMessage. */
- TBMessage *getMessageByID(const TBID &message);
-
- /** Delete the message from this message handler. */
- void deleteMessage(TBMessage *msg);
-
- /** Delete all messages from this message handler. */
- void deleteAllMessages();
-
- /** Called when a message is delivered.
-
- This message won't be found using getMessageByID. It is already removed from the list.
- You should not call DeleteMessage on this message. That is done automatically after this method exit. */
- virtual void onMessageReceived(TBMessage *msg) {
- }
-
- // == static methods to handle the queue of messages ====================================================
-
- /** Process any messages in queue. */
- static void processMessages();
-
- /** Get when the time when ProcessMessages needs to be called again.
- Always returns 0 if there is nondelayed messages to process, which means it needs to be called asap.
- If there's only delayed messages to process, it returns the time that the earliest delayed message should be
- fired. If there's no more messages to process at the moment, it returns TB_NOT_SOON (No call to ProcessMessages
- is needed). */
- static double getNextMessageFireTime();
-
-private:
- TBLinkListOf m_messages;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_node_ref_tree.cpp b/src/modules/ui/turbobadger/tb/tb_node_ref_tree.cpp
deleted file mode 100644
index ce076e253..000000000
--- a/src/modules/ui/turbobadger/tb/tb_node_ref_tree.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_node_ref_tree.h"
-#include "tb_language.h"
-#include "tb_system.h"
-
-namespace tb {
-
-// static
-TBLinkListOf TBNodeRefTree::s_ref_trees;
-
-TBNodeRefTree::TBNodeRefTree(const char *name) : m_name(name), m_name_id(name) {
- s_ref_trees.addLast(this);
-}
-
-TBNodeRefTree::~TBNodeRefTree() {
- s_ref_trees.remove(this);
-}
-
-TBValue &TBNodeRefTree::getValue(const char *request) {
- if (TBNode *node = m_node.getNodeFollowRef(request)) {
- return node->getValue();
- }
- Log::debug("TBNodeRefTree::getValue - Request not found: %s", request);
- static TBValue nullval;
- return nullval;
-}
-
-// static
-TBValue &TBNodeRefTree::getValueFromTree(const char *request) {
- core_assert(*request == '@');
- TBNode tmp;
- tmp.getValue().setString(request, TBValue::SET_AS_STATIC);
- TBNode *node = TBNodeRefTree::followNodeRef(&tmp);
- if (node != &tmp) {
- return node->getValue();
- }
- static TBValue nullval;
- return nullval;
-}
-
-void TBNodeRefTree::setValue(const char *request, const TBValue &value) {
- if (TBNode *node = m_node.getNode(request, TBNode::GET_MISS_POLICY_CREATE)) {
- // FIX: Only invoke the listener if it really changed.
- node->getValue().copy(value);
- invokeChangeListenersInternal(request);
- }
-}
-
-void TBNodeRefTree::invokeChangeListenersInternal(const char *request) {
- TBLinkListOf::Iterator iter = m_listeners.iterateForward();
- while (TBNodeRefTreeListener *listener = iter.getAndStep()) {
- listener->onDataChanged(this, request);
- }
-}
-
-// static
-TBNodeRefTree *TBNodeRefTree::getRefTree(const char *name, int nameLen) {
- for (TBNodeRefTree *rt = s_ref_trees.getFirst(); rt != nullptr; rt = rt->getNext()) {
- if (SDL_strncmp(rt->getName(), name, nameLen) == 0) {
- return rt;
- }
- }
- return nullptr;
-}
-
-// static
-TBNode *TBNodeRefTree::followNodeRef(TBNode *node) {
- // Detect circular loops by letting this call get a unique id.
- // Update the id on each visited node and if it's already set,
- // there's a loop. This cost the storage of id in each TBNode,
- // and assumes the look up doesn't cause other lookups
- // recursively.
- // FIX: Switch to hare and teleporting tortouise?
- static uint32_t s_cycle_id = 0;
- uint32_t cycle_id = ++s_cycle_id;
- TBNode *start_node = node;
-
- while (node->getValue().isString()) {
- // If not a reference at all, we're done.
- const char *node_str = node->getValue().getString();
- if (*node_str != '@') {
- break;
- }
-
- // If there's no tree name and request, we're done. It's probably a language string.
- const char *name_start = node_str + 1;
- const char *name_end = TBNode::getNextNodeSeparator(name_start);
- if (*name_end == 0) {
- break;
- }
-
- TBNode *next_node = nullptr;
-
- // We have a "@>noderequest" string. Go ahead and do a local look up.
- if (*name_start == '>') {
- TBNode *local_root = node;
- while (local_root->getParent() != nullptr) {
- local_root = local_root->getParent();
- }
- next_node = local_root->getNode(name_start + 1, TBNode::GET_MISS_POLICY_NULL);
- }
- // We have a "@treename>noderequest" string. Go ahead and look it up from the right node tree.
- else if (TBNodeRefTree *rt = TBNodeRefTree::getRefTree(name_start, name_end - name_start)) {
- next_node = rt->m_node.getNode(name_end + 1, TBNode::GET_MISS_POLICY_NULL);
- } else {
- Log::debug("TBNodeRefTree::ResolveNode - No tree found for request \"%s\" from node \"%s\"", node_str,
- node->getValue().getString());
- break;
- }
-
- if (next_node == nullptr) {
- Log::debug("TBNodeRefTree::ResolveNode - Node not found on request \"%s\"", node_str);
- break;
- }
- node = next_node;
-
- // Detect circular reference loop.
- if (node->m_cycle_id != cycle_id) {
- node->m_cycle_id = cycle_id;
- } else {
- Log::debug("TBNodeRefTree::ResolveNode - Reference loop detected on request \"%s\" from node \"%s\"",
- node_str, node->getValue().getString());
- return start_node;
- }
- }
- return node;
-}
-
-// static
-void TBNodeRefTree::resolveConditions(TBNode *parentNode) {
- bool condition_ret = false;
- TBNode *node = parentNode->getFirstChild();
- while (node != nullptr) {
- bool delete_node = false;
- bool move_children = false;
- if (SDL_strcmp(node->getName(), "@if") == 0) {
- condition_ret = node->getValueFollowRef().getInt() != 0;
- if (condition_ret) {
- move_children = true;
- }
- delete_node = true;
- } else if (SDL_strcmp(node->getName(), "@else") == 0) {
- condition_ret = !condition_ret;
- if (condition_ret) {
- move_children = true;
- }
- delete_node = true;
- }
-
- // Make sure we'll skip any nodes added from a conditional branch.
- TBNode *node_next = node->getNext();
-
- if (move_children) {
- // Resolve the branch first, since we'll skip it.
- resolveConditions(node);
- while (TBNode *content = node->getLastChild()) {
- node->remove(content);
- parentNode->addAfter(content, node);
- }
- }
-
- if (delete_node) {
- parentNode->doDelete(node);
- } else {
- resolveConditions(node);
- }
- node = node_next;
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_node_ref_tree.h b/src/modules/ui/turbobadger/tb/tb_node_ref_tree.h
deleted file mode 100644
index bb737bd45..000000000
--- a/src/modules/ui/turbobadger/tb/tb_node_ref_tree.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_id.h"
-#include "tb_linklist.h"
-#include "tb_node_tree.h"
-
-namespace tb {
-
-class TBNode;
-class TBNodeRefTreeListener;
-
-/** TBNodeRefTree is a named TBNode.
- Nodes under this node may be referenced from other nodes, either when
- requesting a value (TBNode::getValueFollowRef), or while parsing the
- node tree. While parsing, the values can be used for branch conditions
- or branches of nodes can be included. */
-class TBNodeRefTree : public TBLinkOf {
-public:
- TBNodeRefTree(const char *name);
- virtual ~TBNodeRefTree();
-
- const char *getName() const {
- return m_name.c_str();
- }
- const TBID &getNameID() const {
- return m_name_id;
- }
-
- /** Read the data file. This will *not* invoke any change listener! */
- bool readFile(const char *filename) {
- return m_node.readFile(filename);
- }
- void readData(const char *data) {
- m_node.readData(data);
- }
-
- /** Add a listener that is invoked on changes in this tree. */
- void addListener(TBNodeRefTreeListener *listener) {
- m_listeners.addLast(listener);
- }
-
- /** Remove a change listener from this tree. */
- void removeListener(TBNodeRefTreeListener *listener) {
- m_listeners.remove(listener);
- }
-
- /** Set the value for the given request and invoke the change listener.
- Creates the nodes that doesn't exist. */
- virtual void setValue(const char *request, const TBValue &value);
-
- /** Get the value of the given request. Follows references if any.
- Returns a null value if the request doesn't exist. */
- virtual TBValue &getValue(const char *request);
-
- /** Get the value of the given tree name and request (@treename>noderequest).
- Returns a null value if the given tree or request doesn't exist. */
- static TBValue &getValueFromTree(const char *request);
-
- /** Return the tree with the given name, or nullptr if no matching tree exists. */
- static TBNodeRefTree *getRefTree(const char *name, int name_len);
-
- /** Go through the tree of nodes recursively and include
- or remove branches depending on any conditions. */
- static void resolveConditions(TBNode *parent_node);
-
-private:
- friend class TBNode;
- friend class TBNodeTarget;
- /** Follow any references to data trees and return the destination node.
- If there's broken references, the node will be returned. */
- static TBNode *followNodeRef(TBNode *node);
-
- void invokeChangeListenersInternal(const char *request);
- TBNode m_node;
- core::String m_name;
- TBID m_name_id;
- TBLinkListOf m_listeners;
- static TBLinkListOf s_ref_trees;
-};
-
-/** TBNodeRefTreeListener receive OnDataChanged when the
- value of a node in a TBNodeRefTree is changed.
- FIX: The listener can currently only listen to one tree. */
-class TBNodeRefTreeListener : public TBLinkOf {
-public:
- virtual ~TBNodeRefTreeListener() {
- }
- /** Called when the value is changed for the given node
- in the given ref tree. The request is without tree name. */
- virtual void onDataChanged(TBNodeRefTree *rt, const char *request) = 0;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_node_tree.cpp b/src/modules/ui/turbobadger/tb/tb_node_tree.cpp
deleted file mode 100644
index 7988050a6..000000000
--- a/src/modules/ui/turbobadger/tb/tb_node_tree.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_node_tree.h"
-#include "core/Assert.h"
-#include "core/StringUtil.h"
-#include "tb_language.h"
-#include "tb_node_ref_tree.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-
-namespace tb {
-
-TBNode::~TBNode() {
- clear();
-}
-
-// static
-TBNode *TBNode::create(const char *name) {
- TBNode *n = new TBNode;
- if ((n == nullptr) || ((n->m_name = SDL_strdup(name)) == nullptr)) {
- delete n;
- return nullptr;
- }
- return n;
-}
-
-// static
-TBNode *TBNode::create(const char *name, int nameLen) {
- TBNode *n = new TBNode;
- if ((n == nullptr) || ((n->m_name = (char *)SDL_malloc(nameLen + 1)) == nullptr)) {
- delete n;
- return nullptr;
- }
- SDL_memcpy(n->m_name, name, nameLen);
- n->m_name[nameLen] = 0;
- return n;
-}
-
-// static
-const char *TBNode::getNextNodeSeparator(const char *request) {
- while (*request != 0 && *request != '>') {
- request++;
- }
- return request;
-}
-
-TBNode *TBNode::getNode(const char *request, GET_MISS_POLICY mp) {
- // Iterate one node deeper for each sub request (non recursive)
- TBNode *n = this;
- while ((*request != 0) && (n != nullptr)) {
- const char *nextend = getNextNodeSeparator(request);
- int name_len = nextend - request;
- TBNode *n_child = n->getNodeInternal(request, name_len);
- if ((n_child == nullptr) && mp == GET_MISS_POLICY_CREATE) {
- n_child = n->create(request, name_len);
- if (n_child != nullptr) {
- n->add(n_child);
- }
- }
- n = n_child;
- request = *nextend == 0 ? nextend : nextend + 1;
- }
- return n;
-}
-
-TBNode *TBNode::getNodeFollowRef(const char *request, GET_MISS_POLICY mp) {
- TBNode *node = getNode(request, mp);
- if (node != nullptr) {
- node = TBNodeRefTree::followNodeRef(node);
- }
- return node;
-}
-
-TBNode *TBNode::getNodeInternal(const char *name, int nameLen) const {
- for (TBNode *n = getFirstChild(); n != nullptr; n = n->getNext()) {
- if (SDL_strncmp(n->m_name, name, nameLen) == 0 && n->m_name[nameLen] == 0) {
- return n;
- }
- }
- return nullptr;
-}
-
-bool TBNode::cloneChildren(TBNode *source, bool followRefs) {
- TBNode *item = source->getFirstChild();
- while (item != nullptr) {
- TBNode *new_child = create(item->m_name);
- if (new_child == nullptr) {
- return false;
- }
-
- new_child->m_value.copy(followRefs ? item->getValueFollowRef() : item->m_value);
- add(new_child);
-
- if (!new_child->cloneChildren(item, followRefs)) {
- return false;
- }
- item = item->getNext();
- }
- return true;
-}
-
-TBValue &TBNode::getValueFollowRef() {
- return TBNodeRefTree::followNodeRef(this)->getValue();
-}
-
-int TBNode::getValueInt(const char *request, int def) {
- TBNode *n = getNodeFollowRef(request);
- return n != nullptr ? n->m_value.getInt() : def;
-}
-
-float TBNode::getValueFloat(const char *request, float def) {
- TBNode *n = getNodeFollowRef(request);
- return n != nullptr ? n->m_value.getFloat() : def;
-}
-
-const char *TBNode::getValueString(const char *request, const char *def) {
- if (TBNode *node = getNodeFollowRef(request)) {
- // We might have a language string. Those are not
- // looked up in GetNode/ResolveNode.
- if (node->getValue().isString()) {
- const char *string = node->getValue().getString();
- if (*string == '@' && *TBNode::getNextNodeSeparator(string) == 0) {
- string = g_tb_lng->getString(string + 1);
- }
- return string;
- }
- return node->getValue().getString();
- }
- return def;
-}
-
-const char *TBNode::getValueStringRaw(const char *request, const char *def) {
- TBNode *n = getNodeFollowRef(request);
- return n != nullptr ? n->m_value.getString() : def;
-}
-
-class FileParser : public TBParserStream {
-public:
- bool read(const char *filename, TBParserTarget *target) {
- f = TBFile::open(filename, TBFile::MODE_READ);
- if (f == nullptr) {
- return false;
- }
- TBParser p;
- TBParser::STATUS status = p.read(this, target);
- delete f;
- return status == TBParser::STATUS_OK;
- }
- virtual int getMoreData(char *buf, int bufLen) {
- return f->read(buf, 1, bufLen);
- }
-
-private:
- TBFile *f;
-};
-
-class DataParser : public TBParserStream {
-public:
- bool read(const char *data, int dataLen, TBParserTarget *target) {
- m_data = data;
- m_data_len = dataLen;
- TBParser p;
- TBParser::STATUS status = p.read(this, target);
- return status == TBParser::STATUS_OK;
- }
- virtual int getMoreData(char *buf, int bufLen) {
- const int consume = Min(bufLen, m_data_len);
- SDL_memcpy(buf, m_data, consume);
- m_data += consume;
- m_data_len -= consume;
- return consume;
- }
-
-private:
- const char *m_data;
- int m_data_len;
-};
-
-class TBNodeTarget : public TBParserTarget {
-public:
- TBNodeTarget(TBNode *root, const char *filename) {
- m_root_node = m_target_node = root;
- m_filename = filename;
- }
- virtual void onError(int lineNr, const char *error) {
-#ifdef TB_RUNTIME_DEBUG_INFO
- Log::debug("%s(%d):Parse error: %s", m_filename, lineNr, error);
-#endif // TB_RUNTIME_DEBUG_INFO
- }
- virtual void onComment(int lineNr, const char *comment) {
- }
- virtual void onToken(int lineNr, const char *name, TBValue &value) {
- if (m_target_node == nullptr) {
- return;
- }
- if (SDL_strcmp(name, "@file") == 0) {
- includeFile(lineNr, value.getString());
- } else if (SDL_strcmp(name, "@include") == 0) {
- includeRef(lineNr, value.getString());
- } else if (TBNode *n = TBNode::create(name)) {
- n->m_value.takeOver(value);
- m_target_node->add(n);
- }
- }
- virtual void enter() {
- if (m_target_node != nullptr) {
- m_target_node = m_target_node->getLastChild();
- }
- }
- virtual void leave() {
- core_assert(m_target_node != m_root_node);
- if (m_target_node != nullptr) {
- m_target_node = m_target_node->m_parent;
- }
- }
- void includeFile(int lineNr, const char *filename) {
- // Read the included file into a new TBNode and then
- // move all the children to m_target_node.
- TBTempBuffer include_filename;
- include_filename.appendPath(m_filename);
- include_filename.appendString(filename);
- TBNode content;
- if (content.readFile(include_filename.getData())) {
- while (TBNode *content_n = content.getFirstChild()) {
- content.remove(content_n);
- m_target_node->add(content_n);
- }
- } else {
- const core::String& err = core::string::format("Referenced file \"%s\" was not found!", include_filename.getData());
- onError(lineNr, err.c_str());
- }
- }
- void includeRef(int lineNr, const char *refstr) {
- TBNode *refnode = nullptr;
- if (*refstr == '@') {
- TBNode tmp;
- tmp.getValue().setString(refstr, TBValue::SET_AS_STATIC);
- refnode = TBNodeRefTree::followNodeRef(&tmp);
- } else // Local look-up
- {
- // Note: If we read to a target node that already contains
- // nodes, we might look up nodes that's already there
- // instead of new nodes.
- refnode = m_root_node->getNode(refstr, TBNode::GET_MISS_POLICY_NULL);
-
- // Detect cycles
- TBNode *cycle_detection = m_target_node;
- while ((cycle_detection != nullptr) && (refnode != nullptr)) {
- if (cycle_detection == refnode) {
- refnode = nullptr; // We have a cycle, so just fail the inclusion.
- }
- cycle_detection = cycle_detection->getParent();
- }
- }
- if (refnode != nullptr) {
- m_target_node->cloneChildren(refnode);
- } else {
- const core::String& err = core::string::format("Include \"%s\" was not found!", refstr);
- onError(lineNr, err.c_str());
- }
- }
-
-private:
- TBNode *m_root_node;
- TBNode *m_target_node;
- const char *m_filename;
-};
-
-bool TBNode::readFile(const char *filename, TB_NODE_READ_FLAGS flags) {
- if ((flags & TB_NODE_READ_FLAGS_APPEND) == 0U) {
- clear();
- }
- FileParser p;
- TBNodeTarget t(this, filename);
- if (p.read(filename, &t)) {
- TBNodeRefTree::resolveConditions(this);
- return true;
- }
- return false;
-}
-
-bool TBNode::readData(const char *data, TB_NODE_READ_FLAGS flags) {
- return readData(data, SDL_strlen(data), flags);
-}
-
-bool TBNode::readData(const char *data, int dataLen, TB_NODE_READ_FLAGS flags) {
- if ((flags & TB_NODE_READ_FLAGS_APPEND) == 0U) {
- clear();
- }
- DataParser p;
- TBNodeTarget t(this, "{data}");
- if (!p.read(data, dataLen, &t)) {
- return false;
- }
- TBNodeRefTree::resolveConditions(this);
- return true;
-}
-
-void TBNode::clear() {
- SDL_free(m_name);
- m_name = nullptr;
- m_children.deleteAll();
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_node_tree.h b/src/modules/ui/turbobadger/tb/tb_node_tree.h
deleted file mode 100644
index 31df61052..000000000
--- a/src/modules/ui/turbobadger/tb/tb_node_tree.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "core/Enum.h"
-#include "parser/tb_parser.h"
-#include "tb_linklist.h"
-
-namespace tb {
-
-enum TB_NODE_READ_FLAGS {
- TB_NODE_READ_FLAGS_NONE = 0,
- /** Read nodes without clearing first. Can be used to append
- data from multiple sources, or inject dependencies. */
- TB_NODE_READ_FLAGS_APPEND = 1,
-};
-CORE_ENUM_BIT_OPERATIONS(TB_NODE_READ_FLAGS);
-
-/** TBNode is a tree node with a string name and a value (TBValue).
- It may have a parent TBNode and child TBNodes.
-
- Getting the value of this node or any child, may optionally follow
- references to nodes in any existing TBNodeRefTree (by name).
-
- During ReadFile/ReadData, it may also select which branches to include
- or exclude conditionally by lookup up values in TBNodeRefTree. */
-class TBNode : public TBLinkOf {
-public:
- TBNode() : m_name(nullptr), m_parent(nullptr), m_cycle_id(0) {
- }
- ~TBNode();
-
- /** Create a new node with the given name. */
- static TBNode *create(const char *name);
-
- /** Read a tree of nodes from file into this node. Returns true on success. */
- bool readFile(const char *filename, TB_NODE_READ_FLAGS flags = TB_NODE_READ_FLAGS_NONE);
-
- /** Read a tree of nodes from a null terminated string buffer. */
- bool readData(const char *data, TB_NODE_READ_FLAGS flags = TB_NODE_READ_FLAGS_NONE);
-
- /** Read a tree of nodes from a buffer with a known length. */
- bool readData(const char *data, int data_len, TB_NODE_READ_FLAGS flags = TB_NODE_READ_FLAGS_NONE);
-
- /** Clear the contens of this node. */
- void clear();
-
- /** Add node as child to this node. */
- void add(TBNode *n) {
- m_children.addLast(n);
- n->m_parent = this;
- }
-
- /** Add node before the reference node (which must be a child to this node). */
- void addBefore(TBNode *n, TBNode *reference) {
- m_children.addBefore(n, reference);
- n->m_parent = this;
- }
-
- /** Add node after the reference node (which must be a child to this node). */
- void addAfter(TBNode *n, TBNode *reference) {
- m_children.addAfter(n, reference);
- n->m_parent = this;
- }
-
- /** Remove child node n from this node. */
- void remove(TBNode *n) {
- m_children.remove(n);
- n->m_parent = nullptr;
- }
-
- /** Remove and delete child node n from this node. */
- void doDelete(TBNode *n) {
- m_children.doDelete(n);
- }
-
- /** Create duplicates of all items in source and add them to this node.
- If follow_refs is true, any references will be followed and the final target
- will be cloned instead of the ref node.
- Note: Nodes does not replace existing nodes with the same name. Cloned nodes
- are added after any existing nodes. */
- bool cloneChildren(TBNode *source, bool follow_refs = false);
-
- enum GET_MISS_POLICY {
- /** GetNode will return nullptr if the node doesn't exist. */
- GET_MISS_POLICY_NULL,
- /** GetNode will create all missing nodes for the request. */
- GET_MISS_POLICY_CREATE
- };
-
- /** Get a node from the given request.
- If the node doesn't exist, it will either return nullptr or create
- missing nodes, depending on the miss policy.
- It can find nodes in children as well. Names are separated by a ">".
-
- Ex: GetNode("dishes>pizza>special>batman") */
- TBNode *getNode(const char *request, GET_MISS_POLICY mp = GET_MISS_POLICY_NULL);
-
- /** Returns the name of this node. */
- const char *getName() const {
- return m_name;
- }
-
- /** Returns the value of this node. */
- TBValue &getValue() {
- return m_value;
- }
-
- /** Returns the value of this node.
- Will follow eventual references to TBNodeRefTree. */
- TBValue &getValueFollowRef();
-
- /** Get a value from the given request as an integer.
- Will follow eventual references to TBNodeRefTree.
- If the value is not specified, it returns the default value (def). */
- int getValueInt(const char *request, int def);
-
- /** Get a value from the given request as an float.
- Will follow eventual references to TBNodeRefTree.
- If the value is not specified, it returns the default value (def). */
- float getValueFloat(const char *request, float def);
-
- /** Get a value from the given request as an string.
- Will follow eventual references to TBNodeRefTree.
- Will also return any referenced language string.
- If the value is not specified, it returns the default value (def). */
- const char *getValueString(const char *request, const char *def);
-
- /** Same as getValueString, but won't look up language string references. */
- const char *getValueStringRaw(const char *request, const char *def);
-
- /** Get the next position in request that is a sub node separator,
- or the end of the string. */
- static const char *getNextNodeSeparator(const char *request);
-
- inline TBNode *getParent() const {
- return m_parent;
- }
- inline TBNode *getFirstChild() const {
- return m_children.getFirst();
- }
- inline TBNode *getLastChild() const {
- return m_children.getLast();
- }
-
-private:
- friend class TBNodeTarget;
- friend class TBNodeRefTree;
- TBNode *getNodeFollowRef(const char *request, GET_MISS_POLICY mp = GET_MISS_POLICY_NULL);
- TBNode *getNodeInternal(const char *name, int name_len) const;
- static TBNode *create(const char *name, int name_len);
- char *m_name;
- TBValue m_value;
- TBLinkListOf m_children;
- TBNode *m_parent;
- uint32_t m_cycle_id; ///< Used to detect circular references.
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_object.h b/src/modules/ui/turbobadger/tb/tb_object.h
deleted file mode 100644
index c8063c678..000000000
--- a/src/modules/ui/turbobadger/tb/tb_object.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-#include "tb_linklist.h"
-
-namespace tb {
-
-typedef void *TB_TYPE_ID;
-
-/* TBTypedObject implements custom RTTI so we can get type safe casts,
- and the class name at runtime.
-
- Each subclass is expected to define TBOBJECT_SUBCLASS to get the
- necessary implementations, instead of implementing those manually. */
-class TBTypedObject {
-public:
- virtual ~TBTypedObject() {
- }
-
- /** A static template method that returns a unique id for each type. */
- template static TB_TYPE_ID getTypeId() {
- static char type_id;
- return &type_id;
- }
-
- /** Returns true if the class or the base class matches the type id */
- virtual bool isOfTypeId(const TB_TYPE_ID typeId) const {
- return typeId == getTypeId();
- }
-
- /** Returns this object as the given type or nullptr if it's not that type. */
- template T *safeCastTo() const {
- return (T *)(isOfTypeId(getTypeId()) ? this : nullptr);
- }
-
- /** Return true if this object can safely be casted to the given type. */
- template bool isOfType() const {
- return static_cast(safeCastTo());
- }
-
- /** Get the classname of the object. */
- virtual const char *getClassName() const {
- return "TBTypedObject";
- }
-};
-
-/** Returns the given object as the given type, or nullptr if it's not that type
- or if the object is nullptr. */
-template T *TBSafeCast(TBTypedObject *obj) {
- return obj ? obj->safeCastTo() : nullptr;
-}
-
-/** Returns the given object as the given type, or nullptr if it's not that type
- or if the object is nullptr. */
-template const T *TBSafeCast(const TBTypedObject *obj) {
- return obj ? obj->safeCastTo() : nullptr;
-}
-
-/** Implement the methods for safe typecasting without requiring RTTI. */
-#define TBOBJECT_SUBCLASS(clazz, baseclazz) \
- private: using Super = baseclazz; public: \
- virtual const char *getClassName() const override { \
- return #clazz; \
- } \
- virtual bool isOfTypeId(const tb::TB_TYPE_ID type_id) const override { \
- return getTypeId() == type_id ? true : baseclazz::isOfTypeId(type_id); \
- }
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_popup_window.cpp b/src/modules/ui/turbobadger/tb/tb_popup_window.cpp
deleted file mode 100644
index fdd1c20d7..000000000
--- a/src/modules/ui/turbobadger/tb/tb_popup_window.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_popup_window.h"
-#include "tb_widgets_listener.h"
-
-namespace tb {
-
-TBRect TBPopupAlignment::getAlignedRect(TBWidget *popup, TBWidget *target) const {
- TBWidget *root = target->getParentRoot();
-
- SizeConstraints sc(root->getRect().w, root->getRect().h);
-
- PreferredSize ps = popup->getPreferredSize(sc);
-
- // Amount of pixels that should be avoided if the target rect needs to be moved.
- int avoid_w = 0;
- int avoid_h = 0;
-
- int x = 0;
- int y = 0;
- int w = Min(ps.pref_w, root->getRect().w);
- int h = Min(ps.pref_h, root->getRect().h);
-
- if (pos_in_root.x != UNSPECIFIED && pos_in_root.y != UNSPECIFIED) {
- // Position is specified in absolute root coords
- x = pos_in_root.x;
- y = pos_in_root.y;
- avoid_w = pos_offset.x;
- avoid_h = pos_offset.y;
- // Make sure it's moved into view horizontally
- if (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM) {
- x = Clamp(x, 0, root->getRect().w - w);
- }
- } else {
- target->convertToRoot(x, y);
-
- if (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM) {
- if (expand_to_target_width) {
- w = Max(w, target->getRect().w);
- }
-
- // If the menu is aligned top or bottom, limit its height to the worst case available height.
- // Being in the center of the root, that is half the root height minus the target rect.
- h = Min(h, root->getRect().h / 2 - target->getRect().h);
- }
- avoid_w = target->getRect().w;
- avoid_h = target->getRect().h;
- }
-
- if (align == TB_ALIGN_BOTTOM) {
- y = y + avoid_h + h > root->getRect().h ? y - h : y + avoid_h;
- } else if (align == TB_ALIGN_TOP) {
- y = y - h < 0 ? y + avoid_h : y - h;
- } else if (align == TB_ALIGN_RIGHT) {
- x = x + avoid_w + w > root->getRect().w ? x - w : x + avoid_w;
- y = Min(y, root->getRect().h - h);
- } else // if (align == TB_ALIGN_LEFT)
- {
- x = x - w < 0 ? x + avoid_w : x - w;
- y = Min(y, root->getRect().h - h);
- }
- return TBRect(x, y, w, h);
-}
-
-TBPopupWindow::TBPopupWindow(TBWidget *target) : m_target(target) {
- TBWidgetListener::addGlobalListener(this);
-
- invokePointerCancel();
- setSkinBg(TBIDC("TBPopupWindow"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- setSettings(WINDOW_SETTINGS_NONE);
-}
-
-TBPopupWindow::~TBPopupWindow() {
- TBWidgetListener::removeGlobalListener(this);
-}
-
-bool TBPopupWindow::show(const TBPopupAlignment &alignment) {
- // Calculate and set a good size for the popup window
- setRect(alignment.getAlignedRect(this, m_target.get()));
-
- TBWidget *root = m_target.get()->getParentRoot();
- root->addChild(this);
- return true;
-}
-
-bool TBPopupWindow::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_KEY_DOWN && ev.special_key == TB_KEY_ESC) {
- close();
- return true;
- }
- return TBWindow::onEvent(ev);
-}
-
-void TBPopupWindow::onWidgetFocusChanged(TBWidget *widget, bool focused) {
- if (focused && !isEventDestinationFor(widget)) {
- close();
- }
-}
-
-bool TBPopupWindow::onWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) {
- if ((ev.type == EVENT_TYPE_POINTER_DOWN || ev.type == EVENT_TYPE_CONTEXT_MENU) &&
- !isEventDestinationFor(ev.target)) {
- close();
- }
- return false;
-}
-
-void TBPopupWindow::onWidgetDelete(TBWidget *widget) {
- // If the target widget is deleted, close!
- if (m_target.get() == nullptr) {
- close();
- }
-}
-
-bool TBPopupWindow::onWidgetDying(TBWidget *widget) {
- // If the target widget or an ancestor of it is dying, close!
- if (widget == m_target.get() || widget->isAncestorOf(m_target.get())) {
- close();
- }
- return false;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_popup_window.h b/src/modules/ui/turbobadger/tb/tb_popup_window.h
deleted file mode 100644
index 73a11bed3..000000000
--- a/src/modules/ui/turbobadger/tb/tb_popup_window.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_widgets_listener.h"
-#include "tb_window.h"
-
-namespace tb {
-
-/** TBPopupAlignment describes the preferred alignment of a popup
- relative to a target widget or a given point.
-
- It calculates the rect to be used to match these preferences
- for any given popup and target. */
-class TBPopupAlignment {
-public:
- static const int UNSPECIFIED = TB_INVALID_DIMENSION;
-
- /** Align relative to the target widget. */
- TBPopupAlignment(TB_ALIGN align = TB_ALIGN_BOTTOM)
- : pos_in_root(UNSPECIFIED, UNSPECIFIED), align(align), expand_to_target_width(true) {
- }
-
- /** Align relative to the given position (coordinates relative to the root widget). */
- TBPopupAlignment(const TBPoint &posInRoot, TB_ALIGN align = TB_ALIGN_BOTTOM)
- : pos_in_root(posInRoot), align(align), expand_to_target_width(true) {
- }
-
- /** Align relative to the given position (coordinates relative to the root widget).
- Applies an additional offset. */
- TBPopupAlignment(const TBPoint &posInRoot, const TBPoint &posOffset)
- : pos_in_root(posInRoot), pos_offset(posOffset), align(TB_ALIGN_BOTTOM), expand_to_target_width(true) {
- }
-
- /** Calculate a good rect for the given popup window using its preferred size and
- the preferred alignment information stored in this class. */
- TBRect getAlignedRect(TBWidget *popup, TBWidget *target) const;
-
- TBPoint pos_in_root;
- TBPoint pos_offset;
-
- TB_ALIGN align;
- /** If true, the width of the popup will be at least the same as the target widget
- if the alignment is TB_ALIGN_TOP or TB_ALIGN_BOTTOM. */
- bool expand_to_target_width;
-};
-
-/** TBPopupWindow is a popup window that redirects any child widgets events
- through the given target. It will automatically close on click events that
- are not sent through this popup. */
-
-class TBPopupWindow : public TBWindow, private TBWidgetListener {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBPopupWindow, TBWindow);
-
- TBPopupWindow(TBWidget *target);
- ~TBPopupWindow();
-
- bool show(const TBPopupAlignment &alignment);
-
- virtual TBWidget *getEventDestination() const override {
- return m_target.get();
- }
-
- virtual bool onEvent(const TBWidgetEvent &ev) override;
-
-private:
- TBWidgetSafePointer m_target;
- // TBWidgetListener
- virtual void onWidgetFocusChanged(TBWidget *widget, bool focused) override;
- virtual bool onWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) override;
- virtual void onWidgetDelete(TBWidget *widget) override;
- virtual bool onWidgetDying(TBWidget *widget) override;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_renderer.cpp b/src/modules/ui/turbobadger/tb/tb_renderer.cpp
deleted file mode 100644
index cb15e0206..000000000
--- a/src/modules/ui/turbobadger/tb/tb_renderer.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_renderer.h"
-
-namespace tb {
-
-void TBRenderer::invokeContextLost() {
- TBLinkListOf::Iterator iter = m_listeners.iterateForward();
- while (TBRendererListener *listener = iter.getAndStep()) {
- listener->onContextLost();
- }
-}
-
-void TBRenderer::invokeContextRestored() {
- TBLinkListOf::Iterator iter = m_listeners.iterateForward();
- while (TBRendererListener *listener = iter.getAndStep()) {
- listener->onContextRestored();
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_renderer.h b/src/modules/ui/turbobadger/tb/tb_renderer.h
deleted file mode 100644
index b0800ba2e..000000000
--- a/src/modules/ui/turbobadger/tb/tb_renderer.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_color.h"
-#include "tb_core.h"
-#include "tb_geometry.h"
-#include "tb_linklist.h"
-#include "video/Camera.h"
-
-namespace tb {
-
-class TBBitmapFragment;
-
-/** TBRendererListener is a listener for TBRenderer. */
-class TBRendererListener : public TBLinkOf {
-public:
- virtual ~TBRendererListener() {
- }
-
- /** Called when the context has been lost and all TBBitmaps need to be deleted.
- NOTE: Only do cleanup here. It's not safe to do work on any bitmap since the
- context is already lost. */
- virtual void onContextLost() = 0;
-
- /** Called when the context has been restored again, and new TBBitmaps can be created
- again. */
- virtual void onContextRestored() = 0;
-};
-
-/** TBBitmap is a minimal interface for bitmap to be painted by TBRenderer. */
-
-class TBBitmap {
-public:
- /** Note: Implementations for batched renderers should call TBRenderer::FlushBitmap
- to make sure any active batch is being flushed before the bitmap is deleted. */
- virtual ~TBBitmap() {
- }
-
- virtual int width() = 0;
- virtual int height() = 0;
-
- /** Update the bitmap with the given data (in BGRA32 format).
- Note: Implementations for batched renderers should call TBRenderer::FlushBitmap
- to make sure any active batch is being flushed before the bitmap is changed. */
- virtual void setData(uint32_t *data) = 0;
-};
-
-/** TBRenderer is a minimal interface for painting strings and bitmaps. */
-
-class TBRenderer {
-protected:
- video::Camera _camera;
-public:
- TBRenderer() : _camera(video::CameraType::FirstPerson, video::CameraMode::Orthogonal) {}
-
- virtual ~TBRenderer() {
- }
-
- /** Should be called before invoking paint on any widget.
- render_target_w and render_target_h should be the size of the render target
- that the renderer renders to. I.e window size, screen size or frame buffer object. */
- virtual void beginPaint(int renderTargetW, int renderTargetH) = 0;
- virtual void endPaint() = 0;
-
- /** Translate all drawing with the given offset */
- virtual void translate(int dx, int dy) = 0;
-
- /** Set the current opacity that should apply to all drawing (0.f-1.f). */
- virtual void setOpacity(float opacity) = 0;
- virtual float getOpacity() = 0;
-
- /** Set a clip rect to the renderer. add_to_current should be true when
- pushing a new cliprect that should clip inside the last clip rect,
- and false when restoring.
- It will return the clip rect that was in use before this call. */
- virtual TBRect setClipRect(const TBRect &rect, bool addToCurrent) = 0;
-
- /** Get the current clip rect. Note: This may be different from the rect
- sent to SetClipRect, due to intersecting with the previous cliprect! */
- virtual TBRect getClipRect() = 0;
-
- /** Draw the src_rect part of the fragment stretched to dst_rect.
- dst_rect or src_rect can have negative width and height to achieve horizontal and vertical flip. */
- virtual void drawBitmap(const TBRect &dstRect, const TBRect &srcRect, TBBitmapFragment *bitmapFragment) = 0;
-
- /** Draw the src_rect part of the bitmap stretched to dst_rect.
- dst_rect or src_rect can have negative width and height to achieve horizontal and vertical flip. */
- virtual void drawBitmap(const TBRect &dstRect, const TBRect &srcRect, TBBitmap *bitmap) = 0;
-
- /** Draw the src_rect part of the fragment stretched to dst_rect.
- The bitmap will be used as a mask for the color.
- dst_rect or src_rect can have negative width and height to achieve horizontal and vertical flip. */
- virtual void drawBitmapColored(const TBRect &dstRect, const TBRect &srcRect, const TBColor &color,
- TBBitmapFragment *bitmapFragment) = 0;
-
- /** Draw the src_rect part of the bitmap stretched to dst_rect.
- The bitmap will be used as a mask for the color.
- dst_rect or src_rect can have negative width and height to achieve horizontal and vertical flip. */
- virtual void drawBitmapColored(const TBRect &dstRect, const TBRect &srcRect, const TBColor &color,
- TBBitmap *bitmap) = 0;
-
- /** Draw the bitmap tiled into dst_rect. */
- virtual void drawBitmapTile(const TBRect &dstRect, TBBitmap *bitmap) = 0;
-
- /** Make sure the given bitmap fragment is flushed from any batching, because it may
- be changed or deleted after this call. */
- virtual void flushBitmapFragment(TBBitmapFragment *bitmapFragment) = 0;
-
- /** Create a new TBBitmap from the given data (in BGRA32 format).
- Width and height must be a power of two.
- Return nullptr if fail. */
- virtual TBBitmap *createBitmap(int width, int height, uint32_t *data) = 0;
-
- /** Add a listener to this renderer. Does not take ownership. */
- void addListener(TBRendererListener *listener) {
- m_listeners.addLast(listener);
- }
-
- /** Remove a listener from this renderer. */
- void removeListener(TBRendererListener *listener) {
- m_listeners.remove(listener);
- }
-
- /** Invoke OnContextLost on all listeners.
- Call when bitmaps should be forgotten. */
- void invokeContextLost();
-
- /** Invoke OnContextRestored on all listeners.
- Call when bitmaps can safely be restored. */
- void invokeContextRestored();
-
- /** Defines the hint given to BeginBatchHint. */
- enum BATCH_HINT {
- /** All calls are either DrawBitmap or DrawBitmapColored with the same bitmap
- fragment. */
- BATCH_HINT_DRAW_BITMAP_FRAGMENT
- };
-
- const video::Camera& camera() const {
- return _camera;
- }
-
- /** A hint to batching renderers that the following set of draw calls are of the
- same type so batching might be optimized.
- The hint defines what operations are allowed between BeginBatchHint
- until EndBatchHint is called. All other draw operations are invalid.
- It's not valid to nest calls to BeginBatchHint. */
- virtual void beginBatchHint(BATCH_HINT hint) {
- }
-
- /** End the hint scope started with BeginBatchHint. */
- virtual void endBatchHint() {
- }
-
- virtual void flush() {
- }
-
-private:
- TBLinkListOf m_listeners;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_scroll_container.cpp b/src/modules/ui/turbobadger/tb/tb_scroll_container.cpp
deleted file mode 100644
index a985d5bab..000000000
--- a/src/modules/ui/turbobadger/tb/tb_scroll_container.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_scroll_container.h"
-#include "core/Assert.h"
-#include "tb_system.h"
-
-namespace tb {
-
-TBScrollBarVisibility TBScrollBarVisibility::solve(SCROLL_MODE mode, int contentW, int contentH, int availableW,
- int availableH, int scrollbarXH, int scrollbarYW) {
- TBScrollBarVisibility visibility;
- visibility.visible_w = availableW;
- visibility.visible_h = availableH;
-
- if (mode == SCROLL_MODE_X_Y) {
- visibility.y_on = true;
- visibility.x_on = true;
- visibility.visible_w -= scrollbarYW;
- visibility.visible_h -= scrollbarXH;
- } else if (mode == SCROLL_MODE_OFF) {
- } else if (mode == SCROLL_MODE_Y) {
- visibility.y_on = true;
- visibility.visible_w -= scrollbarYW;
- } else if (mode == SCROLL_MODE_Y_AUTO) {
- if (contentH > availableH) {
- visibility.y_on = true;
- visibility.visible_w -= scrollbarYW;
- }
- } else if (mode == SCROLL_MODE_X_AUTO_Y_AUTO) {
- if (contentW > visibility.visible_w) {
- visibility.x_on = true;
- visibility.visible_h = availableH - scrollbarXH;
- }
- if (contentH > visibility.visible_h) {
- visibility.y_on = true;
- visibility.visible_w = availableW - scrollbarYW;
- }
- if (contentW > visibility.visible_w) {
- visibility.x_on = true;
- visibility.visible_h = availableH - scrollbarXH;
- }
- }
- return visibility;
-}
-
-void TBScrollContainerRoot::onPaintChildren(const PaintProps &paintProps) {
- // We only want clipping in one axis (the overflowing one) so we
- // don't damage any expanded skins on the other axis. Add some fluff.
- const int fluff = 100;
- TBScrollContainer *sc = static_cast(getParent());
- TBRect clip_rect = getPaddingRect().expand(
- sc->m_scrollbar_x.canScrollNegative() ? 0 : fluff, sc->m_scrollbar_y.canScrollNegative() ? 0 : fluff,
- sc->m_scrollbar_x.canScrollPositive() ? 0 : fluff, sc->m_scrollbar_y.canScrollPositive() ? 0 : fluff);
-
- TBRect old_clip_rect = g_renderer->setClipRect(clip_rect, true);
-
- TB_IF_DEBUG_SETTING(LAYOUT_CLIPPING, g_tb_skin->paintRect(clip_rect, TBColor(255, 0, 0, 200), 1));
-
- TBWidget::onPaintChildren(paintProps);
-
- g_renderer->setClipRect(old_clip_rect, false);
-}
-
-void TBScrollContainerRoot::getChildTranslation(int &x, int &y) const {
- TBScrollContainer *sc = static_cast(getParent());
- x = (int)-sc->m_scrollbar_x.getValue();
- y = (int)-sc->m_scrollbar_y.getValue();
-}
-
-TBScrollContainer::TBScrollContainer() {
- addChild(&m_scrollbar_x);
- addChild(&m_scrollbar_y);
- addChild(&m_root);
- m_scrollbar_y.setAxis(AXIS_Y);
-}
-
-TBScrollContainer::~TBScrollContainer() {
- removeChild(&m_root);
- removeChild(&m_scrollbar_y);
- removeChild(&m_scrollbar_x);
-}
-
-void TBScrollContainer::setAdaptToContentSize(bool adapt) {
- if (m_adapt_to_content_size == adapt) {
- return;
- }
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
- m_adapt_to_content_size = adapt;
- invalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
-}
-
-void TBScrollContainer::setAdaptContentSize(bool adapt) {
- if (m_adapt_content_size == adapt) {
- return;
- }
- m_adapt_content_size = adapt;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBScrollContainer::setScrollMode(SCROLL_MODE mode) {
- if (mode == m_mode) {
- return;
- }
- m_mode = mode;
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
-}
-
-void TBScrollContainer::scrollTo(int x, int y) {
- int old_x = m_scrollbar_x.getValue();
- int old_y = m_scrollbar_y.getValue();
- m_scrollbar_x.setValue(x);
- m_scrollbar_y.setValue(y);
- if (old_x != m_scrollbar_x.getValue() || old_y != m_scrollbar_y.getValue()) {
- invalidate();
- }
-}
-
-TBWidget::ScrollInfo TBScrollContainer::getScrollInfo() {
- ScrollInfo info;
- info.min_x = static_cast(m_scrollbar_x.getMinValue());
- info.min_y = static_cast(m_scrollbar_y.getMinValue());
- info.max_x = static_cast(m_scrollbar_x.getMaxValue());
- info.max_y = static_cast(m_scrollbar_y.getMaxValue());
- info.x = m_scrollbar_x.getValue();
- info.y = m_scrollbar_y.getValue();
- return info;
-}
-
-void TBScrollContainer::invalidateLayout(INVALIDATE_LAYOUT il) {
- m_layout_is_invalid = true;
- // No recursion up to parents here unless we adapt to content size.
- if (m_adapt_to_content_size) {
- TBWidget::invalidateLayout(il);
- }
-}
-
-TBRect TBScrollContainer::getPaddingRect() {
- int visible_w = getRect().w;
- int visible_h = getRect().h;
- if (m_scrollbar_x.getOpacity() != 0.0F) {
- visible_h -= m_scrollbar_x.getPreferredSize().pref_h;
- }
- if (m_scrollbar_y.getOpacity() != 0.0F) {
- visible_w -= m_scrollbar_y.getPreferredSize().pref_w;
- }
- return TBRect(0, 0, visible_w, visible_h);
-}
-
-PreferredSize TBScrollContainer::onCalculatePreferredContentSize(const SizeConstraints &constraints) {
- PreferredSize ps;
- ps.pref_w = ps.pref_h = 100;
- ps.min_w = ps.min_h = 50;
- if (m_adapt_to_content_size) {
- if (TBWidget *content_child = m_root.getFirstChild()) {
- ps = content_child->getPreferredSize(constraints);
- int scrollbar_y_w = m_scrollbar_y.getPreferredSize().pref_w;
- int scrollbar_x_h = m_scrollbar_x.getPreferredSize().pref_h;
-
- ps.pref_w += scrollbar_y_w;
- ps.max_w += scrollbar_y_w;
-
- if (m_mode == SCROLL_MODE_X_Y || m_mode == SCROLL_MODE_X_AUTO_Y_AUTO) {
- ps.pref_h += scrollbar_x_h;
- ps.max_h += scrollbar_x_h;
- }
- }
- }
- return ps;
-}
-
-bool TBScrollContainer::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_CHANGED && (ev.target == &m_scrollbar_x || ev.target == &m_scrollbar_y)) {
- invalidate();
- onScroll(m_scrollbar_x.getValue(), m_scrollbar_y.getValue());
- return true;
- }
- if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE) {
- double old_val_y = m_scrollbar_y.getValueDouble();
- m_scrollbar_y.setValueDouble(old_val_y + ev.delta_y * TBSystem::getPixelsPerLine());
- double old_val_x = m_scrollbar_x.getValueDouble();
- m_scrollbar_x.setValueDouble(old_val_x + ev.delta_x * TBSystem::getPixelsPerLine());
- return (m_scrollbar_x.getValueDouble() != old_val_x || m_scrollbar_y.getValueDouble() != old_val_y);
- }
- if (ev.type == EVENT_TYPE_KEY_DOWN) {
- if (ev.special_key == TB_KEY_LEFT && m_scrollbar_x.canScrollNegative()) {
- scrollBySmooth(-TBSystem::getPixelsPerLine(), 0);
- } else if (ev.special_key == TB_KEY_RIGHT && m_scrollbar_x.canScrollPositive()) {
- scrollBySmooth(TBSystem::getPixelsPerLine(), 0);
- } else if (ev.special_key == TB_KEY_UP && m_scrollbar_y.canScrollNegative()) {
- scrollBySmooth(0, -TBSystem::getPixelsPerLine());
- } else if (ev.special_key == TB_KEY_DOWN && m_scrollbar_y.canScrollPositive()) {
- scrollBySmooth(0, TBSystem::getPixelsPerLine());
- } else if (ev.special_key == TB_KEY_PAGE_UP && m_scrollbar_y.canScrollNegative()) {
- scrollBySmooth(0, -getPaddingRect().h);
- } else if (ev.special_key == TB_KEY_PAGE_DOWN && m_scrollbar_y.canScrollPositive()) {
- scrollBySmooth(0, getPaddingRect().h);
- } else if (ev.special_key == TB_KEY_HOME) {
- scrollToSmooth(m_scrollbar_x.getValue(), 0);
- } else if (ev.special_key == TB_KEY_END) {
- scrollToSmooth(m_scrollbar_x.getValue(), (int)m_scrollbar_y.getMaxValue());
- } else {
- return false;
- }
- return true;
- }
- return false;
-}
-
-void TBScrollContainer::onProcess() {
- SizeConstraints sc(getRect().w, getRect().h);
- validateLayout(sc);
-}
-
-void TBScrollContainer::validateLayout(const SizeConstraints &constraints) {
- if (!m_layout_is_invalid) {
- return;
- }
- m_layout_is_invalid = false;
-
- // Layout scrollbars (no matter if they are visible or not)
- int scrollbar_y_w = m_scrollbar_y.getPreferredSize().pref_w;
- int scrollbar_x_h = m_scrollbar_x.getPreferredSize().pref_h;
- m_scrollbar_x.setRect(TBRect(0, getRect().h - scrollbar_x_h, getRect().w - scrollbar_y_w, scrollbar_x_h));
- m_scrollbar_y.setRect(TBRect(getRect().w - scrollbar_y_w, 0, scrollbar_y_w, getRect().h));
-
- if (TBWidget *content_child = m_root.getFirstChild()) {
- int horizontal_padding = TBScrollBarVisibility::isAlwaysOnY(m_mode) ? scrollbar_y_w : 0;
- int vertical_padding = TBScrollBarVisibility::isAlwaysOnX(m_mode) ? scrollbar_x_h : 0;
-
- SizeConstraints inner_sc = constraints.constrainByPadding(horizontal_padding, vertical_padding);
-
- PreferredSize ps = content_child->getPreferredSize(inner_sc);
-
- TBScrollBarVisibility visibility = TBScrollBarVisibility::solve(m_mode, ps.pref_w, ps.pref_h, getRect().w,
- getRect().h, scrollbar_x_h, scrollbar_y_w);
- m_scrollbar_x.setOpacity(visibility.x_on ? 1.F : 0.F);
- m_scrollbar_y.setOpacity(visibility.y_on ? 1.F : 0.F);
- m_root.setRect(TBRect(0, 0, visibility.visible_w, visibility.visible_h));
-
- int content_w;
- int content_h;
- if (m_adapt_content_size) {
- content_w = Max(ps.pref_w, m_root.getRect().w);
- content_h = Max(ps.pref_h, m_root.getRect().h);
- if (!visibility.x_on && m_root.getRect().w < ps.pref_w) {
- content_w = Min(ps.pref_w, m_root.getRect().w);
- }
- } else {
- content_w = ps.pref_w;
- content_h = ps.pref_h;
- }
-
- content_child->setRect(TBRect(0, 0, content_w, content_h));
- double limit_max_w = Max(0, content_w - m_root.getRect().w);
- double limit_max_h = Max(0, content_h - m_root.getRect().h);
- m_scrollbar_x.setLimits(0, limit_max_w, m_root.getRect().w);
- m_scrollbar_y.setLimits(0, limit_max_h, m_root.getRect().h);
- }
-}
-
-void TBScrollContainer::onResized(int oldW, int oldH) {
- invalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
- SizeConstraints sc(getRect().w, getRect().h);
- validateLayout(sc);
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_scroll_container.h b/src/modules/ui/turbobadger/tb/tb_scroll_container.h
deleted file mode 100644
index 620b695ef..000000000
--- a/src/modules/ui/turbobadger/tb/tb_scroll_container.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_widgets_common.h"
-
-namespace tb {
-
-enum SCROLL_MODE {
- SCROLL_MODE_X_Y, ///< X and Y always scroll-mode: xy
- SCROLL_MODE_Y, ///< Y always (X never) scroll-mode: y
- SCROLL_MODE_Y_AUTO, ///< Y auto (X never) scroll-mode: y-auto
- SCROLL_MODE_X_AUTO_Y_AUTO, ///< X auto, Y auto scroll-mode: auto
- SCROLL_MODE_OFF ///< X any Y never scroll-mode: off
-};
-
-/** TBScrollContainerRoot - Internal for TBScrollContainer */
-class TBScrollContainerRoot : public TBWidget {
-private: // May only be used by TBScrollContainer.
- friend class TBScrollContainer;
- TBScrollContainerRoot() {
- }
-
-public:
- virtual void onPaintChildren(const PaintProps &paint_props) override;
- virtual void getChildTranslation(int &x, int &y) const override;
-};
-
-/** TBScrollBarVisibility - Helper for TBScrollContainer or any other scrollable
- container that needs to solve scrollbar visibility according to SCROLL_MODE. */
-class TBScrollBarVisibility {
-public:
- TBScrollBarVisibility() : x_on(false), y_on(false), visible_w(0), visible_h(0) {
- }
-
- static TBScrollBarVisibility solve(SCROLL_MODE mode, int contentW, int contentH, int availableW, int availableH,
- int scrollbarXH, int scrollbarYW);
- static bool isAlwaysOnX(SCROLL_MODE mode) {
- return mode == SCROLL_MODE_X_Y;
- }
- static bool isAlwaysOnY(SCROLL_MODE mode) {
- return mode == SCROLL_MODE_X_Y || mode == SCROLL_MODE_Y;
- }
-
-public:
- bool x_on, y_on;
- int visible_w, visible_h;
-};
-
-/** TBScrollContainer - A container with scrollbars that can scroll its children. */
-class TBScrollContainer : public TBWidget {
- friend class TBScrollContainerRoot;
-
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBScrollContainer, TBWidget);
-
- TBScrollContainer();
- ~TBScrollContainer();
-
- /** Set to true if the preferred size of this container should adapt to the preferred
- size of the content. This is disabled by default. */
- void setAdaptToContentSize(bool adapt);
- bool getAdaptToContentSize() {
- return m_adapt_to_content_size;
- }
-
- /** Set to true if the content should adapt to the available size of this container
- when it's larger than the preferred size. */
- void setAdaptContentSize(bool adapt);
- bool getAdaptContentSize() {
- return m_adapt_content_size;
- }
-
- void setScrollMode(SCROLL_MODE mode);
- SCROLL_MODE getScrollMode() {
- return m_mode;
- }
-
- virtual void scrollTo(int x, int y) override;
- virtual TBWidget::ScrollInfo getScrollInfo() override;
- virtual TBWidget *getScrollRoot() override {
- return &m_root;
- }
-
- virtual void invalidateLayout(INVALIDATE_LAYOUT il) override;
-
- virtual TBRect getPaddingRect() override;
- virtual PreferredSize onCalculatePreferredContentSize(const SizeConstraints &constraints) override;
-
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual bool onEvent(const TBWidgetEvent &ev) override;
- virtual void onProcess() override;
- virtual void onResized(int oldW, int oldH) override;
-
- virtual TBWidget *getContentRoot() override {
- return &m_root;
- }
-
-protected:
- TBScrollBar m_scrollbar_x;
- TBScrollBar m_scrollbar_y;
- TBScrollContainerRoot m_root;
- bool m_adapt_to_content_size = false;
- bool m_adapt_content_size = false;
- bool m_layout_is_invalid = false;
- SCROLL_MODE m_mode = SCROLL_MODE_X_Y;
- void validateLayout(const SizeConstraints &constraints);
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_scroller.cpp b/src/modules/ui/turbobadger/tb/tb_scroller.cpp
deleted file mode 100644
index 4b9e4a03a..000000000
--- a/src/modules/ui/turbobadger/tb/tb_scroller.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_scroller.h"
-#include "tb_system.h"
-#include "tb_widgets.h"
-#include
-
-namespace tb {
-
-// == Misc constants ====================================================================
-
-#define PAN_TARGET_FPS 60
-#define PAN_MSG_DELAY_MS ((double)(1000.0 / PAN_TARGET_FPS))
-
-#define PAN_START_THRESHOLD_MS 50
-#define PAN_POWER_ACC_THRESHOLD_MS 600
-
-#define PAN_POWER_MULTIPLIER 1.3f
-
-#define SCROLL_DECAY 200.0f
-
-#define SF_GATE_THRESHOLD 0.01f
-
-// Lab:
-// http://www.madtealab.com/?V=1&C=6&F=5&G=1&O=1&W=774&GW=720&GH=252&GX=13.389616776278201&GY=4.790704772336853&GS=0.13102127484993598&EH=189&a=3.6666666666666665&aMa=20&aN=OrgSpeed&bMa=3&bN=CurPos&c=8&cMa=60&cI=1&cN=FrameRate&d=16&dMa=16&dI=1&dN=numSimulatedSeconds&l=2.388888888888889&lMa=5&lN=Decay&m=0.1&mMa=0.1&mN=GateThreshold&f1=OrgSpeed+%2A+exp%28-x+%2F+Decay%29&f1N=Speed&f2=CurPos+%2B+OrgSpeed+%2A+%281-exp%28-x+%2F+Decay%29%29%2A+Decay&f2N=Pos&f3=marker%28x%2C+predictGatedPoint%29&f3N=GatePoint&f4=aToF%28simulatedPoints%2Cnearest%2C0%2CnumSimulatedSeconds%29%28x%29&f4N=Iterated&f5=OrgSpeed+%2A+x&f5N=Linear1&Expr=%0ApredictGatedPoint+%3D+-log%28GateThreshold+%2F+%28OrgSpeed%29%29+%2A+Decay%0A%0Avar+cur+%3D+OrgSpeed%0AsimulatedPoints+%3D+sample%28function%28%29+%7B%0A+++cur+%3D+cur+%2A+%281+-+0.05%29%3B%0A+++return+cur%0A+%7D%2C+%5BnumSimulatedSeconds+%2A+FrameRate%5D%29%3B%0A%0ApredictGatedPoint
-
-float TBScrollerFunction::getDurationFromSpeed(float startSpeed) {
- float abs_start_speed = Abs(startSpeed);
- if (abs_start_speed <= SF_GATE_THRESHOLD) {
- return 0;
- }
- return -logf(SF_GATE_THRESHOLD / abs_start_speed) * m_decay;
-}
-
-float TBScrollerFunction::getSpeedFromDistance(float distance) {
- float speed = distance / m_decay;
- if (distance > SF_GATE_THRESHOLD) {
- return speed + SF_GATE_THRESHOLD;
- }
- if (distance < -SF_GATE_THRESHOLD) {
- return speed - SF_GATE_THRESHOLD;
- }
- return speed;
-}
-
-float TBScrollerFunction::getDistanceAtTime(float startSpeed, float elapsedTimeMs) {
- core_assert(elapsedTimeMs >= 0);
- return startSpeed * (1 - expf(-elapsedTimeMs / m_decay)) * m_decay;
-}
-
-int TBScrollerFunction::getDistanceAtTimeInt(float startSpeed, float elapsedTimeMs) {
- float distance = getDistanceAtTime(startSpeed, elapsedTimeMs);
- return (int)(distance < 0 ? distance - 0.5F : distance + 0.5F);
-}
-
-// == TBScroller ========================================================================
-
-TBScroller::TBScroller(TBWidget *target)
- : m_target(target), m_snap_listener(nullptr), m_func(SCROLL_DECAY), m_previous_pan_dx(0), m_previous_pan_dy(0),
- m_scroll_start_ms(0), m_scroll_duration_x_ms(0), m_scroll_duration_y_ms(0), m_pan_power_multiplier_x(1),
- m_pan_power_multiplier_y(1) {
- reset();
-}
-
-TBScroller::~TBScroller() {
-}
-
-void TBScroller::reset() {
- m_is_started = false;
- m_pan_dx = m_pan_dy = 0;
- m_pan_time_ms = 0;
- m_pan_delta_time_ms = 0;
- m_scroll_start_speed_ppms_x = m_scroll_start_speed_ppms_y = 0;
- m_scroll_start_scroll_x = m_scroll_start_scroll_y = 0;
- // don't reset m_previous_pan_dx and m_previous_pan_dy here.
- // don't reset m_pan_power here. It's done on start since it's needed for next pan!
- m_expected_scroll_x = m_expected_scroll_y = 0;
-}
-
-void TBScroller::onScrollBy(int dx, int dy, bool accumulative) {
- if (!isStarted()) {
- start();
- }
-
- float ppms_x = m_func.getSpeedFromDistance((float)dx);
- float ppms_y = m_func.getSpeedFromDistance((float)dy);
-
- if (accumulative && isScrolling()) {
- TBWidget::ScrollInfo info = m_target->getScrollInfo();
- // If new direction is the same as the current direction,
- // calculate the speed needed for the remaining part and
- // add that to the new scroll speed.
- if ((ppms_x < 0) == (m_scroll_start_speed_ppms_x < 0)) {
- int distance_x = m_func.getDistanceAtTimeInt(m_scroll_start_speed_ppms_x,
- m_func.getDurationFromSpeed(m_scroll_start_speed_ppms_x));
- int distance_remaining_x = m_scroll_start_scroll_x + distance_x - info.x;
- distance_remaining_x += m_func.getDistanceAtTimeInt(ppms_x, m_func.getDurationFromSpeed(ppms_x));
- ppms_x = m_func.getSpeedFromDistance((float)distance_remaining_x);
- }
- if ((ppms_y < 0) == (m_scroll_start_speed_ppms_y < 0)) {
- int distance_y = m_func.getDistanceAtTimeInt(m_scroll_start_speed_ppms_y,
- m_func.getDurationFromSpeed(m_scroll_start_speed_ppms_y));
- int distance_remaining_y = m_scroll_start_scroll_y + distance_y - info.y;
- distance_remaining_y += m_func.getDistanceAtTimeInt(ppms_y, m_func.getDurationFromSpeed(ppms_y));
- ppms_y = m_func.getSpeedFromDistance((float)distance_remaining_y);
- }
- }
-
- adjustToSnappingAndScroll(ppms_x, ppms_y);
-}
-
-bool TBScroller::onPan(int dx, int dy) {
- if (!isStarted()) {
- start();
- }
-
- // Pan the target
- const int in_dx = dx;
- const int in_dy = dy;
- m_target->scrollByRecursive(dx, dy);
-
- // Calculate the pan speed. Smooth it out with the
- // previous pan speed to reduce fluctuation a little.
- double now_ms = TBSystem::getTimeMS();
- if (m_pan_time_ms != 0.0) {
- if (m_pan_delta_time_ms != 0.0) {
- m_pan_delta_time_ms = (now_ms - m_pan_time_ms + m_pan_delta_time_ms) / 2.0F;
- } else {
- m_pan_delta_time_ms = now_ms - m_pan_time_ms;
- }
- }
-
- m_pan_time_ms = now_ms;
- m_pan_dx = (m_pan_dx + in_dx) / 2.0F;
- m_pan_dy = (m_pan_dy + in_dy) / 2.0F;
-
- // If we change direction, reset the pan power multiplier in that axis.
- if (m_pan_dx != 0 && (m_previous_pan_dx < 0) != (m_pan_dx < 0)) {
- m_pan_power_multiplier_x = 1;
- }
- if (m_pan_dy != 0 && (m_previous_pan_dy < 0) != (m_pan_dy < 0)) {
- m_pan_power_multiplier_y = 1;
- }
- m_previous_pan_dx = m_pan_dx;
- m_previous_pan_dy = m_pan_dy;
-
- return in_dx != dx || in_dy != dy;
-}
-
-void TBScroller::onPanReleased() {
- if (TBSystem::getTimeMS() < m_pan_time_ms + PAN_START_THRESHOLD_MS) {
- // Don't start scroll if we have too little speed.
- // This will prevent us from scrolling accidently.
- float pan_start_distance_threshold_px = 2 * TBSystem::getDPI() / 100.0F;
- if (Abs(m_pan_dx) < pan_start_distance_threshold_px && Abs(m_pan_dy) < pan_start_distance_threshold_px) {
- stopOrSnapScroll();
- return;
- }
-
- if (m_pan_delta_time_ms == 0) {
- stopOrSnapScroll();
- return;
- }
-
- float ppms_x = (float)m_pan_dx / (float)m_pan_delta_time_ms;
- float ppms_y = (float)m_pan_dy / (float)m_pan_delta_time_ms;
- ppms_x *= m_pan_power_multiplier_x;
- ppms_y *= m_pan_power_multiplier_y;
-
- adjustToSnappingAndScroll(ppms_x, ppms_y);
- } else {
- stopOrSnapScroll();
- }
-}
-
-void TBScroller::start() {
- if (isStarted()) {
- return;
- }
- m_is_started = true;
- double now_ms = TBSystem::getTimeMS();
- if (now_ms < m_scroll_start_ms + PAN_POWER_ACC_THRESHOLD_MS) {
- m_pan_power_multiplier_x *= PAN_POWER_MULTIPLIER;
- m_pan_power_multiplier_y *= PAN_POWER_MULTIPLIER;
- } else {
- m_pan_power_multiplier_x = m_pan_power_multiplier_y = 1;
- }
-}
-
-void TBScroller::stop() {
- deleteAllMessages();
- reset();
-}
-
-bool TBScroller::stopIfAlmostStill() {
- double now_ms = TBSystem::getTimeMS();
- if (now_ms > m_scroll_start_ms + (double)m_scroll_duration_x_ms &&
- now_ms > m_scroll_start_ms + (double)m_scroll_duration_y_ms) {
- stop();
- return true;
- }
- return false;
-}
-
-void TBScroller::stopOrSnapScroll() {
- adjustToSnappingAndScroll(0, 0);
- if (!isScrolling()) {
- stop();
- }
-}
-
-void TBScroller::adjustToSnappingAndScroll(float ppmsX, float ppmsY) {
- if (m_snap_listener != nullptr) {
- // Calculate the distance
- int distance_x = m_func.getDistanceAtTimeInt(ppmsX, m_func.getDurationFromSpeed(ppmsX));
- int distance_y = m_func.getDistanceAtTimeInt(ppmsY, m_func.getDurationFromSpeed(ppmsY));
-
- // Let the snap listener modify the distance
- TBWidget::ScrollInfo info = m_target->getScrollInfo();
- int target_x = distance_x + info.x;
- int target_y = distance_y + info.y;
- m_snap_listener->onScrollSnap(m_target, target_x, target_y);
- distance_x = target_x - info.x;
- distance_y = target_y - info.y;
-
- // Get the start speed from the new distance
- ppmsX = m_func.getSpeedFromDistance((float)distance_x);
- ppmsY = m_func.getSpeedFromDistance((float)distance_y);
- }
-
- scroll(ppmsX, ppmsY);
-}
-
-void TBScroller::scroll(float startSpeedPpmsX, float startSpeedPpmsY) {
- // Set start values
- m_scroll_start_ms = TBSystem::getTimeMS();
- getTargetScrollXY(m_scroll_start_scroll_x, m_scroll_start_scroll_y);
- m_scroll_start_speed_ppms_x = startSpeedPpmsX;
- m_scroll_start_speed_ppms_y = startSpeedPpmsY;
-
- // Calculate duration for the scroll (each axis independently)
- m_scroll_duration_x_ms = m_func.getDurationFromSpeed(m_scroll_start_speed_ppms_x);
- m_scroll_duration_y_ms = m_func.getDurationFromSpeed(m_scroll_start_speed_ppms_y);
-
- if (stopIfAlmostStill()) {
- return;
- }
-
- // Post the pan message if we don't already have one
- if (getMessageByID(TBIDC("scroll")) == nullptr) {
- // Update expected translation
- getTargetChildTranslation(m_expected_scroll_x, m_expected_scroll_y);
-
- postMessageDelayed(TBIDC("scroll"), nullptr, (uint32_t)PAN_MSG_DELAY_MS);
- }
-}
-
-bool TBScroller::isScrolling() {
- return getMessageByID(TBIDC("scroll")) != nullptr;
-}
-
-void TBScroller::getTargetChildTranslation(int &x, int &y) const {
- int root_x = 0;
- int root_y = 0;
- int child_translation_x = 0;
- int child_translation_y = 0;
- TBWidget *scroll_root = m_target->getScrollRoot();
- scroll_root->convertToRoot(root_x, root_y);
- scroll_root->getChildTranslation(child_translation_x, child_translation_y);
- x = root_x + child_translation_x;
- y = root_y + child_translation_y;
-}
-
-void TBScroller::getTargetScrollXY(int &x, int &y) const {
- x = 0;
- y = 0;
- TBWidget *tmp = m_target->getScrollRoot();
- while (tmp != nullptr) {
- TBWidget::ScrollInfo info = tmp->getScrollInfo();
- x += info.x;
- y += info.y;
- tmp = tmp->getParent();
- }
-}
-
-void TBScroller::onMessageReceived(TBMessage *msg) {
- if (msg->message == TBIDC("scroll")) {
- int actual_scroll_x = 0;
- int actual_scroll_y = 0;
- getTargetChildTranslation(actual_scroll_x, actual_scroll_y);
- if (actual_scroll_x != m_expected_scroll_x || actual_scroll_y != m_expected_scroll_y) {
- // Something else has affected the target child translation.
- // This should abort the scroll.
- // This could happen f.ex if something shrunk the scroll limits,
- // some other action changed scroll position, or if another
- // scroller started operating on a sub child that when reacing
- // its scroll limit, started scrolling its chain of parents.
- stop();
- return;
- }
-
- // Calculate the time elapsed from scroll start. Clip within the
- // duration for each axis.
- double now_ms = TBSystem::getTimeMS();
- float elapsed_time_x = (float)(now_ms - m_scroll_start_ms);
- float elapsed_time_y = elapsed_time_x;
- elapsed_time_x = Min(elapsed_time_x, m_scroll_duration_x_ms);
- elapsed_time_y = Min(elapsed_time_y, m_scroll_duration_y_ms);
-
- // Get the new scroll position from the current distance in each axis.
- int scroll_x = m_func.getDistanceAtTimeInt(m_scroll_start_speed_ppms_x, elapsed_time_x);
- int scroll_y = m_func.getDistanceAtTimeInt(m_scroll_start_speed_ppms_y, elapsed_time_y);
- scroll_x += m_scroll_start_scroll_x;
- scroll_y += m_scroll_start_scroll_y;
-
- // Get the scroll delta and invoke ScrollByRecursive.
- int curr_scroll_x;
- int curr_scroll_y;
- getTargetScrollXY(curr_scroll_x, curr_scroll_y);
- const int dx = scroll_x - curr_scroll_x;
- const int dy = scroll_y - curr_scroll_y;
-
- int idx = dx;
- int idy = dy;
- m_target->scrollByRecursive(idx, idy);
-
- // Update expected translation
- getTargetChildTranslation(m_expected_scroll_x, m_expected_scroll_y);
-
- if (((dx != 0) && actual_scroll_x == m_expected_scroll_x) &&
- ((dy != 0) && actual_scroll_y == m_expected_scroll_y)) {
- // We didn't get anywhere despite we tried,
- // so we're done (reached the end).
- stop();
- return;
- }
-
- if (!stopIfAlmostStill()) {
- double next_fire_time = msg->getFireTime() + PAN_MSG_DELAY_MS;
- // avoid timer catch-up if program went sleeping for a while.
- next_fire_time = Max(next_fire_time, now_ms);
- postMessageOnTime(TBIDC("scroll"), nullptr, next_fire_time);
- }
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_scroller.h b/src/modules/ui/turbobadger/tb/tb_scroller.h
deleted file mode 100644
index ddd14920a..000000000
--- a/src/modules/ui/turbobadger/tb/tb_scroller.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-#include "tb_msg.h"
-
-namespace tb {
-
-class TBWidget;
-
-/** TBScrollerFunction does the calculations of time, speed and distance
- that decides how the slow down of a scroll will happen.
-
- Note: Speed is in pixels per millisecond. Duration is in milliseconds
- and distance is in pixels. Distance and speed may be negative! */
-class TBScrollerFunction {
-public:
- TBScrollerFunction(float decay) : m_decay(decay) {
- }
-
- /** Calculate the duration needed until the end distance is reached
- from the given start speed. */
- float getDurationFromSpeed(float start_speed);
-
- /** Calculate the start speed needed to reach the given distance. */
- float getSpeedFromDistance(float distance);
-
- /** Calculate the distance reached at the given elapsed_time_ms with the given start_speed. */
- float getDistanceAtTime(float startSpeed, float elapsedTimeMs);
-
- /** Same as GetDistanceAtTime but rounded to integer. */
- int getDistanceAtTimeInt(float startSpeed, float elapsedTimeMs);
-
-private:
- float m_decay;
-};
-
-/** TBScrollerSnapListener may override the target scroll position of a TBScroller. */
-
-class TBScrollerSnapListener {
-public:
- virtual ~TBScrollerSnapListener(){};
-
- /** Called when the target scroll position is calculated.
-
- target_widget is the widget being scroller.
- target_x, target_y is the suggested target scroll position which may be changed
- to something else in this call.
-
- Note: The scroll positions are relative to the target widget (inner scrolled TBWidget).
- If there's nested scrollable widgets, only the inner scrolled widget applies snapping. */
- virtual void onScrollSnap(TBWidget *targetWidget, int &targetX, int &targetY) = 0;
-};
-
-/** TBScroller handles panning while the pointer is down and measure the pan
- speed over time. It also handles continued scrolling when the pointer has
- been released with a flick. */
-class TBScroller : private TBMessageHandler {
-public:
- TBScroller(TBWidget *target);
- ~TBScroller();
-
- /** Set the listener that may override the target scroll position. */
- void setSnapListener(TBScrollerSnapListener *listener) {
- m_snap_listener = listener;
- }
-
- /** Start tracking pan movement from calls to OnPan. */
- void start();
-
- /** Stop tracking pan movement from calls to OnPan,
- or stop any ongoing scrolling. */
- void stop();
-
- /** Return true if the pan tracking is started or. */
- bool isStarted() const {
- return m_is_started;
- }
-
- /** Get the widget that will be panned/scrolled. Any parent of this
- widget may also be panned/scrolled. */
- TBWidget *getTarget() const {
- return m_target;
- }
-
- /** Pan the target widget (or any parent) with the given deltas.
- Should be called while the pointer is down.
- This will track the pan speed over time. */
- bool onPan(int dx, int dy);
-
- /** The panning ends and the scroller should start scrolling.
- Should be called when the pointer is released. */
- void onPanReleased();
-
- /** Start the scroller based on the given delta. Doesn't
- require previous calls to OnPan or OnPanReleased.
-
- If accumulative is true, the given delta will be
- added to any on going scroll. If it's false, any
- ongoing scroll will be canceled. */
- void onScrollBy(int dx, int dy, bool accumulative);
-
-private:
- virtual void onMessageReceived(TBMessage *msg);
- bool isScrolling();
- bool stopIfAlmostStill();
- void stopOrSnapScroll();
- void reset();
- void adjustToSnappingAndScroll(float ppmsX, float ppmsY);
- void scroll(float startSpeedPpmsX, float startSpeedPpmsY);
- void getTargetChildTranslation(int &x, int &y) const;
- void getTargetScrollXY(int &x, int &y) const;
- TBWidget *m_target;
- TBScrollerSnapListener *m_snap_listener;
- TBScrollerFunction m_func;
- bool m_is_started;
- float m_pan_dx, m_pan_dy;
- float m_previous_pan_dx, m_previous_pan_dy;
- double m_pan_time_ms;
- double m_pan_delta_time_ms;
- float m_scroll_start_speed_ppms_x, m_scroll_start_speed_ppms_y;
- double m_scroll_start_ms;
- float m_scroll_duration_x_ms, m_scroll_duration_y_ms;
- int m_scroll_start_scroll_x, m_scroll_start_scroll_y;
- float m_pan_power_multiplier_x;
- float m_pan_power_multiplier_y;
- int m_expected_scroll_x;
- int m_expected_scroll_y;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_select.cpp b/src/modules/ui/turbobadger/tb/tb_select.cpp
deleted file mode 100644
index cd7e26179..000000000
--- a/src/modules/ui/turbobadger/tb/tb_select.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_select.h"
-#include "tb_language.h"
-#include "tb_menu_window.h"
-#include "tb_sort.h"
-#include "tb_tempbuffer.h"
-#include "tb_widgets_listener.h"
-#include "core/StringUtil.h"
-
-namespace tb {
-
-// == Sort callback for sorting items ===================================================
-
-int select_list_sort_cb(TBSelectItemSource *source, const int *a, const int *b) {
- const int value = SDL_strcmp(source->getItemString(*a), source->getItemString(*b));
- return source->getSort() == TB_SORT_DESCENDING ? -value : value;
-}
-
-TBSelectList::TBSelectList()
- : m_value(-1), m_list_is_invalid(false), m_scroll_to_current(false),
- m_header_lng_string_id(TBIDC("TBList.header")) {
- _sortCallback = select_list_sort_cb;
- setSource(&m_default_source);
- setIsFocusable(true);
- setSkinBg(TBIDC("TBSelectList"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- m_container.setGravity(WIDGET_GRAVITY_ALL);
- m_container.setRect(getPaddingRect());
- addChild(&m_container);
- m_layout.setGravity(WIDGET_GRAVITY_ALL);
- m_layout.setAxis(AXIS_Y);
- m_layout.setSpacing(0);
- m_layout.setLayoutPosition(LAYOUT_POSITION_LEFT_TOP);
- m_layout.setLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP);
- m_layout.setLayoutSize(LAYOUT_SIZE_AVAILABLE);
- m_container.getContentRoot()->addChild(&m_layout);
- m_container.setScrollMode(SCROLL_MODE_Y_AUTO);
- m_container.setAdaptContentSize(true);
-}
-
-TBSelectList::~TBSelectList() {
- m_layout.removeFromParent();
- m_container.removeFromParent();
- setSource(nullptr);
-}
-
-void TBSelectList::onSourceChanged() {
- invalidateList();
-}
-
-void TBSelectList::onItemChanged(int index) {
- if (m_list_is_invalid) { // We're updating all widgets soon.
- return;
- }
-
- TBWidget *old_widget = getItemWidget(index);
- if (old_widget == nullptr) { // We don't have this widget so we have nothing to update.
- return;
- }
-
- // Replace the old widget representing the item, with a new one. Preserve its state.
- WIDGET_STATE old_state = old_widget->getStateRaw();
-
- if (TBWidget *widget = createAndAddItemAfter(index, old_widget)) {
- widget->setStateRaw(old_state);
- }
-
- old_widget->removeFromParent();
- delete old_widget;
-}
-
-void TBSelectList::onItemAdded(int index) {
- if (m_list_is_invalid) { // We're updating all widgets soon.
- return;
- }
-
- // Sorting, filtering etc. makes it messy to handle dynamic addition of items.
- // Resort to invalidate the entire list (may even be faster anyway)
- invalidateList();
-}
-
-void TBSelectList::onItemRemoved(int index) {
- if (m_list_is_invalid) { // We're updating all widgets soon.
- return;
- }
-
- // Sorting, filtering etc. makes it messy to handle dynamic addition of items.
- // Resort to invalidate the entire list (may even be faster anyway)
- invalidateList();
-}
-
-void TBSelectList::onAllItemsRemoved() {
- invalidateList();
- m_value = -1;
-}
-
-void TBSelectList::setFilter(const char *filter) {
- core::String new_filter;
- if ((filter != nullptr) && (*filter != 0)) {
- new_filter = filter;
- }
- if (m_filter == new_filter) {
- return;
- }
- m_filter = new_filter;
- invalidateList();
-}
-
-void TBSelectList::setHeaderString(const TBID &id) {
- if (m_header_lng_string_id == id) {
- return;
- }
- m_header_lng_string_id = id;
- invalidateList();
-}
-
-void TBSelectList::invalidateList() {
- if (m_list_is_invalid) {
- return;
- }
- m_list_is_invalid = true;
- invalidate();
-}
-
-void TBSelectList::validateList() {
- if (!m_list_is_invalid) {
- return;
- }
- m_list_is_invalid = false;
- // FIX: Could delete and create only the changed items (faster filter change)
-
- // Remove old items
- while (TBWidget *child = m_layout.getContentRoot()->getFirstChild()) {
- child->removeFromParent();
- delete child;
- }
- if ((m_source == nullptr) || (m_source->getNumItems() == 0)) {
- return;
- }
-
- // Create a sorted list of the items we should include using the current filter.
- TBTempBuffer sort_buf;
- if (!sort_buf.reserve(m_source->getNumItems() * sizeof(int))) {
- return; // Out of memory
- }
- int *sorted_index = (int *)sort_buf.getData();
-
- // Populate the sorted index list
- int num_sorted_items = 0;
- for (int i = 0; i < m_source->getNumItems(); i++) {
- if (m_filter.empty() || m_source->filter(i, m_filter)) {
- sorted_index[num_sorted_items++] = i;
- }
- }
-
- // Sort
- if (m_source->getSort() != TB_SORT_NONE) {
- insertion_sort(sorted_index, num_sorted_items, m_source, _sortCallback);
- }
-
- // Show header if we only show a subset of all items.
- if (!m_filter.empty()) {
- if (TBWidget *widget = new TBTextField()) {
- const core::String& str = core::string::format(g_tb_lng->getString(m_header_lng_string_id), num_sorted_items, m_source->getNumItems());
- widget->setText(str);
- widget->setSkinBg(TBIDC("TBList.header"));
- widget->setState(WIDGET_STATE_DISABLED, true);
- widget->setGravity(WIDGET_GRAVITY_ALL);
- widget->data.setInt(-1);
- m_layout.getContentRoot()->addChild(widget);
- }
- }
-
- // Create new items
- for (int i = 0; i < num_sorted_items; i++) {
- createAndAddItemAfter(sorted_index[i], nullptr);
- }
-
- selectItem(m_value, true);
-
- // FIX: Should not scroll just because we update the list. Only automatically first time!
- m_scroll_to_current = true;
-}
-
-TBWidget *TBSelectList::createAndAddItemAfter(int index, TBWidget *reference) {
- if (TBWidget *widget = m_source->createItemWidget(index, this)) {
- // Use item data as widget to index lookup
- widget->data.setInt(index);
- m_layout.getContentRoot()->addChildRelative(widget, WIDGET_Z_REL_AFTER, reference);
- return widget;
- }
- return nullptr;
-}
-
-void TBSelectList::setValue(int value) {
- if (value == m_value) {
- return;
- }
-
- selectItem(m_value, false);
- m_value = value;
- selectItem(m_value, true);
- scrollToSelectedItem();
-
- TBWidgetEvent ev(EVENT_TYPE_CHANGED);
- if (TBWidget *widget = getItemWidget(m_value)) {
- ev.ref_id = widget->getID();
- }
- invokeEvent(ev);
-}
-
-TBID TBSelectList::getSelectedItemID() const {
- if ((m_source != nullptr) && m_value >= 0 && m_value < m_source->getNumItems()) {
- return m_source->getItemID(m_value);
- }
- return TBID();
-}
-
-void TBSelectList::selectItem(int index, bool selected) {
- if (TBWidget *widget = getItemWidget(index)) {
- widget->setState(WIDGET_STATE_SELECTED, selected);
- }
-}
-
-TBWidget *TBSelectList::getItemWidget(int index) {
- if (index == -1) {
- return nullptr;
- }
- for (TBWidget *tmp = m_layout.getContentRoot()->getFirstChild(); tmp != nullptr; tmp = tmp->getNext()) {
- if (tmp->data.getInt() == index) {
- return tmp;
- }
- }
- return nullptr;
-}
-
-void TBSelectList::scrollToSelectedItem() {
- if (m_list_is_invalid) {
- m_scroll_to_current = true;
- return;
- }
- m_scroll_to_current = false;
- if (TBWidget *widget = getItemWidget(m_value)) {
- m_container.scrollIntoView(widget->getRect());
- } else {
- m_container.scrollTo(0, 0);
- }
-}
-
-void TBSelectList::onSkinChanged() {
- m_container.setRect(getPaddingRect());
-}
-
-void TBSelectList::onProcess() {
- validateList();
-}
-
-void TBSelectList::onProcessAfterChildren() {
- if (m_scroll_to_current) {
- scrollToSelectedItem();
- }
-}
-
-bool TBSelectList::onEvent(const TBWidgetEvent &ev) {
- if (ev.type == EVENT_TYPE_CLICK && ev.target->getParent() == m_layout.getContentRoot()) {
- // setValue (EVENT_TYPE_CHANGED) might cause something to delete this (f.ex closing
- // the dropdown menu. We want to sent another event, so ensure we're still around.
- TBWidgetSafePointer this_widget(this);
-
- int index = ev.target->data.getInt();
- setValue(index);
-
- // If we're still around, invoke the click event too.
- if (this_widget.get() != nullptr) {
- TBSelectList *target_list = this;
- // If the parent window is a TBMenuWindow, we will iterate up the event destination
- // chain to find the top TBMenuWindow and invoke the event there.
- // That way events in submenus will reach the caller properly, and seem like it was
- // invoked on the top menu.
- TBWindow *window = getParentWindow();
- while (TBMenuWindow *menu_win = TBSafeCast(window)) {
- target_list = menu_win->getList();
- window = menu_win->getEventDestination()->getParentWindow();
- }
-
- // Invoke the click event on the target list
- TBWidgetEvent ev(EVENT_TYPE_CLICK);
- if (TBWidget *widget = getItemWidget(m_value)) {
- ev.ref_id = widget->getID();
- }
- target_list->invokeEvent(ev);
- }
- return true;
- }
- if (ev.type == EVENT_TYPE_KEY_DOWN) {
- if (changeValue(ev.special_key)) {
- return true;
- }
-
- // Give the scroll container a chance to handle the key so it may
- // scroll. This matters if the list itself is focused instead of
- // some child view of any select item (since that would have passed
- // the container already)
- if (getScrollContainer()->onEvent(ev)) {
- return true;
- }
- }
- return false;
-}
-
-bool TBSelectList::changeValue(SPECIAL_KEY key) {
- if ((m_source == nullptr) || (m_layout.getContentRoot()->getFirstChild() == nullptr)) {
- return false;
- }
-
- bool forward;
- if (key == TB_KEY_HOME || key == TB_KEY_DOWN) {
- forward = true;
- } else if (key == TB_KEY_END || key == TB_KEY_UP) {
- forward = false;
- } else {
- return false;
- }
-
- TBWidget *item_root = m_layout.getContentRoot();
- TBWidget *current = getItemWidget(m_value);
- TBWidget *origin = nullptr;
- if (key == TB_KEY_HOME || ((current == nullptr) && key == TB_KEY_DOWN)) {
- current = item_root->getFirstChild();
- } else if (key == TB_KEY_END || ((current == nullptr) && key == TB_KEY_UP)) {
- current = item_root->getLastChild();
- } else {
- origin = current;
- }
-
- while (current != nullptr) {
- if (current != origin && !current->getDisabled()) {
- break;
- }
- current = forward ? current->getNext() : current->getPrev();
- }
- // Select and focus what we found
- if (current != nullptr) {
- setValue(current->data.getInt());
- return true;
- }
- return false;
-}
-
-// == TBSelectDropdown ==========================================
-
-TBSelectDropdown::TBSelectDropdown() : m_value(-1) {
- setSource(&m_default_source);
- setSkinBg(TBIDC("TBSelectDropdown"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- m_arrow.setSkinBg(TBIDC("TBSelectDropdown.arrow"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- getContentRoot()->addChild(&m_arrow);
-}
-
-TBSelectDropdown::~TBSelectDropdown() {
- getContentRoot()->removeChild(&m_arrow);
- setSource(nullptr);
- closeWindow();
-}
-
-void TBSelectDropdown::onSourceChanged() {
- m_value = -1;
- if ((m_source != nullptr) && (m_source->getNumItems() != 0)) {
- setValue(0);
- }
-}
-
-void TBSelectDropdown::onItemChanged(int index) {
-}
-
-void TBSelectDropdown::setValue(int value) {
- if (value == m_value || (m_source == nullptr)) {
- return;
- }
- m_value = value;
-
- if (m_value < 0) {
- setText("");
- } else if (m_value < m_source->getNumItems()) {
- setText(m_source->getItemString(m_value));
- }
-
- TBWidgetEvent ev(EVENT_TYPE_CHANGED);
- invokeEvent(ev);
-}
-
-TBID TBSelectDropdown::getSelectedItemID() const {
- if ((m_source != nullptr) && m_value >= 0 && m_value < m_source->getNumItems()) {
- return m_source->getItemID(m_value);
- }
- return TBID();
-}
-
-void TBSelectDropdown::openWindow() {
- if ((m_source == nullptr) || (m_source->getNumItems() == 0) || (m_window_pointer.get() != nullptr)) {
- return;
- }
-
- if (TBMenuWindow *window = new TBMenuWindow(this, TBIDC("TBSelectDropdown.window"))) {
- m_window_pointer.set(window);
- window->setSkinBg(TBIDC("TBSelectDropdown.window"));
- window->show(m_source, TBPopupAlignment(), getValue());
- }
-}
-
-void TBSelectDropdown::closeWindow() {
- if (TBMenuWindow *window = getMenuIfOpen()) {
- window->close();
- }
-}
-
-TBMenuWindow *TBSelectDropdown::getMenuIfOpen() const {
- return TBSafeCast(m_window_pointer.get());
-}
-
-bool TBSelectDropdown::onEvent(const TBWidgetEvent &ev) {
- if (ev.target == this && ev.type == EVENT_TYPE_CLICK) {
- // Open the menu, or set the value and close it if already open (this will
- // happen when clicking by keyboard since that will call click on this button)
- if (TBMenuWindow *menu_window = getMenuIfOpen()) {
- TBWidgetSafePointer tmp(this);
- int value = menu_window->getList()->getValue();
- menu_window->die();
- if (tmp.get() != nullptr) {
- setValue(value);
- }
- } else {
- openWindow();
- }
- return true;
- }
- if (ev.target->getID() == TBIDC("TBSelectDropdown.window") && ev.type == EVENT_TYPE_CLICK) {
- // Set the value of the clicked item
- if (TBMenuWindow *menu_window = getMenuIfOpen()) {
- setValue(menu_window->getList()->getValue());
- }
- return true;
- }
- if (ev.target == this && (m_source != nullptr) && ev.isKeyEvent()) {
- if (TBMenuWindow *menu_window = getMenuIfOpen()) {
- // Redirect the key strokes to the list
- TBWidgetEvent redirected_ev(ev);
- return menu_window->getList()->invokeEvent(redirected_ev);
- }
- }
- return false;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_select.h b/src/modules/ui/turbobadger/tb/tb_select.h
deleted file mode 100644
index d7a70abe1..000000000
--- a/src/modules/ui/turbobadger/tb/tb_select.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_scroll_container.h"
-#include "tb_select_item.h"
-#include "tb_window.h"
-
-namespace tb {
-
-class TBMenuWindow;
-
-/** TBSelectList shows a scrollable list of items provided by a TBSelectItemSource. */
-
-class TBSelectList : public TBWidget, public TBSelectItemViewer {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBSelectList, TBWidget);
-
- TBSelectList();
- ~TBSelectList();
-
- /** Get the default item source for this widget. This source can be used to add
- items of type TBGenericStringItem to this widget.
- It is the item source that is fed from resource files.
-
- If you need to add other types of items, or if you want to share item sources
- between several TBSelectDropDown/TBSelectList widgets, use SetSource using a
- external item source. */
- TBGenericStringItemSource *getDefaultSource() {
- return &m_default_source;
- }
-
- /** Set filter string so only matching items will be showed.
- Set nullptr or empty string to remove filter and show all items. */
- void setFilter(const core::String& filter) {
- setFilter(filter.c_str());
- }
- void setFilter(const char *filter);
- const char *getFilter() const {
- return m_filter.c_str();
- }
-
- /** Set the language string id for the header. The header is shown
- at the top of the list when only a subset of all items are shown. */
- void setHeaderString(const TBID &id);
-
- /** Make the list update its items to reflect the items from the
- in the current source. The update will take place next time
- the list is validated. */
- void invalidateList();
-
- /** Make sure the list is reflecting the current items in the source. */
- void validateList();
-
- /** The value is the selected item. In lists with multiple selectable
- items it's the item that is the current focus. */
- virtual void setValue(int value) override;
- virtual int getValue() const override {
- return m_value;
- }
-
- /** Get the ID of the selected item, or 0 if there is no item selected. */
- TBID getSelectedItemID() const;
-
- /** Change the value to a non disabled item that is visible with the current
- filter. Returns true if it successfully found another item.
- Valid keys:
- TB_KEY_UP - Previous item.
- TB_KEY_DOWN - Next item.
- TB_KEY_HOME - First item.
- TB_KEY_END - Last item. */
- bool changeValue(SPECIAL_KEY key);
-
- /** Set the selected state of the item at the given index. If you want
- to unselect the previously selected item, use setValue. */
- void selectItem(int index, bool selected);
- TBWidget *getItemWidget(int index);
-
- /** Scroll to the current selected item. The scroll may be delayed until
- the items has been layouted if the layout is currently invalid. */
- void scrollToSelectedItem();
-
- /** Return the scrollcontainer used in this list. */
- TBScrollContainer *getScrollContainer() {
- return &m_container;
- }
-
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual void onSkinChanged() override;
- virtual void onProcess() override;
- virtual void onProcessAfterChildren() override;
- virtual bool onEvent(const TBWidgetEvent &ev) override;
-
- // == TBSelectItemViewer ==================================================
- virtual void onSourceChanged() override;
- virtual void onItemChanged(int index) override;
- virtual void onItemAdded(int index) override;
- virtual void onItemRemoved(int index) override;
- virtual void onAllItemsRemoved() override;
-
- inline void setSortCallback(int (*func)(TBSelectItemSource *source, const int *a, const int *b)) {
- _sortCallback = func;
- }
-
-protected:
- TBScrollContainer m_container;
- TBLayout m_layout;
- TBGenericStringItemSource m_default_source;
- int m_value;
- core::String m_filter;
- bool m_list_is_invalid;
- bool m_scroll_to_current;
- TBID m_header_lng_string_id;
-
- int (*_sortCallback)(TBSelectItemSource *source, const int *a, const int *b);
-
-private:
- TBWidget *createAndAddItemAfter(int index, TBWidget *reference);
-};
-
-/** TBSelectDropdown shows a button that opens a popup with a TBSelectList with items
- provided by a TBSelectItemSource. */
-
-class TBSelectDropdown : public TBButton, public TBSelectItemViewer {
-public:
- // For safe typecasting
- TBOBJECT_SUBCLASS(TBSelectDropdown, TBButton);
-
- TBSelectDropdown();
- ~TBSelectDropdown();
-
- /** Get the default item source for this widget. This source can be used to add
- items of type TBGenericStringItem to this widget.
- It is the item source that is fed from resource files.
-
- If you need to add other types of items, or if you want to share item sources
- between several TBSelectDropDown/TBSelectList widgets, use SetSource using a
- external item source. */
- TBGenericStringItemSource *getDefaultSource() {
- return &m_default_source;
- }
-
- /** Set the selected item. */
- virtual void setValue(int value) override;
- virtual int getValue() const override {
- return m_value;
- }
-
- /** Get the ID of the selected item, or 0 if there is no item selected. */
- TBID getSelectedItemID() const;
-
- /** Open the window if the model has items. */
- void openWindow();
-
- /** Close the window if it is open. */
- void closeWindow();
-
- /** Return the menu window if it's open, or nullptr. */
- TBMenuWindow *getMenuIfOpen() const;
-
- virtual void onInflate(const INFLATE_INFO &info) override;
- virtual bool onEvent(const TBWidgetEvent &ev) override;
-
- // == TBSelectItemViewer ==================================================
- virtual void onSourceChanged() override;
- virtual void onItemChanged(int index) override;
- virtual void onItemAdded(int index) override {
- }
- virtual void onItemRemoved(int index) override {
- }
- virtual void onAllItemsRemoved() override {
- }
-
-protected:
- TBGenericStringItemSource m_default_source;
- TBSkinImage m_arrow;
- int m_value;
- TBWidgetSafePointer m_window_pointer; ///< Points to the dropdown window if opened
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_select_item.cpp b/src/modules/ui/turbobadger/tb/tb_select_item.cpp
deleted file mode 100644
index 57293034f..000000000
--- a/src/modules/ui/turbobadger/tb/tb_select_item.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * @file
- */
-
-#include "core/Assert.h"
-#include "tb_language.h"
-#include "tb_menu_window.h"
-#include "tb_select.h"
-#include "tb_widgets_listener.h"
-#include
-
-namespace tb {
-
-/** TBSimpleLayoutItemWidget is a item containing a layout with the following:
- -TBSkinImage showing the item image.
- -TBTextField showing the item string.
- -TBSkinImage showing the arrow for items with a submenu.
- It also handles submenu events. */
-class TBSimpleLayoutItemWidget : public TBLayout, private TBWidgetListener {
-public:
- TBSimpleLayoutItemWidget(const TBID &image, TBSelectItemSource *source, const char *str);
- ~TBSimpleLayoutItemWidget();
- virtual bool onEvent(const TBWidgetEvent &ev);
-
-private:
- TBSelectItemSource *m_source;
- TBTextField m_textfield;
- TBSkinImage m_image;
- TBSkinImage m_image_arrow;
- TBMenuWindow *m_menu; ///< Points to the submenu window if opened
- virtual void onWidgetDelete(TBWidget *widget);
- void openSubMenu();
- void closeSubMenu();
-};
-
-TBSimpleLayoutItemWidget::TBSimpleLayoutItemWidget(const TBID &image, TBSelectItemSource *source, const char *str)
- : m_source(source), m_menu(nullptr) {
- setSkinBg(TBIDC("TBSelectItem"));
- setLayoutDistribution(LAYOUT_DISTRIBUTION_AVAILABLE);
- setPaintOverflowFadeout(false);
-
- if (image != 0U) {
- m_image.setSkinBg(image);
- m_image.setIgnoreInput(true);
- addChild(&m_image);
- }
-
- m_textfield.setText(str);
- m_textfield.setTextAlign(TB_TEXT_ALIGN_LEFT);
- m_textfield.setIgnoreInput(true);
- addChild(&m_textfield);
-
- if (source != nullptr) {
- m_image_arrow.setSkinBg(TBIDC("arrow.right"));
- m_image_arrow.setIgnoreInput(true);
- addChild(&m_image_arrow);
- }
-}
-
-TBSimpleLayoutItemWidget::~TBSimpleLayoutItemWidget() {
- m_image_arrow.removeFromParent();
- m_textfield.removeFromParent();
- m_image.removeFromParent();
- closeSubMenu();
-}
-
-bool TBSimpleLayoutItemWidget::onEvent(const TBWidgetEvent &ev) {
- if ((m_source != nullptr) && ev.type == EVENT_TYPE_CLICK && ev.target == this) {
- openSubMenu();
- return true;
- }
- return false;
-}
-
-void TBSimpleLayoutItemWidget::onWidgetDelete(TBWidget *widget) {
- core_assert(widget == m_menu);
- closeSubMenu();
-}
-
-void TBSimpleLayoutItemWidget::openSubMenu() {
- if (m_menu != nullptr) {
- return;
- }
-
- // Open a new menu window for the submenu with this widget as target
- m_menu = new TBMenuWindow(this, TBIDC("submenu"));
- if (m_menu != nullptr) {
- setState(WIDGET_STATE_SELECTED, true);
- m_menu->addListener(this);
- m_menu->show(m_source, TBPopupAlignment(TB_ALIGN_RIGHT), -1);
- }
-}
-
-void TBSimpleLayoutItemWidget::closeSubMenu() {
- if (m_menu == nullptr) {
- return;
- }
-
- setState(WIDGET_STATE_SELECTED, false);
- m_menu->removeListener(this);
- if (!m_menu->getIsDying()) {
- m_menu->close();
- }
- m_menu = nullptr;
-}
-
-void TBSelectItemViewer::setSource(TBSelectItemSource *source) {
- if (m_source == source) {
- return;
- }
-
- if (m_source != nullptr) {
- m_source->m_viewers.remove(this);
- }
- m_source = source;
- if (m_source != nullptr) {
- m_source->m_viewers.addLast(this);
- }
-
- onSourceChanged();
-}
-
-TBSelectItemSource::~TBSelectItemSource() {
- // If this core_assert trig, you are deleting a model that's still set on some
- // TBSelect widget. That might be dangerous.
- core_assert(!m_viewers.hasLinks());
-}
-
-bool TBSelectItemSource::filter(int index, const char *filter) {
- const char *str = getItemString(index);
- return (str != nullptr) && (stristr(str, filter) != nullptr);
-}
-
-TBWidget *TBSelectItemSource::createItemWidget(int index, TBSelectItemViewer *viewer) {
- const char *string = getItemString(index);
- TBSelectItemSource *sub_source = getItemSubSource(index);
- TBID image = getItemImage(index);
- if ((sub_source != nullptr) || (image != 0U)) {
- if (TBSimpleLayoutItemWidget *itemwidget = new TBSimpleLayoutItemWidget(image, sub_source, string)) {
- return itemwidget;
- }
- } else if ((string != nullptr) && *string == '-') {
- if (TBSeparator *separator = new TBSeparator) {
- separator->setGravity(WIDGET_GRAVITY_ALL);
- separator->setSkinBg(TBIDC("TBSelectItem.separator"));
- return separator;
- }
- } else if (TBTextField *textfield = new TBTextField) {
- textfield->setSkinBg("TBSelectItem");
- textfield->setText(string);
- textfield->setTextAlign(TB_TEXT_ALIGN_LEFT);
- return textfield;
- }
- return nullptr;
-}
-
-void TBSelectItemSource::invokeItemChanged(int index, TBSelectItemViewer *excludeViewer) {
- TBLinkListOf::Iterator iter = m_viewers.iterateForward();
- while (TBSelectItemViewer *viewer = iter.getAndStep()) {
- if (viewer != excludeViewer) {
- viewer->onItemChanged(index);
- }
- }
-}
-
-void TBSelectItemSource::invokeItemAdded(int index) {
- TBLinkListOf::Iterator iter = m_viewers.iterateForward();
- while (TBSelectItemViewer *viewer = iter.getAndStep()) {
- viewer->onItemAdded(index);
- }
-}
-
-void TBSelectItemSource::invokeItemRemoved(int index) {
- TBLinkListOf::Iterator iter = m_viewers.iterateForward();
- while (TBSelectItemViewer *viewer = iter.getAndStep()) {
- viewer->onItemRemoved(index);
- }
-}
-
-void TBSelectItemSource::invokeAllItemsRemoved() {
- TBLinkListOf::Iterator iter = m_viewers.iterateForward();
- while (TBSelectItemViewer *viewer = iter.getAndStep()) {
- viewer->onAllItemsRemoved();
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_select_item.h b/src/modules/ui/turbobadger/tb/tb_select_item.h
deleted file mode 100644
index edb7ef344..000000000
--- a/src/modules/ui/turbobadger/tb/tb_select_item.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "core/String.h"
-#include "tb_linklist.h"
-#include "tb_list.h"
-#include "tb_value.h"
-
-namespace tb {
-
-class TBSelectItemSource;
-
-enum TB_SORT {
- TB_SORT_NONE, ///< No sorting. Items appear in list order.
- TB_SORT_ASCENDING, ///< Ascending sort.
- TB_SORT_DESCENDING ///< Descending sort.
-};
-
-/** TBSelectItemViewer is the viewer for items provided by TBSelectItemSource.
- There can be multiple viewers for each source. The viewer will recieve
- callbacks when the source is changed, so it can update itself.
-*/
-class TBSelectItemViewer : public TBLinkOf {
-public:
- TBSelectItemViewer() : m_source(nullptr) {
- }
- virtual ~TBSelectItemViewer() {
- }
-
- /** Set the source which should provide the items for this viewer.
- This source needs to live longer than this viewer.
- Set nullptr to unset currently set source. */
- void setSource(TBSelectItemSource *source);
- TBSelectItemSource *getSource() const {
- return m_source;
- }
-
- /** Called when the source has changed or been unset by calling SetSource. */
- virtual void onSourceChanged() = 0;
-
- /** Called when the item at the given index has changed in a way that should
- update the viewer. */
- virtual void onItemChanged(int index) = 0;
-
- /** Called when the item at the given index has been added. */
- virtual void onItemAdded(int index) = 0;
-
- /** Called when the item at the given index has been removed. */
- virtual void onItemRemoved(int index) = 0;
-
- /** Called when all items have been removed. */
- virtual void onAllItemsRemoved() = 0;
-
-protected:
- TBSelectItemSource *m_source;
-};
-
-/** TBSelectItemSource is a item provider interface for list widgets (TBSelectList and
- TBSelectDropdown).
-
- Instead of feeding all list widgets with all items all the time, the list widgets
- will ask TBSelectItemSource when it needs it. The list widgets may also apply
- filtering so only a subset of all the items are shown.
-
- CreateItemWidget can be overridden to create any set of widget content for each item.
-
- This class has no storage of items. If you want an array storage of items,
- use the subclass TBSelectItemSourceList. If you implement your own storage,
- remember to call InvokeItem[Added/...] to notify viewers that they need to update.
-*/
-class TBSelectItemSource {
-public:
- TBSelectItemSource() : m_sort(TB_SORT_NONE) {
- }
- virtual ~TBSelectItemSource();
-
- /** Return true if an item matches the given filter text.
- By default, it returns true if GetItemString contains filter. */
- virtual bool filter(int index, const char *filter);
-
- bool filter(int index, const core::String& filterStr) {
- return filter(index, filterStr.c_str());
- }
-
- /** Get the string of an item. If an item has more than one string,
- return the one that should be used for inline-find (pressing keys
- in the list will scroll to the item starting with the same letters),
- and for sorting the list. */
- virtual const char *getItemString(int index) const = 0;
-
- /** Get the source to be used if this item should open a sub menu. */
- virtual TBSelectItemSource *getItemSubSource(int index) {
- return nullptr;
- }
-
- /** Get the skin image to be painted before the text for this item. */
- virtual TBID getItemImage(int /*index*/) const {
- return TBID();
- }
-
- /** Get the id of the item. */
- virtual TBID getItemID(int /*index*/) const {
- return TBID();
- }
-
- /** Create the item representation widget(s). By default, it will create
- a TBTextField for string-only items, and other types for items that
- also has image or submenu. */
- virtual TBWidget *createItemWidget(int index, TBSelectItemViewer *viewer);
-
- /** Get the number of items */
- virtual int getNumItems() const = 0;
-
- /** Set sort type. Default is TB_SORT_NONE. */
- void setSort(TB_SORT sort) {
- m_sort = sort;
- }
- TB_SORT getSort() const {
- return m_sort;
- }
-
- /** Invoke onItemChanged on all open viewers for this source. */
- void invokeItemChanged(int index, TBSelectItemViewer *exclude_viewer = nullptr);
- void invokeItemAdded(int index);
- void invokeItemRemoved(int index);
- void invokeAllItemsRemoved();
-
-private:
- friend class TBSelectItemViewer;
- TBLinkListOf m_viewers;
- TB_SORT m_sort;
-};
-
-/** TBSelectItemSourceList is an item provider for list widgets (TBSelectList and
- TBSelectDropdown). It stores items of the type specified by the template in an array. */
-template class TBSelectItemSourceList : public TBSelectItemSource {
-public:
- TBSelectItemSourceList() {
- }
- virtual ~TBSelectItemSourceList() {
- deleteAllItems();
- }
- virtual const char *getItemString(int index) const {
- return getItem(index)->str.c_str();
- }
- virtual TBSelectItemSource *getItemSubSource(int index) {
- return getItem(index)->sub_source;
- }
- virtual TBID getItemImage(int index) const {
- return getItem(index)->skin_image;
- }
- virtual TBID getItemID(int index) const {
- return getItem(index)->id;
- }
- virtual int getNumItems() const {
- return m_items.getNumItems();
- }
- virtual TBWidget *createItemWidget(int index, TBSelectItemViewer *viewer) {
- if (TBWidget *widget = TBSelectItemSource::createItemWidget(index, viewer)) {
- T *item = m_items[index];
- widget->setID(item->id);
- return widget;
- }
- return nullptr;
- }
-
- inline int getItemIndex(const T *item) const {
- return m_items.find(item);
- }
-
- inline bool isFirst(const T *item) const {
- const int idx = getItemIndex(item);
- return idx == 0;
- }
-
- inline bool isLast(const T *item) const {
- const int idx = getItemIndex(item);
- if (idx == -1) {
- return false;
- }
- return idx == getNumItems() - 1;
- }
-
- /** Add a new item at the given index. */
- bool addItem(T *item, int index) {
- if (m_items.add(item, index)) {
- invokeItemAdded(index);
- return true;
- }
- return false;
- }
-
- /** Add a new item last. */
- bool addItem(T *item) {
- return addItem(item, m_items.getNumItems());
- }
-
- void swap(int idx1, int idx2, TBSelectItemViewer *exclude_viewer = nullptr) {
- m_items.swap(idx1, idx2);
- invokeItemChanged(idx1, exclude_viewer);
- invokeItemChanged(idx2, exclude_viewer);
- }
-
- /** Get the item at the given index. */
- T *getItem(int index) const {
- return m_items[index];
- }
-
- /** Delete the item at the given index. */
- void deleteItem(int index) {
- if (!m_items.getNumItems()) {
- return;
- }
- m_items.doDelete(index);
- invokeItemRemoved(index);
- }
-
- /** Delete all items. */
- void deleteAllItems() {
- if (!m_items.getNumItems()) {
- return;
- }
- m_items.deleteAll();
- invokeAllItemsRemoved();
- }
-
-private:
- TBListOf m_items;
-};
-
-/** TBGenericStringItem item for TBGenericStringItemSource.
- It has a string and may have a skin image and sub item source. */
-class TBGenericStringItem {
-public:
- TBGenericStringItem(const TBGenericStringItem &other)
- : str(other.str), id(other.id), sub_source(other.sub_source), tag(other.tag) {
- }
- TBGenericStringItem(const char *str) : str(str), sub_source(nullptr) {
- }
- TBGenericStringItem(const char *str, TBID id) : str(str), id(id), sub_source(nullptr) {
- }
- TBGenericStringItem(const char *str, TBSelectItemSource *subSource) : str(str), sub_source(subSource) {
- }
- const TBGenericStringItem &operator=(const TBGenericStringItem &other) {
- str = other.str;
- id = other.id;
- sub_source = other.sub_source;
- tag = other.tag;
- return *this;
- }
-
- void setSkinImage(const TBID &image) {
- skin_image = image;
- }
-
-public:
- core::String str;
- TBID id;
- TBID skin_image;
- TBSelectItemSource *sub_source;
-
- /** This value is free to use for anything. It's not used internally. */
- TBValue tag;
-};
-
-/** TBGenericStringItemSource is an item source list providing items of type TBGenericStringItem. */
-
-class TBGenericStringItemSource : public TBSelectItemSourceList {};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_skin.cpp b/src/modules/ui/turbobadger/tb/tb_skin.cpp
deleted file mode 100644
index 0e3e0dfd5..000000000
--- a/src/modules/ui/turbobadger/tb/tb_skin.cpp
+++ /dev/null
@@ -1,899 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_skin.h"
-#include "core/Assert.h"
-#include "core/Log.h"
-#include "tb_node_tree.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-
-namespace tb {
-
-// == Util functions ==========================================================
-
-/*TB_TEXT_ALIGN StringToTextAlign(const char *align_str)
-{
- TB_TEXT_ALIGN align = TB_TEXT_ALIGN_CENTER;
- if (SDL_strstr(state_str, "left")) align = TB_TEXT_ALIGN_LEFT;
- if (SDL_strstr(state_str, "center")) align = TB_TEXT_ALIGN_CENTER;
- if (SDL_strstr(state_str, "right")) align = TB_TEXT_ALIGN_RIGHT;
- return state;
-}*/
-
-SKIN_STATE stringToState(const char *stateStr) {
- SKIN_STATE state = SKIN_STATE_NONE;
- if (SDL_strstr(stateStr, "all")) {
- state |= SKIN_STATE_ALL;
- }
- if (SDL_strstr(stateStr, "disabled")) {
- state |= SKIN_STATE_DISABLED;
- }
- if (SDL_strstr(stateStr, "focused")) {
- state |= SKIN_STATE_FOCUSED;
- }
- if (SDL_strstr(stateStr, "pressed")) {
- state |= SKIN_STATE_PRESSED;
- }
- if (SDL_strstr(stateStr, "selected")) {
- state |= SKIN_STATE_SELECTED;
- }
- if (SDL_strstr(stateStr, "hovered")) {
- state |= SKIN_STATE_HOVERED;
- }
- return state;
-}
-
-SKIN_ELEMENT_TYPE stringToType(const char *typeStr) {
- if (SDL_strcmp(typeStr, "StretchBox") == 0) {
- return SKIN_ELEMENT_TYPE_STRETCH_BOX;
- }
- if (SDL_strcmp(typeStr, "Image") == 0) {
- return SKIN_ELEMENT_TYPE_IMAGE;
- }
- if (SDL_strcmp(typeStr, "Stretch Image") == 0) {
- return SKIN_ELEMENT_TYPE_STRETCH_IMAGE;
- }
- if (SDL_strcmp(typeStr, "Tile") == 0) {
- return SKIN_ELEMENT_TYPE_TILE;
- }
- if (SDL_strcmp(typeStr, "StretchBorder") == 0) {
- return SKIN_ELEMENT_TYPE_STRETCH_BORDER;
- }
- Log::debug("Skin error: Unknown skin type!");
- return SKIN_ELEMENT_TYPE_STRETCH_BOX;
-}
-
-TBSkinCondition::TARGET stringToTarget(const char *targetStr) {
- if (SDL_strcmp(targetStr, "this") == 0) {
- return TBSkinCondition::TARGET_THIS;
- }
- if (SDL_strcmp(targetStr, "parent") == 0) {
- return TBSkinCondition::TARGET_PARENT;
- }
- if (SDL_strcmp(targetStr, "ancestors") == 0) {
- return TBSkinCondition::TARGET_ANCESTORS;
- }
- if (SDL_strcmp(targetStr, "prev sibling") == 0) {
- return TBSkinCondition::TARGET_PREV_SIBLING;
- }
- if (SDL_strcmp(targetStr, "next sibling") == 0) {
- return TBSkinCondition::TARGET_NEXT_SIBLING;
- }
- Log::debug("Skin error: Unknown target in condition!");
- return TBSkinCondition::TARGET_THIS;
-}
-
-TBSkinCondition::PROPERTY stringToProperty(const char *propStr) {
- if (SDL_strcmp(propStr, "skin") == 0) {
- return TBSkinCondition::PROPERTY_SKIN;
- }
- if (SDL_strcmp(propStr, "window active") == 0) {
- return TBSkinCondition::PROPERTY_WINDOW_ACTIVE;
- }
- if (SDL_strcmp(propStr, "axis") == 0) {
- return TBSkinCondition::PROPERTY_AXIS;
- }
- if (SDL_strcmp(propStr, "align") == 0) {
- return TBSkinCondition::PROPERTY_ALIGN;
- }
- if (SDL_strcmp(propStr, "id") == 0) {
- return TBSkinCondition::PROPERTY_ID;
- }
- if (SDL_strcmp(propStr, "state") == 0) {
- return TBSkinCondition::PROPERTY_STATE;
- }
- if (SDL_strcmp(propStr, "value") == 0) {
- return TBSkinCondition::PROPERTY_VALUE;
- }
- if (SDL_strcmp(propStr, "hover") == 0) {
- return TBSkinCondition::PROPERTY_HOVER;
- }
- if (SDL_strcmp(propStr, "capture") == 0) {
- return TBSkinCondition::PROPERTY_CAPTURE;
- }
- if (SDL_strcmp(propStr, "focus") == 0) {
- return TBSkinCondition::PROPERTY_FOCUS;
- }
- return TBSkinCondition::PROPERTY_CUSTOM;
-}
-
-// == TBSkinCondition =======================================================
-
-TBSkinCondition::TBSkinCondition(TARGET target, PROPERTY prop, const TBID &customProp, const TBID &value, TEST test)
- : m_target(target), m_test(test) {
- m_info.prop = prop;
- m_info.custom_prop = customProp;
- m_info.value = value;
-}
-
-bool TBSkinCondition::getCondition(TBSkinConditionContext &context) const {
- const bool equal = context.getCondition(m_target, m_info);
- return equal == (m_test == TEST_EQUAL);
-}
-
-// == TBSkin ================================================================
-
-TBSkin::TBSkin()
- : m_listener(nullptr), m_color_frag(nullptr), m_default_disabled_opacity(0.3F), m_default_placeholder_opacity(0.2F),
- m_default_spacing(0) {
- g_renderer->addListener(this);
-
- // Avoid filtering artifacts at edges when we draw fragments stretched.
- m_frag_manager.setAddBorder(true);
-}
-
-bool TBSkin::load(const char *skinFile, const char *overrideSkinFile) {
- if (!loadInternal(skinFile)) {
- return false;
- }
- if ((overrideSkinFile != nullptr) && !loadInternal(overrideSkinFile)) {
- return false;
- }
- return reloadBitmaps();
-}
-
-bool TBSkin::loadInternal(const char *skinFile) {
- TBNode node;
- if (!node.readFile(skinFile)) {
- return false;
- }
-
- TBTempBuffer skin_path;
- if (!skin_path.appendPath(skinFile)) {
- return false;
- }
-
- if (node.getNode("description") != nullptr) {
- // Check which DPI mode the dimension converter should use.
- // The base-dpi is the dpi in which the padding, spacing (and so on)
- // is specified in. If the skin supports a different DPI that is
- // closer to the screen DPI, all such dimensions will be scaled.
- int base_dpi = node.getValueInt("description>base-dpi", 96);
- int supported_dpi = base_dpi;
- if (TBNode *supported_dpi_node = node.getNode("description>supported-dpi")) {
- core_assert(supported_dpi_node->getValue().isArray() ||
- supported_dpi_node->getValue().getInt() == base_dpi);
- if (TBValueArray *arr = supported_dpi_node->getValue().getArray()) {
- int screen_dpi = TBSystem::getDPI();
- int best_supported_dpi = 0;
- for (int i = 0; i < arr->getLength(); i++) {
- int candidate_dpi = arr->getValue(i)->getInt();
- if ((best_supported_dpi == 0) ||
- Abs(candidate_dpi - screen_dpi) < Abs(best_supported_dpi - screen_dpi)) {
- best_supported_dpi = candidate_dpi;
- }
- }
- supported_dpi = best_supported_dpi;
- }
- }
- m_dim_conv.setDPI(base_dpi, supported_dpi);
- }
-
- // Read skin constants
- if (const char *color = node.getValueString("defaults>text-color", nullptr)) {
- m_default_text_color.setFromString(color, SDL_strlen(color));
- }
- m_default_disabled_opacity = node.getValueFloat("defaults>disabled>opacity", m_default_disabled_opacity);
- m_default_placeholder_opacity = node.getValueFloat("defaults>placeholder>opacity", m_default_placeholder_opacity);
- m_default_spacing = getPxFromNode(node.getNode("defaults>spacing"), m_default_spacing);
-
- // Iterate through all elements nodes and add skin elements or patch already
- // existing elements.
- TBNode *elements = node.getNode("elements");
- if (elements != nullptr) {
- TBNode *n = elements->getFirstChild();
- while (n != nullptr) {
- // If we have a "clone" node, clone all children from that node
- // into this node.
- while (TBNode *clone = n->getNode("clone")) {
- n->remove(clone);
-
- TBNode *clone_source = elements->getNode(clone->getValue().getString());
- if (clone_source != nullptr) {
- n->cloneChildren(clone_source);
- }
-
- delete clone;
- }
-
- // If the skin element already exist, we will call Load on it again.
- // This will patch the element with any new data from the node.
- TBID element_id(n->getName());
- TBSkinElement *e = getSkinElement(element_id);
- if (e == nullptr) {
- e = new TBSkinElement;
- if (e == nullptr) {
- return false;
- }
- m_elements.add(element_id, e);
- }
-
- e->load(n, this, skin_path.getData());
- if (m_listener != nullptr) {
- m_listener->onSkinElementLoaded(this, e, n);
- }
-
- n = n->getNext();
- }
- }
- return true;
-}
-
-void TBSkin::unloadBitmaps() {
- // Unset all bitmap pointers.
- TBHashTableIteratorOf it(&m_elements);
- while (TBSkinElement *element = it.getNextContent()) {
- element->bitmap = nullptr;
- }
-
- // Clear all fragments and bitmaps.
- m_frag_manager.clear();
- m_color_frag = nullptr;
-}
-
-bool TBSkin::reloadBitmaps() {
- unloadBitmaps();
- bool success = reloadBitmapsInternal();
- // Create all bitmaps for the bitmap fragment maps
- if (success) {
- success = m_frag_manager.validateBitmaps();
- }
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- Log::debug("Skin loaded using %d bitmaps.", m_frag_manager.getNumMaps());
-#endif
- return success;
-}
-
-bool TBSkin::reloadBitmapsInternal() {
- // Load all bitmap files into new bitmap fragments.
- TBTempBuffer filename_dst_DPI;
- bool success = true;
- TBHashTableIteratorOf it(&m_elements);
- while (TBSkinElement *element = it.getNextContent()) {
- if (!element->bitmap_file.empty()) {
- core_assert(!element->bitmap);
-
- // FIX: dedicated_map is not needed for all backends (only deprecated fixed function GL)
- bool dedicated_map = element->type == SKIN_ELEMENT_TYPE_TILE;
-
- // Try to load bitmap fragment in the destination DPI (F.ex "foo.png" becomes "foo@192.png")
- int bitmap_dpi = m_dim_conv.getSrcDPI();
- if (m_dim_conv.needConversion()) {
- m_dim_conv.getDstDPIFilename(element->bitmap_file.c_str(), &filename_dst_DPI);
- element->bitmap = m_frag_manager.getFragmentFromFile(filename_dst_DPI.getData(), dedicated_map);
- if (element->bitmap != nullptr) {
- bitmap_dpi = m_dim_conv.getDstDPI();
- }
- }
- element->setBitmapDPI(m_dim_conv, bitmap_dpi);
-
- // If we still have no bitmap fragment, load from default file.
- if (element->bitmap == nullptr) {
- element->bitmap = m_frag_manager.getFragmentFromFile(element->bitmap_file.c_str(), dedicated_map);
- }
-
- if (element->bitmap == nullptr) {
- success = false;
- }
- }
- }
- // Create fragment used for color fills. Use 2x2px and inset source rect to center 0x0
- // to avoid filtering artifacts.
- uint32_t data[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
- m_color_frag = m_frag_manager.createNewFragment(TBID((uint32_t)0), false, 2, 2, 2, data);
- if (m_color_frag == nullptr) {
- return false;
- }
- m_color_frag->m_rect = m_color_frag->m_rect.shrink(1, 1);
- return success;
-}
-
-TBSkin::~TBSkin() {
- g_renderer->removeListener(this);
-}
-
-TBSkinElement *TBSkin::getSkinElement(const TBID &skinId) const {
- if (skinId == 0U) {
- return nullptr;
- }
- return m_elements.get(skinId);
-}
-
-TBSkinElement *TBSkin::getSkinElementStrongOverride(const TBID &skinId, SKIN_STATE state,
- TBSkinConditionContext &context) const {
- if (TBSkinElement *skin_element = getSkinElement(skinId)) {
- // Avoid eternal recursion when overrides refer to elements referring back.
- if (skin_element->is_getting) {
- return nullptr;
- }
- skin_element->is_getting = true;
-
- // Check if there's any strong overrides for this element with the given state.
- TBSkinElementState *override_state = skin_element->m_strong_override_elements.getStateElement(state, context);
- if (override_state != nullptr) {
- if (TBSkinElement *override_element =
- getSkinElementStrongOverride(override_state->element_id, state, context)) {
- skin_element->is_getting = false;
- return override_element;
- }
- }
-
- skin_element->is_getting = false;
- return skin_element;
- }
- return nullptr;
-}
-
-TBSkinElement *TBSkin::paintSkin(const TBRect &dstRect, const TBID &skinId, SKIN_STATE state,
- TBSkinConditionContext &context) {
- return paintSkin(dstRect, getSkinElement(skinId), state, context);
-}
-
-TBSkinElement *TBSkin::paintSkin(const TBRect &dstRect, TBSkinElement *element, SKIN_STATE state,
- TBSkinConditionContext &context) {
- if ((element == nullptr) || element->is_painting) {
- return nullptr;
- }
-
- // Avoid potential endless recursion in evil skins
- element->is_painting = true;
-
- // Return the override if we have one.
- TBSkinElement *return_element = element;
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- bool paint_error_highlight = false;
-#endif
-
- // If there's any override for this state, paint it.
- TBSkinElementState *override_state = element->m_override_elements.getStateElement(state, context);
- if (override_state != nullptr) {
- if (TBSkinElement *used_override = paintSkin(dstRect, override_state->element_id, state, context)) {
- return_element = used_override;
- } else {
-#ifdef TB_RUNTIME_DEBUG_INFO
- paint_error_highlight = true;
-#endif
- Log::debug("Skin error: The skin references a missing element, or has a reference loop!");
- // Fall back to the standard skin.
- override_state = nullptr;
- }
- }
-
- // If there was no override, paint the standard skin element.
- if (override_state == nullptr) {
- paintElement(dstRect, element);
- }
-
- // Paint all child elements that match the state (or should be painted for all states)
- if (element->m_child_elements.hasStateElements()) {
- const TBSkinElementState *state_element = element->m_child_elements.getFirstElement();
- while (state_element != nullptr) {
- if (state_element->isMatch(state, context)) {
- paintSkin(dstRect, state_element->element_id, state_element->state & state, context);
- }
- state_element = state_element->getNext();
- }
- }
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- // Paint ugly rectangles on invalid skin elements in debug builds.
- if (paint_error_highlight) {
- g_tb_skin->paintRect(dstRect.expand(1, 1), TBColor(255, 205, 0), 1);
- }
- if (paint_error_highlight) {
- g_tb_skin->paintRect(dstRect.shrink(1, 1), TBColor(255, 0, 0), 1);
- }
-#endif
-
- element->is_painting = false;
- return return_element;
-}
-
-void TBSkin::paintSkinOverlay(const TBRect &dstRect, TBSkinElement *element, SKIN_STATE state,
- TBSkinConditionContext &context) {
- if ((element == nullptr) || element->is_painting) {
- return;
- }
-
- // Avoid potential endless recursion in evil skins
- element->is_painting = true;
-
- // Paint all overlay elements that matches the state (or should be painted for all states)
- const TBSkinElementState *state_element = element->m_overlay_elements.getFirstElement();
- while (state_element != nullptr) {
- if (state_element->isMatch(state, context)) {
- paintSkin(dstRect, state_element->element_id, state_element->state & state, context);
- }
- state_element = state_element->getNext();
- }
-
- element->is_painting = false;
-}
-
-void TBSkin::paintElement(const TBRect &dstRect, TBSkinElement *element) {
- paintElementBGColor(dstRect, element);
- if (element->bitmap == nullptr) {
- return;
- }
- if (element->type == SKIN_ELEMENT_TYPE_IMAGE) {
- paintElementImage(dstRect, element);
- } else if (element->type == SKIN_ELEMENT_TYPE_TILE) {
- paintElementTile(dstRect, element);
- } else if (element->type == SKIN_ELEMENT_TYPE_STRETCH_IMAGE || element->cut == 0) {
- paintElementStretchImage(dstRect, element);
- } else if (element->type == SKIN_ELEMENT_TYPE_STRETCH_BORDER) {
- paintElementStretchBox(dstRect, element, false);
- } else {
- paintElementStretchBox(dstRect, element, true);
- }
-}
-
-TBRect TBSkin::getFlippedRect(const TBRect &srcRect, TBSkinElement *element) const {
- // Turning the source rect "inside out" will flip the result when rendered.
- TBRect tmp_rect = srcRect;
- if (element->flip_x != 0) {
- tmp_rect.x += tmp_rect.w;
- tmp_rect.w = -tmp_rect.w;
- }
- if (element->flip_y != 0) {
- tmp_rect.y += tmp_rect.h;
- tmp_rect.h = -tmp_rect.h;
- }
- return tmp_rect;
-}
-
-void TBSkin::paintRect(const TBRect &dstRect, const TBColor &color, int thickness) {
- if (dstRect.w < thickness * 2 || dstRect.h < thickness * 2) {
- paintRectFill(dstRect, color);
- return;
- }
- // Top
- paintRectFill(TBRect(dstRect.x, dstRect.y, dstRect.w, thickness), color);
- // Bottom
- paintRectFill(TBRect(dstRect.x, dstRect.y + dstRect.h - thickness, dstRect.w, thickness), color);
- // Left
- paintRectFill(TBRect(dstRect.x, dstRect.y + thickness, thickness, dstRect.h - thickness * 2), color);
- // Right
- paintRectFill(
- TBRect(dstRect.x + dstRect.w - thickness, dstRect.y + thickness, thickness, dstRect.h - thickness * 2), color);
-}
-
-void TBSkin::paintRectFill(const TBRect &dstRect, const TBColor &color) {
- if (!dstRect.isEmpty()) {
- g_renderer->drawBitmapColored(dstRect, TBRect(), color, m_color_frag);
- }
-}
-
-void TBSkin::paintElementBGColor(const TBRect &dstRect, TBSkinElement *element) {
- if (element->bg_color == 0) {
- return;
- }
- paintRectFill(dstRect, element->bg_color);
-}
-
-void TBSkin::paintElementImage(const TBRect &dstRect, TBSkinElement *element) {
- const TBRect src_rect(0, 0, element->bitmap->width(), element->bitmap->height());
- TBRect rect = dstRect.expand(element->expand, element->expand);
- rect.set(rect.x + element->img_ofs_x + (rect.w - src_rect.w) * element->img_position_x / 100,
- rect.y + element->img_ofs_y + (rect.h - src_rect.h) * element->img_position_y / 100, src_rect.w,
- src_rect.h);
- g_renderer->drawBitmap(rect, getFlippedRect(src_rect, element), element->bitmap);
-}
-
-void TBSkin::paintElementTile(const TBRect &dstRect, TBSkinElement *element) {
- const TBRect &rect = dstRect.expand(element->expand, element->expand);
- g_renderer->drawBitmapTile(rect, element->bitmap->getBitmap(TB_VALIDATE_ALWAYS));
-}
-
-void TBSkin::paintElementStretchImage(const TBRect &dstRect, TBSkinElement *element) {
- if (dstRect.isEmpty()) {
- return;
- }
- const TBRect &rect = dstRect.expand(element->expand, element->expand);
- const TBRect &src_rect = getFlippedRect(TBRect(0, 0, element->bitmap->width(), element->bitmap->height()), element);
- g_renderer->drawBitmap(rect, src_rect, element->bitmap);
-}
-
-void TBSkin::paintElementStretchBox(const TBRect &dstRect, TBSkinElement *element, bool fillCenter) {
- if (dstRect.isEmpty()) {
- return;
- }
-
- TBRect rect = dstRect.expand(element->expand, element->expand);
-
- // Stretch the dst_cut (if rect is smaller than the skin size)
- // FIX: the expand should also be stretched!
- const int cut = element->cut;
- int dst_cut_w = Min(cut, rect.w / 2);
- int dst_cut_h = Min(cut, rect.h / 2);
- const int bw = element->bitmap->width();
- const int bh = element->bitmap->height();
-
- const bool has_left_right_edges = rect.h > dst_cut_h * 2;
- const bool has_top_bottom_edges = rect.w > dst_cut_w * 2;
-
- rect = getFlippedRect(rect, element);
- if (element->flip_x != 0) {
- dst_cut_w = -dst_cut_w;
- }
- if (element->flip_y != 0) {
- dst_cut_h = -dst_cut_h;
- }
-
- // Corners
- g_renderer->drawBitmap(TBRect(rect.x, rect.y, dst_cut_w, dst_cut_h), TBRect(0, 0, cut, cut), element->bitmap);
- g_renderer->drawBitmap(TBRect(rect.x + rect.w - dst_cut_w, rect.y, dst_cut_w, dst_cut_h),
- TBRect(bw - cut, 0, cut, cut), element->bitmap);
- g_renderer->drawBitmap(TBRect(rect.x, rect.y + rect.h - dst_cut_h, dst_cut_w, dst_cut_h),
- TBRect(0, bh - cut, cut, cut), element->bitmap);
- g_renderer->drawBitmap(TBRect(rect.x + rect.w - dst_cut_w, rect.y + rect.h - dst_cut_h, dst_cut_w, dst_cut_h),
- TBRect(bw - cut, bh - cut, cut, cut), element->bitmap);
-
- // Left & right edge
- if (has_left_right_edges) {
- g_renderer->drawBitmap(TBRect(rect.x, rect.y + dst_cut_h, dst_cut_w, rect.h - dst_cut_h * 2),
- TBRect(0, cut, cut, bh - cut * 2), element->bitmap);
- g_renderer->drawBitmap(
- TBRect(rect.x + rect.w - dst_cut_w, rect.y + dst_cut_h, dst_cut_w, rect.h - dst_cut_h * 2),
- TBRect(bw - cut, cut, cut, bh - cut * 2), element->bitmap);
- }
-
- // Top & bottom edge
- if (has_top_bottom_edges) {
- g_renderer->drawBitmap(TBRect(rect.x + dst_cut_w, rect.y, rect.w - dst_cut_w * 2, dst_cut_h),
- TBRect(cut, 0, bw - cut * 2, cut), element->bitmap);
- g_renderer->drawBitmap(
- TBRect(rect.x + dst_cut_w, rect.y + rect.h - dst_cut_h, rect.w - dst_cut_w * 2, dst_cut_h),
- TBRect(cut, bh - cut, bw - cut * 2, cut), element->bitmap);
- }
-
- // Center
- if (fillCenter && has_top_bottom_edges && has_left_right_edges) {
- g_renderer->drawBitmap(
- TBRect(rect.x + dst_cut_w, rect.y + dst_cut_h, rect.w - dst_cut_w * 2, rect.h - dst_cut_h * 2),
- TBRect(cut, cut, bw - cut * 2, bh - cut * 2), element->bitmap);
- }
-}
-
-#ifdef TB_RUNTIME_DEBUG_INFO
-void TBSkin::debug() {
- m_frag_manager.debug();
-}
-#endif // TB_RUNTIME_DEBUG_INFO
-
-void TBSkin::onContextLost() {
- // We could simply do: m_frag_manager.DeleteBitmaps() and then all bitmaps
- // would be recreated automatically when needed. But because it's easy,
- // we unload everything so we save some memory (by not keeping any image
- // data around).
- unloadBitmaps();
-}
-
-void TBSkin::onContextRestored() {
- // Reload bitmaps (since we unloaded everything in OnContextLost())
- reloadBitmaps();
-}
-
-int TBSkin::getPxFromNode(TBNode *node, int defValue) const {
- return node != nullptr ? m_dim_conv.getPxFromValue(&node->getValue(), defValue) : defValue;
-}
-
-// == TBSkinElement =========================================================
-
-TBSkinElement::TBSkinElement()
- : bitmap(nullptr), cut(0), expand(0), type(SKIN_ELEMENT_TYPE_STRETCH_BOX), is_painting(false), is_getting(false),
- padding_left(0), padding_top(0), padding_right(0), padding_bottom(0), width(SKIN_VALUE_NOT_SPECIFIED),
- height(SKIN_VALUE_NOT_SPECIFIED), pref_width(SKIN_VALUE_NOT_SPECIFIED), pref_height(SKIN_VALUE_NOT_SPECIFIED),
- min_width(SKIN_VALUE_NOT_SPECIFIED), min_height(SKIN_VALUE_NOT_SPECIFIED), max_width(SKIN_VALUE_NOT_SPECIFIED),
- max_height(SKIN_VALUE_NOT_SPECIFIED), spacing(SKIN_VALUE_NOT_SPECIFIED), content_ofs_x(0), content_ofs_y(0),
- img_ofs_x(0), img_ofs_y(0), img_position_x(50), img_position_y(50), flip_x(0), flip_y(0), opacity(1.F),
- text_color(0, 0, 0, 0), bg_color(0, 0, 0, 0), bitmap_dpi(0) {
-}
-
-TBSkinElement::~TBSkinElement() {
-}
-
-int TBSkinElement::getIntrinsicMinWidth() const {
- if ((bitmap != nullptr) && type == SKIN_ELEMENT_TYPE_IMAGE) {
- return bitmap->width() - expand * 2;
- }
- // Sizes below the skin cut size would start to shrink the skin below pretty,
- // so assume that's the default minimum size if it's not specified (minus expansion)
- return cut * 2 - expand * 2;
-}
-
-int TBSkinElement::getIntrinsicMinHeight() const {
- if ((bitmap != nullptr) && type == SKIN_ELEMENT_TYPE_IMAGE) {
- return bitmap->height() - expand * 2;
- }
- // Sizes below the skin cut size would start to shrink the skin below pretty,
- // so assume that's the default minimum size if it's not specified (minus expansion)
- return cut * 2 - expand * 2;
-}
-
-int TBSkinElement::getIntrinsicWidth() const {
- if (width != SKIN_VALUE_NOT_SPECIFIED) {
- return width;
- }
- if (bitmap != nullptr) {
- return bitmap->width() - expand * 2;
- }
- // FIX: We may want to check child elements etc.
- return SKIN_VALUE_NOT_SPECIFIED;
-}
-
-int TBSkinElement::getIntrinsicHeight() const {
- if (height != SKIN_VALUE_NOT_SPECIFIED) {
- return height;
- }
- if (bitmap != nullptr) {
- return bitmap->height() - expand * 2;
- }
- // FIX: We may want to check child elements etc.
- return SKIN_VALUE_NOT_SPECIFIED;
-}
-
-void TBSkinElement::setBitmapDPI(const TBDimensionConverter &dimConv, int bitmapDpi) {
- if (this->bitmap_dpi != 0) {
- // We have already applied the modifications so abort. This may
- // happen when we reload bitmaps without reloading the skin.
- return;
- }
- if (dimConv.needConversion()) {
- if (bitmapDpi == dimConv.getDstDPI()) {
- // The bitmap was loaded in a different DPI than the base DPI so
- // we must scale the bitmap properties.
- expand = expand * dimConv.getDstDPI() / dimConv.getSrcDPI();
- cut = cut * dimConv.getDstDPI() / dimConv.getSrcDPI();
- } else {
- // The bitmap was loaded in the base DPI and we need to scale it.
- // Apply the DPI conversion to the skin element scale factor.
- // FIX: For this to work well, we would need to apply scale to both
- // image and all the other types of drawing too.
- // scale_x = scale_x * dim_conv.getDstDPI() / dim_conv.getSrcDPI();
- // scale_y = scale_y * dim_conv.getDstDPI() / dim_conv.getSrcDPI();
- }
- }
- this->bitmap_dpi = bitmapDpi;
-}
-
-bool TBSkinElement::hasState(SKIN_STATE state, TBSkinConditionContext &context) {
- return (m_override_elements.getStateElement(state, context, TBSkinElementState::MATCH_RULE_ONLY_SPECIFIC_STATE) !=
- nullptr) ||
- (m_child_elements.getStateElement(state, context, TBSkinElementState::MATCH_RULE_ONLY_SPECIFIC_STATE) !=
- nullptr) ||
- (m_overlay_elements.getStateElement(state, context, TBSkinElementState::MATCH_RULE_ONLY_SPECIFIC_STATE) !=
- nullptr);
-}
-
-void TBSkinElement::load(TBNode *n, TBSkin *skin, const char *skinPath) {
- if (const char *bitmap = n->getValueString("bitmap", nullptr)) {
- bitmap_file.clear();
- bitmap_file.append(skinPath);
- bitmap_file.append(bitmap);
- }
-
- // Note: Always read cut and expand as pixels. These values might later be
- // recalculated depending on the DPI the bitmaps are available in.
- cut = n->getValueInt("cut", cut);
- expand = n->getValueInt("expand", expand);
- bitmap_dpi = 0;
-
- name = n->getName();
- id.set(n->getName());
-
- const TBDimensionConverter *dim_conv = skin->getDimensionConverter();
-
- if (TBNode *padding_node = n->getNode("padding")) {
- TBValue &val = padding_node->getValue();
- if (val.getArrayLength() == 4) {
- padding_top = dim_conv->getPxFromValue(val.getArray()->getValue(0), 0);
- padding_right = dim_conv->getPxFromValue(val.getArray()->getValue(1), 0);
- padding_bottom = dim_conv->getPxFromValue(val.getArray()->getValue(2), 0);
- padding_left = dim_conv->getPxFromValue(val.getArray()->getValue(3), 0);
- } else if (val.getArrayLength() == 2) {
- padding_top = padding_bottom = dim_conv->getPxFromValue(val.getArray()->getValue(0), 0);
- padding_left = padding_right = dim_conv->getPxFromValue(val.getArray()->getValue(1), 0);
- } else {
- padding_top = padding_right = padding_bottom = padding_left = dim_conv->getPxFromValue(&val, 0);
- }
- }
- width = skin->getPxFromNode(n->getNode("width"), width);
- height = skin->getPxFromNode(n->getNode("height"), height);
- pref_width = skin->getPxFromNode(n->getNode("pref-width"), pref_width);
- pref_height = skin->getPxFromNode(n->getNode("pref-height"), pref_height);
- min_width = skin->getPxFromNode(n->getNode("min-width"), min_width);
- min_height = skin->getPxFromNode(n->getNode("min-height"), min_height);
- max_width = skin->getPxFromNode(n->getNode("max-width"), max_width);
- max_height = skin->getPxFromNode(n->getNode("max-height"), max_height);
- spacing = skin->getPxFromNode(n->getNode("spacing"), spacing);
- content_ofs_x = skin->getPxFromNode(n->getNode("content-ofs-x"), content_ofs_x);
- content_ofs_y = skin->getPxFromNode(n->getNode("content-ofs-y"), content_ofs_y);
- img_position_x = n->getValueInt("img-position-x", img_position_x);
- img_position_y = n->getValueInt("img-position-y", img_position_y);
- img_ofs_x = skin->getPxFromNode(n->getNode("img-ofs-x"), img_ofs_x);
- img_ofs_y = skin->getPxFromNode(n->getNode("img-ofs-y"), img_ofs_y);
- flip_x = n->getValueInt("flip-x", flip_x);
- flip_y = n->getValueInt("flip-y", flip_y);
- opacity = n->getValueFloat("opacity", opacity);
-
- if (const char *color = n->getValueString("text-color", nullptr)) {
- text_color.setFromString(color, SDL_strlen(color));
- }
-
- if (const char *color = n->getValueString("background-color", nullptr)) {
- bg_color.setFromString(color, SDL_strlen(color));
- }
-
- if (const char *type_str = n->getValueString("type", nullptr)) {
- type = stringToType(type_str);
- }
-
- // Create all state elements
- m_override_elements.load(n->getNode("overrides"));
- m_strong_override_elements.load(n->getNode("strong-overrides"));
- m_child_elements.load(n->getNode("children"));
- m_overlay_elements.load(n->getNode("overlays"));
-}
-
-// == TBSkinElementState ====================================================
-
-bool TBSkinElementState::isMatch(SKIN_STATE state, TBSkinConditionContext &context, MATCH_RULE rule) const {
- if (rule == MATCH_RULE_ONLY_SPECIFIC_STATE && this->state == SKIN_STATE_ALL) {
- return false;
- }
- if (((state & this->state) != 0U) || this->state == SKIN_STATE_ALL) {
- for (TBSkinCondition *condition = conditions.getFirst(); condition != nullptr;
- condition = condition->getNext()) {
- if (!condition->getCondition(context)) {
- return false;
- }
- }
- return true;
- }
- return false;
-}
-
-bool TBSkinElementState::isExactMatch(SKIN_STATE state, TBSkinConditionContext &context, MATCH_RULE rule) const {
- if (rule == MATCH_RULE_ONLY_SPECIFIC_STATE && this->state == SKIN_STATE_ALL) {
- return false;
- }
- if (state == this->state || this->state == SKIN_STATE_ALL) {
- for (TBSkinCondition *condition = conditions.getFirst(); condition != nullptr;
- condition = condition->getNext()) {
- if (!condition->getCondition(context)) {
- return false;
- }
- }
- return true;
- }
- return false;
-}
-
-// == TBSkinElementStateList ==================================================
-
-TBSkinElementStateList::~TBSkinElementStateList() {
- while (TBSkinElementState *state = m_state_elements.getFirst()) {
- m_state_elements.remove(state);
- delete state;
- }
-}
-
-TBSkinElementState *TBSkinElementStateList::getStateElement(SKIN_STATE state, TBSkinConditionContext &context,
- TBSkinElementState::MATCH_RULE rule) const {
- // First try to get a state element with a exact match to the current state
- if (TBSkinElementState *element_state = getStateElementExactMatch(state, context, rule)) {
- return element_state;
- }
- // No exact state match. Get a state with a partly match if there is one.
- TBSkinElementState *state_element = m_state_elements.getFirst();
- while (state_element != nullptr) {
- if (state_element->isMatch(state, context, rule)) {
- return state_element;
- }
- state_element = state_element->getNext();
- }
- return nullptr;
-}
-
-TBSkinElementState *TBSkinElementStateList::getStateElementExactMatch(SKIN_STATE state, TBSkinConditionContext &context,
- TBSkinElementState::MATCH_RULE rule) const {
- TBSkinElementState *state_element = m_state_elements.getFirst();
- while (state_element != nullptr) {
- if (state_element->isExactMatch(state, context, rule)) {
- return state_element;
- }
- state_element = state_element->getNext();
- }
- return nullptr;
-}
-
-void TBSkinElementStateList::load(TBNode *n) {
- if (n == nullptr) {
- return;
- }
-
- // For each node, create a new state element.
- TBNode *element_node = n->getFirstChild();
- while (element_node != nullptr) {
- TBSkinElementState *state = new TBSkinElementState;
- if (state == nullptr) {
- return;
- }
-
- // By default, a state element applies to all combinations of states
- state->state = SKIN_STATE_ALL;
- state->element_id.set(element_node->getValue().getString());
-
- // Loop through all nodes, read state and create all found conditions.
- for (TBNode *condition_node = element_node->getFirstChild(); condition_node != nullptr;
- condition_node = condition_node->getNext()) {
- if (SDL_strcmp(condition_node->getName(), "state") == 0) {
- state->state = stringToState(condition_node->getValue().getString());
- } else if (SDL_strcmp(condition_node->getName(), "condition") == 0) {
- TBSkinCondition::TARGET target = stringToTarget(condition_node->getValueString("target", ""));
-
- const char *prop_str = condition_node->getValueString("property", "");
- TBSkinCondition::PROPERTY prop = stringToProperty(prop_str);
- TBID custom_prop;
- if (prop == TBSkinCondition::PROPERTY_CUSTOM) {
- custom_prop.set(prop_str);
- }
-
- TBID value;
- if (TBNode *value_n = condition_node->getNode("value")) {
- // Set the it to number or string. If it's a state, we must first convert the
- // state string to the SKIN_STATE state combo.
- if (prop == TBSkinCondition::PROPERTY_STATE) {
- value.set(stringToState(value_n->getValue().getString()));
- } else if (value_n->getValue().isString()) {
- value.set(value_n->getValue().getString());
- } else {
- value.set(value_n->getValue().getInt());
- }
- }
-
- TBSkinCondition::TEST test = TBSkinCondition::TEST_EQUAL;
- if (const char *test_str = condition_node->getValueString("test", nullptr)) {
- if (SDL_strcmp(test_str, "!=") == 0) {
- test = TBSkinCondition::TEST_NOT_EQUAL;
- }
- }
-
- if (TBSkinCondition *condition = new TBSkinCondition(target, prop, custom_prop, value, test)) {
- state->conditions.addLast(condition);
- }
- }
- }
-
- // State is reado to add
- m_state_elements.addLast(state);
- element_node = element_node->getNext();
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_skin.h b/src/modules/ui/turbobadger/tb/tb_skin.h
deleted file mode 100644
index 7f723b7ae..000000000
--- a/src/modules/ui/turbobadger/tb/tb_skin.h
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_bitmap_fragment.h"
-#include "tb_core.h"
-#include "tb_dimension.h"
-#include "tb_hashtable.h"
-#include "tb_linklist.h"
-#include "tb_renderer.h"
-#include "tb_value.h"
-
-namespace tb {
-
-class TBNode;
-class TBSkinConditionContext;
-
-/** Used for some values in TBSkinElement if they has not been specified in the skin. */
-#define SKIN_VALUE_NOT_SPECIFIED TB_INVALID_DIMENSION
-
-/** Skin state types (may be combined).
- NOTE: This should exactly match WIDGET_STATE in tb_widgets.h! */
-enum SKIN_STATE {
- SKIN_STATE_NONE = 0,
- SKIN_STATE_DISABLED = 1,
- SKIN_STATE_FOCUSED = 2,
- SKIN_STATE_PRESSED = 4,
- SKIN_STATE_SELECTED = 8,
- SKIN_STATE_HOVERED = 16,
-
- SKIN_STATE_ALL =
- SKIN_STATE_DISABLED | SKIN_STATE_FOCUSED | SKIN_STATE_PRESSED | SKIN_STATE_SELECTED | SKIN_STATE_HOVERED
-};
-CORE_ENUM_BIT_OPERATIONS(SKIN_STATE);
-
-/** Type of painting that should be done for a TBSkinElement. */
-enum SKIN_ELEMENT_TYPE {
- SKIN_ELEMENT_TYPE_STRETCH_BOX, ///< Default element type, cut
- /// bitmap into 9 pieces "cut" wide
- SKIN_ELEMENT_TYPE_STRETCH_BORDER, ///< Same as above, but dont fill the center
- SKIN_ELEMENT_TYPE_STRETCH_IMAGE, ///< Scale the bitmap to the dest rect
- SKIN_ELEMENT_TYPE_TILE, ///< Tile the bitmap to the dest rect
- SKIN_ELEMENT_TYPE_IMAGE
-};
-
-/** TBSkinCondition checks if a condition is true for a given TBSkinConditionContext.
- This is used to apply different state elements depending on what is currently
- painting the skin. */
-
-class TBSkinCondition : public TBLinkOf {
-public:
- /** Defines which target(s) relative to the context that should be tested for the condition. */
- enum TARGET {
- TARGET_THIS, ///< The object painting the skin.
- TARGET_PARENT, ///< The parent of the object painting the skin.
- TARGET_ANCESTORS, ///< All ancestors of the object painting the skin.
- TARGET_PREV_SIBLING, ///< The previous sibling of the object painting the skin.
- TARGET_NEXT_SIBLING ///< The next sibling of the object painting the skin.
- };
- /** Defines which property in the context that should be checked. */
- enum PROPERTY {
- PROPERTY_SKIN, ///< The background skin id.
- PROPERTY_WINDOW_ACTIVE, ///< The window is active (no value required).
- PROPERTY_AXIS, ///< The axis of the content (x or y)
- PROPERTY_ALIGN, ///< The alignment.
- PROPERTY_ID, ///< The id.
- PROPERTY_STATE, ///< The state is set.
- PROPERTY_VALUE, ///< The current value (integer).
- PROPERTY_HOVER, ///< Focus is on the target or any child (no value required).
- PROPERTY_CAPTURE, ///< Capture is on the target or any child (no value required).
- PROPERTY_FOCUS, ///< Focus is on the target or any child (no value required).
- PROPERTY_CUSTOM ///< It's a property unknown to skin, that the TBSkinConditionContext might know about.
- };
-
- /** Defines if the condition tested should be equal or not for the condition to be true. */
- enum TEST {
- TEST_EQUAL, ///< Value should be equal for condition to be true.
- TEST_NOT_EQUAL ///< Value should not be equal for condition to be true.
- };
-
- /** Stores the information needed for checking a condition. */
- struct CONDITION_INFO {
- PROPERTY prop; ///< Which property.
- TBID custom_prop; ///< Which property (only if prop is PROPERTY_CUSTOM).
- TBID value; ///< The value to compare.
- };
-
- TBSkinCondition(TARGET target, PROPERTY prop, const TBID &custom_prop, const TBID &value, TEST test);
-
- /** Return true if the condition is true for the given context. */
- bool getCondition(TBSkinConditionContext &context) const;
-
-private:
- TARGET m_target;
- CONDITION_INFO m_info;
- TEST m_test;
-};
-
-/** TBSkinConditionContext checks if a condition is true. It is passed to skin painting functions
- so different state elements can be applied depending on the current situation of the context.
- F.ex a widget may change appearance if it's under a parent with a certain skin. */
-
-class TBSkinConditionContext {
-public:
- virtual ~TBSkinConditionContext() {
- }
- /** Return true if the given target and property equals the given value. */
- virtual bool getCondition(TBSkinCondition::TARGET target, const TBSkinCondition::CONDITION_INFO &info) = 0;
-};
-
-/** TBSkinElementState has a skin element id that should be used if its state and condition
- matches that which is being painted.
-*/
-
-class TBSkinElementState : public TBLinkOf {
-public:
- /** Defines how to match states. */
- enum MATCH_RULE {
- /** States with "all" (SKIN_STATE_ALL) will also be considered a match. */
- MATCH_RULE_DEFAULT,
- /** States with "all" will not be considered a match. */
- MATCH_RULE_ONLY_SPECIFIC_STATE
- };
-
- bool isMatch(SKIN_STATE state, TBSkinConditionContext &context, MATCH_RULE rule = MATCH_RULE_DEFAULT) const;
-
- bool isExactMatch(SKIN_STATE state, TBSkinConditionContext &context, MATCH_RULE rule = MATCH_RULE_DEFAULT) const;
-
- TBID element_id;
- SKIN_STATE state;
- TBLinkListAutoDeleteOf conditions;
-};
-
-/** List of state elements in a TBSkinElement. */
-
-class TBSkinElementStateList {
-public:
- ~TBSkinElementStateList();
-
- TBSkinElementState *
- getStateElement(SKIN_STATE state, TBSkinConditionContext &context,
- TBSkinElementState::MATCH_RULE rule = TBSkinElementState::MATCH_RULE_DEFAULT) const;
-
- TBSkinElementState *
- getStateElementExactMatch(SKIN_STATE state, TBSkinConditionContext &context,
- TBSkinElementState::MATCH_RULE rule = TBSkinElementState::MATCH_RULE_DEFAULT) const;
-
- bool hasStateElements() const {
- return m_state_elements.hasLinks();
- }
- const TBSkinElementState *getFirstElement() const {
- return m_state_elements.getFirst();
- }
-
- void load(TBNode *n);
-
-private:
- TBLinkListOf m_state_elements;
-};
-
-/** Skin element.
- Contains a bitmap fragment (or nullptr) and info specifying how it should be painted.
- Also contains padding and other look-specific widget properties. */
-class TBSkinElement {
-public:
- TBSkinElement();
- ~TBSkinElement();
-
- // Skin properties
- TBID id; ///< ID of the skin element
- core::String name; ///< Name of the skin element, f.ex "TBSelectDropdown.arrow"
- core::String bitmap_file; ///< File name of the bitmap (might be empty)
- TBBitmapFragment *bitmap; ///< Bitmap fragment containing the graphics, or nullptr.
- uint8_t cut; ///< How the bitmap should be sliced using StretchBox.
- int16_t expand; ///< How much the skin should expand outside the widgets rect.
- SKIN_ELEMENT_TYPE type; ///< Skin element type
- bool is_painting; ///< If the skin is being painted (avoiding eternal recursing)
- bool is_getting; ///< If the skin is being got (avoiding eternal recursion)
- int16_t padding_left; ///< Left padding for any content in the element
- int16_t padding_top; ///< Top padding for any content in the element
- int16_t padding_right; ///< Right padding for any content in the element
- int16_t padding_bottom; ///< Bottom padding for any content in the element
- int16_t width; ///< Intrinsic width or SKIN_VALUE_NOT_SPECIFIED
- int16_t height; ///< Intrinsic height or SKIN_VALUE_NOT_SPECIFIED
- int16_t pref_width; ///< Preferred width or SKIN_VALUE_NOT_SPECIFIED
- int16_t pref_height; ///< Preferred height or SKIN_VALUE_NOT_SPECIFIED
- int16_t min_width; ///< Minimum width or SKIN_VALUE_NOT_SPECIFIED
- int16_t min_height; ///< Minimum height or SKIN_VALUE_NOT_SPECIFIED
- int16_t max_width; ///< Maximum width or SKIN_VALUE_NOT_SPECIFIED
- int16_t max_height; ///< Maximum height or SKIN_VALUE_NOT_SPECIFIED
- int16_t spacing; ///< Spacing used on layout or SKIN_VALUE_NOT_SPECIFIED.
- int16_t content_ofs_x; ///< X offset of the content in the widget.
- int16_t content_ofs_y; ///< Y offset of the content in the widget.
- int16_t img_ofs_x; ///< X offset for type image. Relative to image position (img_position_x).
- int16_t img_ofs_y; ///< Y offset for type image. Relative to image position (img_position_y).
- int8_t img_position_x; ///< Horizontal position for type image. 0-100 (left to
- ///< right in available space). Default 50.
- int8_t img_position_y; ///< Vertical position for type image. 0-100 (top to bottom
- ///< in available space). Default 50.
- int8_t flip_x; ///< The skin is flipped horizontally
- int8_t flip_y; ///< The skin is flipped vertically
- float opacity; ///< Opacity that should be used for the whole widget (0.f - 1.f).
- TBColor text_color; ///< Color of the text in the widget.
- TBColor bg_color; ///< Color of the background in the widget.
- int16_t bitmap_dpi; ///< The DPI of the bitmap that was loaded.
- TBValue tag; ///< This value is free to use for anything. It's not used internally.
-
- /** Get the minimum width, or SKIN_VALUE_NOT_SPECIFIED if not specified. */
- int getMinWidth() const {
- return min_width;
- }
-
- /** Get the minimum height, or SKIN_VALUE_NOT_SPECIFIED if not specified. */
- int getMinHeight() const {
- return min_height;
- }
-
- /** Get the intrinsic minimum width. It will be calculated based on the skin properties. */
- int getIntrinsicMinWidth() const;
-
- /** Get the intrinsic minimum height. It will be calculated based on the skin properties. */
- int getIntrinsicMinHeight() const;
-
- /** Get the maximum width, or SKIN_VALUE_NOT_SPECIFIED if not specified. */
- int getMaxWidth() const {
- return max_width;
- }
-
- /** Get the maximum height, or SKIN_VALUE_NOT_SPECIFIED if not specified. */
- int getMaxHeight() const {
- return max_height;
- }
-
- /** Get the preferred width, or SKIN_VALUE_NOT_SPECIFIED if not specified. */
- int getPrefWidth() const {
- return pref_width;
- }
-
- /** Get the preferred height, or SKIN_VALUE_NOT_SPECIFIED if not specified. */
- int getPrefHeight() const {
- return pref_height;
- }
-
- /** Get the intrinsic width. If not specified using the "width" attribute, it will be
- calculated based on the skin properties. If it can't be calculated it will return
- SKIN_VALUE_NOT_SPECIFIED. */
- int getIntrinsicWidth() const;
-
- /** Get the intrinsic height. If not specified using the "height" attribute, it will be
- calculated based on the skin properties. If it can't be calculated it will return
- SKIN_VALUE_NOT_SPECIFIED. */
- int getIntrinsicHeight() const;
-
- /** Set the DPI that the bitmap was loaded in. This may modify properties
- to compensate for the bitmap resolution. */
- void setBitmapDPI(const TBDimensionConverter &dimConv, int bitmapDpi);
-
- /** List of override elements (See TBSkin::PaintSkin) */
- TBSkinElementStateList m_override_elements;
-
- /** List of strong-override elements (See TBSkin::PaintSkin) */
- TBSkinElementStateList m_strong_override_elements;
-
- /** List of child elements (See TBSkin::PaintSkin) */
- TBSkinElementStateList m_child_elements;
-
- /** List of overlay elements (See TBSkin::PaintSkin) */
- TBSkinElementStateList m_overlay_elements;
-
- /** Check if there's a exact or partial match for the given state in either
- override, child or overlay element list.
- State elements with state "all" will be ignored. */
- bool hasState(SKIN_STATE state, TBSkinConditionContext &context);
-
- /** Return true if this element has overlay elements. */
- bool hasOverlayElements() const {
- return m_overlay_elements.hasStateElements();
- }
-
- void load(TBNode *n, TBSkin *skin, const char *skin_path);
-};
-
-class TBSkinListener {
-public:
- virtual ~TBSkinListener() {
- }
- /** Called when a skin element has been loaded from the given TBNode.
- NOTE: This may be called multiple times on elements that occur multiple times
- in the skin or is overridden in an override skin.
- This method can be used to f.ex feed custom properties into element->tag. */
- virtual void onSkinElementLoaded(TBSkin *skin, TBSkinElement *element, TBNode *node) = 0;
-};
-
-/** TBSkin contains a list of TBSkinElement. */
-class TBSkin : private TBRendererListener {
-public:
- TBSkin();
- virtual ~TBSkin();
-
- /** Set the listener for this skin. */
- void setListener(TBSkinListener *listener) {
- m_listener = listener;
- }
- TBSkinListener *getListener() const {
- return m_listener;
- }
-
- /** Load the skin file and the bitmaps it refers to.
-
- If override_skin_file is specified, it will also be loaded into this skin after
- loading skin_file. Elements using the same name will override any previosly
- read data for the same element. Known limitation: Clone can currently only
- clone elements in the same file!
-
- Returns true on success, and all bitmaps referred to also loaded successfully. */
- bool load(const char *skinFile, const char *overrideSkinFile = nullptr);
-
- /** Unload all bitmaps used in this skin. */
- void unloadBitmaps();
-
- /** Reload all bitmaps used in this skin. Calls UnloadBitmaps first to ensure no bitmaps
- are loaded before loading new ones. */
- bool reloadBitmaps();
-
- /** Get the dimension converter used for the current skin. This dimension converter
- converts to px by the same factor as the skin (based on the skin DPI settings). */
- const TBDimensionConverter *getDimensionConverter() const {
- return &m_dim_conv;
- }
-
- /** Get the skin element with the given id.
- Returns nullptr if there's no match. */
- TBSkinElement *getSkinElement(const TBID &skin_id) const;
-
- /** Get the skin element with the given id and state.
- This is like calling GetSkinElement and also following any strong overrides that
- match the current state (if any). See details about strong overrides in PaintSkin.
- Returns nullptr if there's no match. */
- TBSkinElement *getSkinElementStrongOverride(const TBID &skin_id, SKIN_STATE state,
- TBSkinConditionContext &context) const;
-
- /** Get the default text color for all skin elements */
- TBColor getDefaultTextColor() const {
- return m_default_text_color;
- }
-
- /** Get the default disabled opacity for all skin elements */
- float getDefaultDisabledOpacity() const {
- return m_default_disabled_opacity;
- }
-
- /** Get the default placeholder opacity for all skin elements */
- float getDefaultPlaceholderOpacity() const {
- return m_default_placeholder_opacity;
- }
-
- /** Get the default layout spacing in pixels. */
- int getDefaultSpacing() const {
- return m_default_spacing;
- }
-
- /** Paint the skin at dst_rect.
-
- Strong override elements:
- -Strong override elements are like override elements, but they don't only apply
- when painting. They also override padding and other things that might affect
- the layout of the widget having the skin set.
-
- Override elements:
- -If there is a override element with the exact matching state, it will paint
- the override *instead* if the base skin. If no exact match was found, it will
- check for a partial match and paint that *instead* of the base skin.
-
- Child elements:
- -It will paint *all* child elements that match the current state ("all" can be specified
- as state so it will always be painted). The elements are painted in the order they are
- specified in the skin.
-
- Special elements:
- -There's some special generic skin elements used by TBWidget (see TBWidget::setSkinBg)
-
- Overlay elements:
- -Overlay elements are painted separately, from PaintSkinOverlay (when all sibling
- widgets has been painted). As with child elements, all overlay elements that match
- the current state will be painted in the order they are specified in the skin.
-
- Return the skin element used (after following override elements),
- or nullptr if no skin element was found matching the skin_id. */
- TBSkinElement *paintSkin(const TBRect &dstRect, const TBID &skinId, SKIN_STATE state,
- TBSkinConditionContext &context);
-
- /** Paint the skin at dst_rect. Just like the PaintSkin above, but takes a specific
- skin element instead of looking it up from the id. */
- TBSkinElement *paintSkin(const TBRect &dst_rect, TBSkinElement *element, SKIN_STATE state,
- TBSkinConditionContext &context);
-
- /** Paint the overlay elements for the given skin element and state. */
- void paintSkinOverlay(const TBRect &dst_rect, TBSkinElement *element, SKIN_STATE state,
- TBSkinConditionContext &context);
-
- /** Paint a rectangle outline inside dst_rect with the given thickness and color. */
- void paintRect(const TBRect &dst_rect, const TBColor &color, int thickness);
-
- /** Paint a filled rectangle with the given color. */
- void paintRectFill(const TBRect &dst_rect, const TBColor &color);
-
-#ifdef TB_RUNTIME_DEBUG_INFO
- /** Render the skin bitmaps on screen, to analyze fragment positioning. */
- void debug();
-#endif
-
- /** Get the fragment manager. */
- TBBitmapFragmentManager *getFragmentManager() {
- return &m_frag_manager;
- }
-
- // Implementing TBRendererListener
- virtual void onContextLost();
- virtual void onContextRestored();
-
-private:
- friend class TBSkinElement;
- TBSkinListener *m_listener;
- TBHashTableAutoDeleteOf m_elements; ///< All skin elements for this skin.
- TBBitmapFragmentManager m_frag_manager; ///< Fragment manager
- TBDimensionConverter m_dim_conv; ///< Dimension converter
- TBColor m_default_text_color; ///< Default text color for all skin elements
- TBBitmapFragment *m_color_frag; ///< Used for painting single color.
- float m_default_disabled_opacity; ///< Disabled opacity
- float m_default_placeholder_opacity; ///< Placeholder opacity
- int16_t m_default_spacing; ///< Default layout spacing
- bool loadInternal(const char *skin_file);
- bool reloadBitmapsInternal();
- void paintElement(const TBRect &dst_rect, TBSkinElement *element);
- void paintElementBGColor(const TBRect &dst_rect, TBSkinElement *element);
- void paintElementImage(const TBRect &dst_rect, TBSkinElement *element);
- void paintElementTile(const TBRect &dst_rect, TBSkinElement *element);
- void paintElementStretchImage(const TBRect &dst_rect, TBSkinElement *element);
- void paintElementStretchBox(const TBRect &dstRect, TBSkinElement *element, bool fillCenter);
- TBRect getFlippedRect(const TBRect &src_rect, TBSkinElement *element) const;
- int getPxFromNode(TBNode *node, int def_value) const;
-};
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_skin_util.cpp b/src/modules/ui/turbobadger/tb/tb_skin_util.cpp
deleted file mode 100644
index 47c2fabec..000000000
--- a/src/modules/ui/turbobadger/tb/tb_skin_util.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_skin_util.h"
-
-namespace tb {
-
-static int getFadeoutSize(int scrolledDistance, int fadeoutLength) {
- // Make it appear gradually
- // float factor = scrolled_distance / 10.f;
- // factor = Clamp(factor, 0.5f, 1);
- // return (int)(fadeout_length * factor);
- return scrolledDistance > 0 ? fadeoutLength : 0;
-}
-
-void drawEdgeFadeout(const TBRect &dstRect, const TBID &skinX, const TBID &skinY, int left, int top, int right,
- int bottom) {
- if (TBSkinElement *skin = g_tb_skin->getSkinElement(skinX)) {
- if (skin->bitmap != nullptr) {
- const int bw = skin->bitmap->width();
- const int bh = skin->bitmap->height();
- int dw;
- if ((dw = getFadeoutSize(left, bw)) > 0) {
- g_renderer->drawBitmap(TBRect(dstRect.x, dstRect.y, dw, dstRect.h), TBRect(0, 0, bw, bh), skin->bitmap);
- }
- if ((dw = getFadeoutSize(right, bw)) > 0) {
- g_renderer->drawBitmap(TBRect(dstRect.x + dstRect.w - dw, dstRect.y, dw, dstRect.h),
- TBRect(bw, 0, -bw, bh), skin->bitmap);
- }
- }
- }
- if (TBSkinElement *skin = g_tb_skin->getSkinElement(skinY)) {
- if (skin->bitmap != nullptr) {
- const int bw = skin->bitmap->width();
- const int bh = skin->bitmap->height();
- int dh;
- if ((dh = getFadeoutSize(top, bh)) > 0) {
- g_renderer->drawBitmap(TBRect(dstRect.x, dstRect.y, dstRect.w, dh), TBRect(0, 0, bw, bh), skin->bitmap);
- }
- if ((dh = getFadeoutSize(bottom, bh)) > 0) {
- g_renderer->drawBitmap(TBRect(dstRect.x, dstRect.y + dstRect.h - dh, dstRect.w, dh),
- TBRect(0, bh, bw, -bh), skin->bitmap);
- }
- }
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_skin_util.h b/src/modules/ui/turbobadger/tb/tb_skin_util.h
deleted file mode 100644
index 33354ed5d..000000000
--- a/src/modules/ui/turbobadger/tb/tb_skin_util.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_skin.h"
-
-namespace tb {
-
-/** Draw fade out skin elements at the edges of dst_rect if needed.
- It indicates to the user that there is hidden content.
- left, top, right, bottom specifies the (positive) distance scrolled
- from the limit. */
-void drawEdgeFadeout(const TBRect &dstRect, const TBID &skinX, const TBID &skinY, int left, int top, int right,
- int bottom);
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_sort.h b/src/modules/ui/turbobadger/tb/tb_sort.h
deleted file mode 100644
index 5b218c4cf..000000000
--- a/src/modules/ui/turbobadger/tb/tb_sort.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include
-
-namespace tb {
-
-template
-static void insertion_sort(TYPE *elements, size_t elementcount, CONTEXT context,
- int (*cmp)(CONTEXT context, const TYPE *a, const TYPE *b)) {
- size_t i;
- size_t j;
- for (i = 1; i < elementcount; i++) {
- TYPE value = elements[i];
- for (j = i; j > 0 && cmp(context, &value, &elements[j - 1]) < 0; j--) {
- elements[j] = elements[j - 1];
- }
- elements[j] = value;
- }
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_str.cpp b/src/modules/ui/turbobadger/tb/tb_str.cpp
deleted file mode 100644
index 640f0f40d..000000000
--- a/src/modules/ui/turbobadger/tb/tb_str.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_str.h"
-#include "core/Assert.h"
-
-namespace tb {
-
-const char *stristr(const char *arg1, const char *arg2) {
- const char *a;
- const char *b;
-
- for (; *arg1 != 0; arg1++) {
- a = arg1;
- b = arg2;
- while (SDL_toupper(*a++) == SDL_toupper(*b++)) {
- if (*b == 0) {
- return arg1;
- }
- }
- }
- return nullptr;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_str.h b/src/modules/ui/turbobadger/tb/tb_str.h
deleted file mode 100644
index 007a9a284..000000000
--- a/src/modules/ui/turbobadger/tb/tb_str.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_types.h"
-#include "core/String.h"
-#include
-
-namespace tb {
-
-/** Some useful C-like functions that's missing in the standard. */
-const char *stristr(const char *arg1, const char *arg2);
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_style_edit.cpp b/src/modules/ui/turbobadger/tb/tb_style_edit.cpp
deleted file mode 100644
index b46ea838c..000000000
--- a/src/modules/ui/turbobadger/tb/tb_style_edit.cpp
+++ /dev/null
@@ -1,2013 +0,0 @@
-/**
- * @file
- */
-
-#include "tb_style_edit.h"
-#include "core/Assert.h"
-#include "tb_font_renderer.h"
-#include "tb_style_edit_content.h"
-#include "tb_system.h"
-#include "tb_tempbuffer.h"
-#include "tb_widgets_common.h"
-#include "utf8/utf8.h"
-
-namespace tb {
-
-#if 0 // Enable for some graphical debugging
-#define TMPDEBUG(expr) expr
-#define nTMPDEBUG(expr)
-#else
-#define TMPDEBUG(expr)
-#define nTMPDEBUG(expr) expr
-#endif
-
-const int TAB_SPACE = 4;
-
-const char *special_char_newln = "¶"; // 00B6 PILCROW SIGN
-const char *special_char_space = "·"; // 00B7 MIDDLE DOT
-const char *special_char_tab = "»"; // 00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-const char *special_char_password = "•"; // 2022 BULLET
-
-static bool is_space(int8_t c) {
- switch (c) {
- case ' ':
- return true;
- }
- return false;
-}
-
-static bool is_linebreak(int8_t c) {
- switch (c) {
- case '\n':
- case '\r':
- case 0:
- return true;
- }
- return false;
-}
-
-static bool is_wordbreak(int8_t c) {
- switch (c) {
- case 0:
- case '\n':
- case '\r':
- case '\t':
- case '\"':
- case '\'':
- case '/':
- case '\\':
- case '[':
- case ']':
- case '{':
- case '}':
- case '(':
- case ')':
- case '>':
- case '<':
- case '-':
- case '+':
- case '*':
- case ',':
- case '.':
- case ';':
- case ':':
- case '&':
- case '|':
- case '#':
- case '!':
- case '=':
- case '^':
- case '~':
- case '?':
- case '@':
- case '$':
- return true;
- }
- return is_space(c);
-}
-
-/** Check if no line wrapping is allowed before the character at the given offset.
- The string must be null terminated. */
-static bool is_never_break_before(const char *str, int ofs) {
- switch (str[ofs]) {
- case '\n':
- case '\r':
- case ' ':
- case '-':
- case '.':
- case ',':
- case ':':
- case ';':
- case '!':
- case '?':
- case ')':
- case ']':
- case '}':
- case '>':
- return true;
- case '\'':
- case '"':
- // Simple test if it's the first quote in a word surrounded by space.
- return ofs > 0 && !is_space(str[ofs - 1]);
- default:
- return false;
- }
-}
-
-/** Check if no line wrapping is allowed after the character at the given offset.
- The string must be null terminated. */
-static bool is_never_break_after(const char *str, int ofs) {
- switch (str[ofs]) {
- case '(':
- case '[':
- case '{':
- case '<':
- case '@':
- case '$':
- return true;
- case '\'':
- case '"':
- // Simple test if it's the last quote in a word surrounded by space.
- return !is_space(str[ofs + 1]);
- default:
- return false;
- }
-}
-
-static bool getNextFragment(const char *text, TBTextFragmentContentFactory *contentFactory, int *fragLen,
- bool *isEmbed) {
- if (text[0] == '\t') {
- *fragLen = 1;
- return text[1] != 0;
- }
- if (text[0] == 0) // happens when not setting text and maby when setting ""
- {
- *fragLen = 0;
- return false;
- }
- if (text[0] == '\r' || text[0] == '\n') {
- int len = (text[0] == '\r' && text[1] == '\n') ? 2 : 1;
- *fragLen = len;
- return false;
- }
- if (contentFactory != nullptr) {
- if (int content_len = contentFactory->getContent(text)) {
- *fragLen = content_len;
- *isEmbed = true;
- return text[content_len] != 0;
- }
- }
- int i = 0;
- while (!is_wordbreak(text[i])) {
- i++;
- }
- if (i == 0) {
- if (is_wordbreak(text[i])) {
- i++;
- }
- }
- *fragLen = i;
- return text[i] != 0;
-}
-
-// == TBSelection ==================================================
-
-TBSelection::TBSelection(TBStyleEdit *styledit) : styledit(styledit) {
-}
-
-void TBSelection::correctOrder() {
- if (start.block == stop.block && start.ofs == stop.ofs) {
- selectNothing();
- } else {
- if ((start.block == stop.block && start.ofs > stop.ofs) ||
- (start.block != stop.block && start.block->ypos > stop.block->ypos)) {
- TBTextOfs tmp = start;
- start = stop;
- stop = tmp;
- }
- }
-}
-
-void TBSelection::copyToClipboard() {
- if (isSelected()) {
- core::String text;
- if (getText(text)) {
- TBClipboard::setText(text.c_str());
- }
- }
-}
-
-void TBSelection::invalidate() const {
- TBBlock *block = start.block;
- while (block != nullptr) {
- block->invalidate();
- if (block == stop.block) {
- break;
- }
- block = block->getNext();
- }
-}
-
-void TBSelection::select(const TBTextOfs &newStart, const TBTextOfs &newStop) {
- invalidate();
- start.set(newStart);
- stop.set(newStop);
- correctOrder();
- invalidate();
-}
-
-void TBSelection::select(const TBPoint &from, const TBPoint &to) {
- invalidate();
- styledit->caret.place(from);
- start.set(styledit->caret.pos);
- styledit->caret.place(to);
- stop.set(styledit->caret.pos);
- correctOrder();
- invalidate();
- styledit->caret.updateWantedX();
-}
-
-void TBSelection::select(int globOfsFrom, int globOfsTo) {
- TBTextOfs ofs1;
- TBTextOfs ofs2;
- ofs1.setGlobalOfs(styledit, globOfsFrom);
- ofs2.setGlobalOfs(styledit, globOfsTo);
- select(ofs1, ofs2);
-}
-
-void TBSelection::selectToCaret(TBBlock *oldCaretBlock, int32_t oldCaretOfs) {
- invalidate();
- if (start.block == nullptr) {
- start.set(oldCaretBlock, oldCaretOfs);
- stop.set(styledit->caret.pos);
- } else {
- if (start.block == oldCaretBlock && start.ofs == oldCaretOfs) {
- start.set(styledit->caret.pos);
- } else {
- stop.set(styledit->caret.pos);
- }
- }
- correctOrder();
- invalidate();
-}
-
-void TBSelection::selectAll() {
- start.set(styledit->blocks.getFirst(), 0);
- stop.set(styledit->blocks.getLast(), styledit->blocks.getLast()->str_len);
- invalidate();
-}
-
-void TBSelection::selectNothing() {
- invalidate();
- start.set(nullptr, 0);
- stop.set(nullptr, 0);
-}
-
-bool TBSelection::isBlockSelected(const TBBlock *block) const {
- if (!isSelected()) {
- return false;
- }
- return block->ypos >= start.block->ypos && block->ypos <= stop.block->ypos;
-}
-
-bool TBSelection::isFragmentSelected(const TBBlock *block, TBTextFragment *elm) const {
- if (!isSelected()) {
- return false;
- }
- if (start.block == stop.block) {
- if (block != start.block) {
- return false;
- }
- return start.ofs < elm->ofs + elm->len && stop.ofs >= elm->ofs;
- }
- if (block->ypos > start.block->ypos && block->ypos < stop.block->ypos) {
- return true;
- }
- if (block->ypos == start.block->ypos && elm->ofs + elm->len > start.ofs) {
- return true;
- }
- if (block->ypos == stop.block->ypos && elm->ofs < stop.ofs) {
- return true;
- }
- return false;
-}
-
-bool TBSelection::isSelected() const {
- return start.block != nullptr;
-}
-
-void TBSelection::removeContent() {
- if (!isSelected()) {
- return;
- }
- styledit->beginLockScrollbars();
- if (start.block == stop.block) {
- if (!styledit->undoredo.applying) {
- styledit->undoredo.commit(styledit, start.getGlobalOfs(styledit), stop.ofs - start.ofs,
- start.block->str.c_str() + start.ofs, false);
- }
- start.block->removeContent(start.ofs, stop.ofs - start.ofs);
- } else {
- // Remove text in first block
- TBTempBuffer commit_string;
- int32_t start_gofs = 0;
- if (!styledit->undoredo.applying) {
- start_gofs = start.getGlobalOfs(styledit);
- commit_string.append(start.block->str.c_str() + start.ofs, start.block->str_len - start.ofs);
- }
- start.block->removeContent(start.ofs, start.block->str_len - start.ofs);
-
- // Remove text in all block in between start and stop
- TBBlock *block = start.block->getNext();
- while (block != stop.block) {
- if (!styledit->undoredo.applying) {
- commit_string.append(block->str.c_str(), block->str_len);
- }
-
- TBBlock *next = block->getNext();
- styledit->blocks.doDelete(block);
- block = next;
- }
-
- // Remove text in last block
- if (!styledit->undoredo.applying) {
- commit_string.append(stop.block->str.c_str(), stop.ofs);
- styledit->undoredo.commit(styledit, start_gofs, commit_string.getAppendPos(), commit_string.getData(),
- false);
- }
- stop.block->removeContent(0, stop.ofs);
- }
- stop.block->merge();
- start.block->merge();
- styledit->caret.place(start.block, start.ofs);
- styledit->caret.updateWantedX();
- selectNothing();
- styledit->endLockScrollbars();
-}
-
-bool TBSelection::getText(core::String &text) const {
- if (!isSelected()) {
- text.clear();
- return true;
- }
- if (start.block == stop.block) {
- text.append(start.block->str.c_str() + start.ofs, stop.ofs - start.ofs);
- } else {
- TBTempBuffer buf;
- buf.append(start.block->str.c_str() + start.ofs, start.block->str_len - start.ofs);
- TBBlock *block = start.block->getNext();
- while (block != stop.block) {
- buf.append(block->str.c_str(), block->str_len);
- block = block->getNext();
- }
- // FIX: Add methods to change data owner from temp buffer to string!
- buf.append(stop.block->str.c_str(), stop.ofs);
- text = core::String((char *)buf.getData(), buf.getAppendPos());
- }
- return true;
-}
-
-// == TBTextOfs =========================================================================
-
-int32_t TBTextOfs::getGlobalOfs(TBStyleEdit *se) const {
- int32_t gofs = 0;
- TBBlock *b = se->blocks.getFirst();
- while ((b != nullptr) && b != block) {
- gofs += b->str_len;
- b = b->getNext();
- }
- gofs += ofs;
- return gofs;
-}
-
-bool TBTextOfs::setGlobalOfs(TBStyleEdit *se, int32_t gofs) {
- TBBlock *b = se->blocks.getFirst();
- while (b != nullptr) {
- int b_len = b->str_len;
- if (gofs <= b_len) {
- block = b;
- ofs = gofs;
- return true;
- }
- gofs -= b_len;
- b = b->getNext();
- }
- core_assert(!"out of range! not a valid global offset!");
- return false;
-}
-
-// == TBCaret ============================================================================
-
-TBCaret::TBCaret(TBStyleEdit *styledit)
- : styledit(styledit), x(0), y(0), width(2), height(0), wanted_x(0), on(false), prefer_first(true) {
-}
-
-void TBCaret::invalidate() {
- if (styledit->listener != nullptr) {
- styledit->listener->invalidate(TBRect(x - styledit->scroll_x, y - styledit->scroll_y, width, height));
- }
-}
-
-void TBCaret::updatePos() {
- invalidate();
- TBTextFragment *fragment = getFragment();
- x = fragment->xpos + fragment->getCharX(pos.block, styledit->font, pos.ofs - fragment->ofs);
- y = fragment->ypos + pos.block->ypos;
- height = fragment->getHeight(pos.block, styledit->font);
- if (height == 0) {
- // If we don't have height, we're probably inside a style switch embed.
- y = fragment->line_ypos + pos.block->ypos;
- height = fragment->line_height;
- }
- invalidate();
-}
-
-bool TBCaret::move(bool forward, bool word) {
- // Make it stay on the same line if it reach the wrap point.
- prefer_first = forward;
- if (this->styledit->packed.password_on) {
- word = false;
- }
-
- int len = pos.block->str_len;
- if (word && !(forward && pos.ofs == len) && !(!forward && pos.ofs == 0)) {
- const char *str = pos.block->str.c_str();
- if (forward) {
- if (is_linebreak(str[pos.ofs])) {
- pos.ofs++;
- } else if (is_wordbreak(str[pos.ofs])) {
- while (pos.ofs < len && is_wordbreak(str[pos.ofs]) && !is_linebreak(str[pos.ofs])) {
- pos.ofs++;
- }
- } else {
- while (pos.ofs < len && !is_wordbreak(str[pos.ofs])) {
- pos.ofs++;
- }
- while (pos.ofs < len && is_space(str[pos.ofs])) {
- pos.ofs++;
- }
- }
- } else if (pos.ofs > 0) {
- while (pos.ofs > 0 && is_space(str[pos.ofs - 1])) {
- pos.ofs--;
- }
- if (pos.ofs > 0 && is_wordbreak(str[pos.ofs - 1])) {
- while (pos.ofs > 0 && is_wordbreak(str[pos.ofs - 1])) {
- pos.ofs--;
- }
- } else {
- while (pos.ofs > 0 && !is_wordbreak(str[pos.ofs - 1])) {
- pos.ofs--;
- }
- }
- }
- } else {
- if (forward && pos.ofs >= pos.block->str_len && (pos.block->getNext() != nullptr)) {
- pos.block = pos.block->getNext();
- pos.ofs = 0;
- } else if (!forward && pos.ofs <= 0 && (pos.block->prev != nullptr)) {
- pos.block = pos.block->getPrev();
- pos.ofs = pos.block->str_len;
- } else {
- int i = pos.ofs;
- if (forward) {
- utf8::move_inc(pos.block->str.c_str(), &i, pos.block->str_len);
- } else {
- utf8::move_dec(pos.block->str.c_str(), &i);
- }
- pos.ofs = i;
- }
- }
- return place(pos.block, pos.ofs, true, forward);
-}
-
-bool TBCaret::place(const TBPoint &point) {
- TBBlock *block = styledit->findBlock(point.y);
- TBTextFragment *fragment = block->findFragment(point.x, point.y - block->ypos);
- int ofs = fragment->ofs + fragment->getCharOfs(block, styledit->font, point.x - fragment->xpos);
-
- if (place(block, ofs)) {
- if (getFragment() != fragment) {
- prefer_first = !prefer_first;
- place(block, ofs);
- }
- return true;
- }
- return false;
-}
-
-void TBCaret::place(TB_CARET_POS pos) {
- if (pos == TB_CARET_POS_BEGINNING) {
- place(styledit->blocks.getFirst(), 0);
- } else if (pos == TB_CARET_POS_END) {
- place(styledit->blocks.getLast(), styledit->blocks.getLast()->str_len);
- }
-}
-
-bool TBCaret::place(TBBlock *block, int ofs, bool allowSnap, bool snapForward) {
- if (block != nullptr) {
- while ((block->getNext() != nullptr) && ofs > block->str_len) {
- ofs -= block->str_len;
- block = block->getNext();
- }
- while ((block->prev != nullptr) && ofs < 0) {
- block = block->getPrev();
- ofs += block->str_len;
- }
- if (ofs < 0) {
- ofs = 0;
- }
- if (ofs > block->str_len) {
- ofs = block->str_len;
- }
-
- // Avoid being inside linebreak
- if (allowSnap) {
- TBTextFragment *fragment = block->findFragment(ofs);
- if (ofs > fragment->ofs && fragment->isBreak()) {
- if (snapForward && (block->getNext() != nullptr)) {
- block = block->getNext();
- ofs = 0;
- } else {
- ofs = fragment->ofs;
- }
- }
- }
- }
-
- bool changed = (pos.block != block || pos.ofs != ofs);
- pos.set(block, ofs);
-
- if (block != nullptr) {
- updatePos();
- }
-
- return changed;
-}
-
-void TBCaret::avoidLineBreak() {
- TBTextFragment *fragment = getFragment();
- if (pos.ofs > fragment->ofs && fragment->isBreak()) {
- pos.ofs = fragment->ofs;
- }
- updatePos();
-}
-
-void TBCaret::paint(int32_t translateX, int32_t translateY) {
- // if (on && !(styledit->select_state && styledit->selection.isSelected()))
- if (on || (styledit->select_state != 0)) {
- styledit->listener->drawCaret(TBRect(translateX + x, translateY + y, width, height));
- }
-}
-
-void TBCaret::resetBlink() {
- styledit->listener->caretBlinkStop();
- on = true;
- styledit->listener->caretBlinkStart();
-}
-
-void TBCaret::updateWantedX() {
- wanted_x = x;
-}
-
-TBTextFragment *TBCaret::getFragment() {
- return pos.block->findFragment(pos.ofs, prefer_first);
-}
-
-void TBCaret::switchBlock(bool second) {
-}
-
-void TBCaret::setGlobalOfs(int32_t gofs, bool allowSnap, bool snapForward) {
- TBTextOfs ofs;
- if (ofs.setGlobalOfs(styledit, gofs)) {
- place(ofs.block, ofs.ofs, allowSnap, snapForward);
- }
-}
-
-// == TBTextProps =======================================================================
-
-void TBTextProps::reset(const TBFontDescription &fontDesc, const TBColor &textColor) {
- core_assert(next_index == 0);
- while (list.getNumItems() > 0) {
- delete list.get(0);
- list.remove(0);
- }
- next_index = 0;
- base.font_desc = fontDesc;
- base.text_color = textColor;
- base.underline = false;
- data = &base;
-}
-
-TBTextProps::Data *TBTextProps::push() {
- if (next_index >= list.getNumItems()) {
- Data *data = new Data;
- if (data == nullptr) {
- return nullptr;
- }
- if (!list.add(data)) {
- delete data;
- return nullptr;
- }
- }
- Data *next = list.get(next_index++);
- *next = *data;
- data = next;
- return data;
-}
-
-void TBTextProps::pop() {
- if (next_index == 0) {
- return; // Unballanced or we previously got OOM.
- }
- next_index--;
- data = next_index > 0 ? list.get(next_index - 1) : &base;
-}
-
-TBFontFace *TBTextProps::getFont() const {
- return g_font_manager->getFontFace(data->font_desc);
-}
-
-// ============================================================================
-
-TBBlock::TBBlock(TBStyleEdit *styledit)
- : styledit(styledit), ypos(0), height(0), align(styledit->align), line_width_max(0), str_len(0), syntax_data(0) {
-}
-
-TBBlock::~TBBlock() {
- clear();
-}
-
-void TBBlock::clear() {
- fragments.deleteAll();
-}
-
-void TBBlock::set(const char *newstr, int32_t len) {
- str = core::String(newstr, len);
- str_len = len;
- split();
- layout(true, true);
-}
-
-void TBBlock::setAlign(TB_TEXT_ALIGN align) {
- if (this->align == align) {
- return;
- }
- this->align = align;
- layout(false, false);
-}
-
-int32_t TBBlock::insertText(int32_t ofs, const char *text, int32_t len, bool allowLineRecurse) {
- styledit->beginLockScrollbars();
- int first_line_len = len;
- for (int i = 0; i < len; i++) {
- if (text[i] == '\r' || text[i] == '\n') {
- first_line_len = i;
- // Include the line break too but not for single lines
- if (!styledit->packed.multiline_on) {
- break;
- }
- if (text[i] == '\r' && text[i + 1] == '\n') {
- first_line_len++;
- }
- first_line_len++;
- break;
- }
- }
-
- int32_t inserted_len = first_line_len;
- str.insert(ofs, text, first_line_len);
- str_len += first_line_len;
-
- split();
- layout(true, true);
-
- // Add the rest which was after the linebreak.
- if (allowLineRecurse && styledit->packed.multiline_on) {
- // Instead of recursively calling InsertText, we will loop through them all here
- TBBlock *next_block = getNext();
- const char *next_line_ptr = &text[first_line_len];
- int remaining = len - first_line_len;
- while (remaining > 0) {
- if (next_block == nullptr) {
- next_block = new TBBlock(styledit);
- styledit->blocks.addLast(next_block);
- }
- int consumed = next_block->insertText(0, next_line_ptr, remaining, false);
- next_line_ptr += consumed;
- inserted_len += consumed;
- remaining -= consumed;
- next_block = next_block->getNext();
- }
- }
- styledit->endLockScrollbars();
- return inserted_len;
-}
-
-void TBBlock::removeContent(int32_t ofs, int32_t len) {
- if (len == 0) {
- return;
- }
- str.erase(ofs, len);
- str_len -= len;
- layout(true, true);
-}
-
-void TBBlock::split() {
- int32_t len = str_len;
- int brlen =
- 1; // FIX: skip ending newline fragment but not if there is several newlines and check for singleline newline.
- if (len > 1 && str.c_str()[len - 2] == '\r' && str.c_str()[len - 1] == '\n') {
- brlen++;
- }
- len -= brlen;
- for (int i = 0; i < len; i++) {
- if (is_linebreak(str.c_str()[i])) {
- TBBlock *block = new TBBlock(styledit);
- if (block == nullptr) {
- return;
- }
- styledit->blocks.addAfter(block, this);
-
- if (i < len - 1 && str.c_str()[i] == '\r' && str.c_str()[i + 1] == '\n') {
- i++;
- }
- i++;
-
- len = len + brlen - i;
- block->set(str.c_str() + i, len);
- str.erase(i, len);
- str_len -= len;
- break;
- }
- }
-}
-
-void TBBlock::merge() {
- TBBlock *next_block = getNext();
- if ((next_block != nullptr) && !fragments.getLast()->isBreak()) {
- str.append(getNext()->str);
- str_len = str.size();
-
- styledit->blocks.doDelete(next_block);
-
- height = 0; // Ensure that Layout propagate height to remaining blocks.
- layout(true, true);
- }
-}
-
-int32_t TBBlock::calculateTabWidth(TBFontFace *font, int32_t xpos) const {
- int tabsize = font->getStringWidth("x", 1) * TAB_SPACE;
- int p2 = int(xpos / tabsize) * tabsize + tabsize;
- return p2 - xpos;
-}
-
-int32_t TBBlock::calculateStringWidth(TBFontFace *font, const char *str, int len) const {
- if (styledit->packed.password_on) {
- // Convert the length in number or characters, since that's what matters for password width.
- len = utf8::count_characters(str, len);
- return font->getStringWidth(special_char_password, SDL_strlen(special_char_password)) * len;
- }
- return font->getStringWidth(str, len);
-}
-
-int32_t TBBlock::calculateLineHeight(TBFontFace *font) const {
- return font->getHeight();
-}
-
-int32_t TBBlock::calculateBaseline(TBFontFace *font) const {
- return font->getAscent();
-}
-
-int TBBlock::getStartIndentation(TBFontFace *font, int firstLineLen) const {
- // Lines beginning with whitespace or list points, should
- // indent to the same as the beginning when wrapped.
- int indentation = 0;
- int i = 0;
- while (i < firstLineLen) {
- const char *current_str = str.c_str() + i;
- UCS4 uc = utf8::decode_next(str.c_str(), &i, firstLineLen);
- switch (uc) {
- case '\t':
- indentation += calculateTabWidth(font, indentation);
- continue;
- case ' ':
- case '-':
- case '*':
- indentation += calculateStringWidth(font, current_str, 1);
- continue;
- case 0x2022: // BULLET
- indentation += calculateStringWidth(font, current_str, 3);
- continue;
- }
- break;
- }
- return indentation;
-}
-
-void TBBlock::layout(bool updateFragments, bool propagateHeight) {
- // Create fragments from the word fragments
- if (updateFragments || (fragments.getFirst() == nullptr)) {
- clear();
-
- int ofs = 0;
- const char *text = str.c_str();
- while (true) {
- int frag_len;
- bool is_embed = false;
- bool more = getNextFragment(&text[ofs], styledit->packed.styling_on ? styledit->content_factory : nullptr,
- &frag_len, &is_embed);
-
- TBTextFragment *fragment = new TBTextFragment();
- if (fragment == nullptr) {
- break;
- }
-
- fragment->init(this, ofs, frag_len);
-
- if (is_embed) {
- fragment->content = styledit->content_factory->createFragmentContent(&text[ofs], frag_len);
- }
-
- fragments.addLast(fragment);
- ofs += frag_len;
-
- if (!more) {
- break;
- }
- }
- if (styledit->syntax_highlighter != nullptr) {
- styledit->syntax_highlighter->onFragmentsUpdated(this);
- }
- }
-
- // Layout
-
- if (styledit->layout_width <= 0 && styledit->getSizeAffectsLayout()) {
- // Don't layout if we have no space. This will happen when setting text
- // before the widget has been layouted. We will relayout when we are resized.
- return;
- }
-
- int old_line_width_max = line_width_max;
- line_width_max = 0;
- int line_ypos = 0;
- int first_line_indentation = 0;
- TBTextFragment *first_fragment_on_line = fragments.getFirst();
-
- while (first_fragment_on_line != nullptr) {
- int line_width = 0;
-
- // Get the last fragment that should be laid out on the line while
- // calculating line width and preliminary x positions for the fragments.
-
- TBTextFragment *last_fragment_on_line = fragments.getLast();
- if (styledit->packed.wrapping) {
- // If we should wrap, search for the last allowed break point before the overflow.
- TBTextFragment *allowed_last_fragment = nullptr;
-
- int line_xpos = first_line_indentation;
- for (TBTextFragment *fragment = first_fragment_on_line; fragment != nullptr;
- fragment = fragment->getNext()) {
- // Give the fragment the current x. Then tab widths are calculated properly in GetWidth.
- fragment->xpos = line_xpos;
- int fragment_w = fragment->getWidth(this, styledit->font);
-
- // Check if we overflow
- bool overflow = line_xpos + fragment_w > styledit->layout_width;
-
- if (overflow && (allowed_last_fragment != nullptr)) {
- last_fragment_on_line = allowed_last_fragment;
- break;
- }
-
- // Check if this is a allowed break position
- if (fragment->getAllowBreakAfter(this)) {
- if ((fragment->getNext() == nullptr) || fragment->getNext()->getAllowBreakBefore(this)) {
- allowed_last_fragment = fragment;
- line_width = line_xpos + fragment_w;
- }
- }
-
- line_xpos += fragment_w;
- }
- if (allowed_last_fragment == nullptr) {
- line_width = line_xpos;
- }
- } else {
- // When wrapping is off, just measure and set pos.
- line_width = first_line_indentation;
- for (TBTextFragment *fragment = first_fragment_on_line; fragment != nullptr;
- fragment = fragment->getNext()) {
- fragment->xpos = line_width;
- line_width += fragment->getWidth(this, styledit->font);
- }
- }
-
- // Commit line - Layout each fragment on the line.
-
- int line_height = 0;
- int line_baseline = 0;
- TBTextFragment *fragment = first_fragment_on_line;
- while (fragment != nullptr) {
- line_height = Max(fragment->getHeight(this, styledit->font), line_height);
- line_baseline = Max(fragment->getBaseline(this, styledit->font), line_baseline);
-
- // These positions are not final. Will be adjusted below.
- fragment->ypos = line_ypos;
-
- if (fragment == last_fragment_on_line) {
- break;
- }
- fragment = fragment->getNext();
- }
-
- // Adjust the position of fragments on the line - now when we know the line totals.
- // x change because of alignment, y change because of fragment baseline vs line baseline.
-
- int32_t xofs = 0;
- if (align == TB_TEXT_ALIGN_RIGHT) {
- xofs = styledit->layout_width - line_width;
- } else if (align == TB_TEXT_ALIGN_CENTER) {
- xofs = (styledit->layout_width - line_width) / 2;
- }
-
- int adjusted_line_height = line_height;
- fragment = first_fragment_on_line;
- while (fragment != nullptr) {
- // The fragment need to know these later.
- fragment->line_ypos = line_ypos;
- fragment->line_height = line_height;
-
- // Adjust the position
- fragment->ypos += line_baseline - fragment->getBaseline(this, styledit->font);
- fragment->xpos += xofs;
-
- // We now know the final position so update content.
- fragment->updateContentPos(this);
-
- // Total line height may now have changed a bit.
- adjusted_line_height =
- Max(adjusted_line_height, line_baseline - fragment->getBaseline(this, styledit->font) +
- fragment->getHeight(this, styledit->font));
-
- if (fragment == last_fragment_on_line) {
- break;
- }
- fragment = fragment->getNext();
- }
-
- // Update line_height set on fragments if needed
- if (line_height != adjusted_line_height) {
- for (fragment = first_fragment_on_line; fragment != last_fragment_on_line->getNext();
- fragment = fragment->getNext()) {
- fragment->line_height = adjusted_line_height;
- }
- }
-
- line_width_max = Max(line_width_max, line_width);
-
- // This was the first line so calculate the indentation to use for the other lines.
- if (styledit->packed.wrapping && first_fragment_on_line == fragments.getFirst()) {
- first_line_indentation =
- getStartIndentation(styledit->font, last_fragment_on_line->ofs + last_fragment_on_line->len);
- }
-
- // Consume line
-
- line_ypos += adjusted_line_height;
-
- first_fragment_on_line = last_fragment_on_line->getNext();
- }
-
- ypos = getPrev() != nullptr ? getPrev()->ypos + getPrev()->height : 0;
- setSize(old_line_width_max, line_width_max, line_ypos, propagateHeight);
-
- invalidate();
-}
-
-void TBBlock::setSize(int32_t oldW, int32_t newW, int32_t newH, bool propagateHeight) {
- // Later: could optimize with Scroll here.
- int32_t dh = newH - height;
- height = newH;
- if (dh != 0 && propagateHeight) {
- TBBlock *block = getNext();
- while (block != nullptr) {
- block->ypos = block->getPrev()->ypos + block->getPrev()->height;
- block->invalidate();
- block = block->getNext();
- }
- }
-
- // Update content_width and content_height
- // content_width can only be calculated in constant time if we grow larger.
- // If we shrink our width and where equal to content_width, we don't know
- // how wide the widest block is and we set a flag to update it when needed.
-
- if (!styledit->packed.wrapping && !styledit->packed.multiline_on) {
- styledit->content_width = newW;
- } else if (newW > styledit->content_width) {
- styledit->content_width = newW;
- } else if (newW < oldW && oldW == styledit->content_width) {
- styledit->packed.calculate_content_width_needed = 1;
- }
-
- styledit->content_height = styledit->blocks.getLast()->ypos + styledit->blocks.getLast()->height;
-
- if ((styledit->listener != nullptr) && styledit->packed.lock_scrollbars_counter == 0 && propagateHeight) {
- styledit->listener->updateScrollbars();
- }
-}
-
-TBTextFragment *TBBlock::findFragment(int32_t ofs, bool preferFirst) const {
- TBTextFragment *fragment = fragments.getFirst();
- while (fragment != nullptr) {
- if (preferFirst && ofs <= fragment->ofs + fragment->len) {
- return fragment;
- }
- if (!preferFirst && ofs < fragment->ofs + fragment->len) {
- return fragment;
- }
- fragment = fragment->getNext();
- }
- return fragments.getLast();
-}
-
-TBTextFragment *TBBlock::findFragment(int32_t x, int32_t y) const {
- TBTextFragment *fragment = fragments.getFirst();
- while (fragment != nullptr) {
- if (y < fragment->line_ypos + fragment->line_height) {
- if (x < fragment->xpos + fragment->getWidth(this, styledit->font)) {
- return fragment;
- }
- if ((fragment->getNext() != nullptr) && fragment->getNext()->line_ypos > fragment->line_ypos) {
- return fragment;
- }
- }
- fragment = fragment->getNext();
- }
- return fragments.getLast();
-}
-
-void TBBlock::invalidate() const {
- if (styledit->listener != nullptr) {
- styledit->listener->invalidate(TBRect(0, -styledit->scroll_y + ypos, styledit->layout_width, height));
- }
-}
-
-void TBBlock::buildSelectionRegion(int32_t translateX, int32_t translateY, TBTextProps *props, TBRegion &bgRegion,
- TBRegion &fgRegion) {
- if (!styledit->selection.isBlockSelected(this)) {
- return;
- }
-
- TBPaintProps paint_props;
- paint_props.block = this;
- paint_props.props = props;
- paint_props.translate_x = translateX;
- paint_props.translate_y = translateY + ypos;
-
- TBTextFragment *fragment = fragments.getFirst();
- while (fragment != nullptr) {
- fragment->buildSelectionRegion(&paint_props, bgRegion, fgRegion);
- fragment = fragment->getNext();
- }
-}
-
-void TBBlock::paint(int32_t translateX, int32_t translateY, TBTextProps *props) {
- TMPDEBUG(styledit->listener->DrawRect(TBRect(translate_x, translate_y + ypos, styledit->layout_width, height),
- TBColor(255, 200, 0, 128)));
-
- TBPaintProps paint_props;
- paint_props.block = this;
- paint_props.props = props;
- paint_props.translate_x = translateX;
- paint_props.translate_y = translateY + ypos;
-
- if (styledit->syntax_highlighter != nullptr) {
- styledit->syntax_highlighter->onPaintBlock(&paint_props);
- }
-
- TBTextFragment *fragment = fragments.getFirst();
- while (fragment != nullptr) {
- if (styledit->syntax_highlighter != nullptr) {
- styledit->syntax_highlighter->onBeforePaintFragment(&paint_props, fragment);
- }
-
- fragment->paint(&paint_props);
-
- if (styledit->syntax_highlighter != nullptr) {
- styledit->syntax_highlighter->onAfterPaintFragment(&paint_props, fragment);
- }
-
- fragment = fragment->getNext();
- }
-}
-
-// == TBTextFragment =========================================================================
-
-TBTextFragment::~TBTextFragment() {
- delete content;
-}
-
-void TBTextFragment::init(const TBBlock *block, uint16_t ofs, uint16_t len) {
- this->ofs = ofs;
- this->len = len;
- m_packed.is_break = str(block)[0] == '\r' || str(block)[0] == '\n';
- m_packed.is_space = is_space(str(block)[0]);
- m_packed.is_tab = str(block)[0] == '\t';
-}
-
-void TBTextFragment::updateContentPos(const TBBlock *block) {
- if (content != nullptr) {
- content->updatePos(block, xpos, ypos + block->ypos);
- }
-}
-
-void TBTextFragment::buildSelectionRegion(const TBPaintProps *props, TBRegion &bgRegion, TBRegion &fgRegion) {
- const TBBlock *block = props->block;
- if (!block->styledit->selection.isFragmentSelected(block, this)) {
- return;
- }
-
- const int x = props->translate_x + xpos;
- const int y = props->translate_y + ypos;
- TBFontFace *font = props->props->getFont();
-
- if (content != nullptr) {
- // Selected embedded content should add to the foreground region.
- fgRegion.includeRect(TBRect(x, y, getWidth(block, font), getHeight(block, font)));
- return;
- }
-
- // Selected text should add to the backgroud region.
- TBSelection *sel = &block->styledit->selection;
-
- int sofs1 = sel->start.block == block ? sel->start.ofs : 0;
- int sofs2 = sel->stop.block == block ? sel->stop.ofs : block->str_len;
- sofs1 = Max(sofs1, (int)ofs);
- sofs2 = Min(sofs2, (int)(ofs + len));
-
- int s1x = getStringWidth(block, font, block->str.c_str() + ofs, sofs1 - ofs);
- int s2x = getStringWidth(block, font, block->str.c_str() + sofs1, sofs2 - sofs1);
-
- bgRegion.includeRect(TBRect(x + s1x, y, s2x, getHeight(block, font)));
-}
-
-void TBTextFragment::paint(const TBPaintProps *props) {
- TBStyleEditListener *listener = props->block->styledit->listener;
-
- const int x = props->translate_x + xpos;
- const int y = props->translate_y + ypos;
- const TBColor color = props->props->data->text_color;
- TBFontFace *font = props->props->getFont();
- TBBlock *block = props->block;
-
- if (content != nullptr) {
- content->paint(props, this);
- return;
- }
- TMPDEBUG(
- listener->DrawRect(TBRect(x, y, getWidth(block, font), getHeight(block, font)), TBColor(255, 255, 255, 128)));
-
- if (block->styledit->packed.password_on) {
- const int len = SDL_strlen(special_char_password);
- int cw = block->calculateStringWidth(font, special_char_password, len);
- int num_char = utf8::count_characters(str(block), len);
- for (int i = 0; i < num_char; i++) {
- listener->drawString(x + i * cw, y, font, color, special_char_password, len);
- }
- } else if (block->styledit->packed.show_whitespace) {
- if (isTab()) {
- listener->drawString(x, y, font, color, special_char_tab, SDL_strlen(special_char_tab));
- } else if (isBreak()) {
- listener->drawString(x, y, font, color, special_char_newln, SDL_strlen(special_char_newln));
- } else if (isSpace()) {
- listener->drawString(x, y, font, color, special_char_space, SDL_strlen(special_char_space));
- } else {
- listener->drawString(x, y, font, color, str(block), len);
- }
- } else if (!isTab() && !isBreak() && !isSpace()) {
- listener->drawString(x, y, font, color, str(block), len);
- }
-
- if (props->props->data->underline) {
- int line_h = font->getHeight() / 16;
- line_h = Max(line_h, 1);
- listener->drawRectFill(TBRect(x, y + getBaseline(block, font) + 1, getWidth(block, font), line_h), color);
- }
-}
-
-void TBTextFragment::click(const TBBlock *block, int button, uint32_t modifierkeys) {
- if (content != nullptr) {
- content->click(block, this, button, modifierkeys);
- }
-}
-
-int32_t TBTextFragment::getWidth(const TBBlock *block, TBFontFace *font) {
- if (m_packed.is_width_valid) {
- return m_packed.width;
- }
- int32_t width = 0;
- if (content != nullptr) {
- width = content->getWidth(block, font, this);
- } else if (isBreak()) {
- width = 0;
- } else if (isTab()) {
- width = block->calculateTabWidth(font, xpos);
- } else {
- width = block->calculateStringWidth(font, block->str.c_str() + ofs, len);
- }
- if ((((uint32_t)width) & WIDTH_CACHE_MASK) == (uint32_t)width) {
- m_packed.is_width_valid = 1;
- m_packed.width = (uint32_t)width;
- }
- return width;
-}
-
-int32_t TBTextFragment::getHeight(const TBBlock *block, TBFontFace *font) {
- if (content != nullptr) {
- return content->getHeight(block, font, this);
- }
- return block->calculateLineHeight(font);
-}
-
-int32_t TBTextFragment::getBaseline(const TBBlock *block, TBFontFace *font) {
- if (content != nullptr) {
- return content->getBaseline(block, font, this);
- }
- return block->calculateBaseline(font);
-}
-
-int32_t TBTextFragment::getCharX(const TBBlock *block, TBFontFace *font, int32_t ofs) {
- core_assert(ofs >= 0 && ofs <= len);
-
- if (isEmbedded() || isTab()) {
- return ofs == 0 ? 0 : getWidth(block, font);
- }
- if (isBreak()) {
- return 0;
- }
-
- return block->calculateStringWidth(font, block->str.c_str() + this->ofs, ofs);
-}
-
-int32_t TBTextFragment::getCharOfs(const TBBlock *block, TBFontFace *font, int32_t x) {
- if (isEmbedded() || isTab()) {
- return x > getWidth(block, font) / 2 ? 1 : 0;
- }
- if (isBreak()) {
- return 0;
- }
-
- const char *str = block->str.c_str() + ofs;
- int i = 0;
- while (i < len) {
- int pos = i;
- utf8::move_inc(str, &i, len);
- int last_char_len = i - pos;
- // Always measure from the beginning of the fragment because of eventual kerning & text shaping etc.
- int width_except_last_char = block->calculateStringWidth(font, str, i - last_char_len);
- int width = block->calculateStringWidth(font, str, i);
- if (x < width - (width - width_except_last_char) / 2) {
- return pos;
- }
- }
- return len;
-}
-
-int32_t TBTextFragment::getStringWidth(const TBBlock *block, TBFontFace *font, const char *str, int len) {
- if (len == 0) {
- return 0;
- }
- if (len == this->len) {
- return getWidth(block, font);
- }
- if (isTab()) {
- return block->calculateTabWidth(font, xpos);
- }
- if (isBreak()) {
- return 8;
- }
- return block->calculateStringWidth(font, str, len);
-}
-
-bool TBTextFragment::getAllowBreakBefore(const TBBlock *block) const {
- if (content != nullptr) {
- return content->getAllowBreakBefore(block);
- }
- return (len != 0U) && !is_never_break_before(block->str.c_str(), ofs);
-}
-
-bool TBTextFragment::getAllowBreakAfter(const TBBlock *block) const {
- if (content != nullptr) {
- return content->getAllowBreakAfter(block);
- }
- return (len != 0U) && !is_never_break_after(block->str.c_str(), ofs + len - 1);
-}
-
-// ============================================================================
-
-TBStyleEdit::TBStyleEdit()
- : listener(nullptr), content_factory(&default_content_factory), syntax_highlighter(nullptr), layout_width(0),
- layout_height(0), content_width(0), content_height(0), caret(nullptr), selection(nullptr), scroll_x(0),
- scroll_y(0), select_state(0), mousedown_fragment(nullptr), font(nullptr), align(TB_TEXT_ALIGN_LEFT),
- packed_init(0) {
- caret.styledit = this;
- selection.styledit = this;
- TMPDEBUG(packed.show_whitespace = true);
-
- font_desc = g_font_manager->getDefaultFontDescription();
- font = g_font_manager->getFontFace(font_desc);
-
-#ifdef TB_TARGET_WINDOWS
- packed.win_style_br = 1;
-#endif
- packed.selection_on = 1;
-
- clear();
-}
-
-TBStyleEdit::~TBStyleEdit() {
- listener->caretBlinkStop();
- clear(false);
-}
-
-void TBStyleEdit::setListener(TBStyleEditListener *listener) {
- this->listener = listener;
-}
-
-void TBStyleEdit::setContentFactory(TBTextFragmentContentFactory *contentFactory) {
- if (contentFactory != nullptr) {
- this->content_factory = contentFactory;
- } else {
- this->content_factory = &default_content_factory;
- }
-}
-
-void TBStyleEdit::setSyntaxHighlighter(TBSyntaxHighlighter *syntaxHighlighter) {
- this->syntax_highlighter = syntaxHighlighter;
- reformat(true);
-}
-
-void TBStyleEdit::setFont(const TBFontDescription &fontDesc) {
- if (this->font_desc == fontDesc) {
- return;
- }
- this->font_desc = fontDesc;
- font = g_font_manager->getFontFace(fontDesc);
- reformat(true);
-}
-
-void TBStyleEdit::clear(bool initNew) {
- undoredo.clear(true, true);
- selection.selectNothing();
-
- if (initNew && (blocks.getFirst() != nullptr) && isEmpty()) {
- return;
- }
-
- for (TBBlock *block = blocks.getFirst(); block != nullptr; block = block->getNext()) {
- block->invalidate();
- }
- blocks.deleteAll();
-
- if (initNew) {
- blocks.addLast(new TBBlock(this));
- blocks.getFirst()->set("", 0);
- }
-
- caret.place(blocks.getFirst(), 0);
- caret.updateWantedX();
-}
-
-void TBStyleEdit::scrollIfNeeded(bool x, bool y) {
- if (layout_width <= 0 || layout_height <= 0) {
- return; // This is likely during construction before layout.
- }
-
- int32_t newx = scroll_x;
- int32_t newy = scroll_y;
- if (x) {
- if (caret.x - scroll_x < 0) {
- newx = caret.x;
- }
- if (caret.x + caret.width - scroll_x > layout_width) {
- newx = caret.x + caret.width - layout_width;
- }
- }
- if (y) {
- if (caret.y - scroll_y < 0) {
- newy = caret.y;
- }
- if (caret.y + caret.height - scroll_y > layout_height) {
- newy = caret.y + caret.height - layout_height;
- }
- }
- setScrollPos(newx, newy);
-}
-
-void TBStyleEdit::setScrollPos(int32_t x, int32_t y) {
- x = Min(x, getContentWidth() - layout_width);
- y = Min(y, getContentHeight() - layout_height);
- x = Max(x, 0);
- y = Max(y, 0);
- if (!packed.multiline_on) {
- y = 0;
- }
- int dx = scroll_x - x;
- int dy = scroll_y - y;
- if ((dx != 0) || (dy != 0)) {
- scroll_x = x;
- scroll_y = y;
- listener->scroll(dx, dy);
- }
-}
-
-void TBStyleEdit::beginLockScrollbars() {
- packed.lock_scrollbars_counter++;
-}
-
-void TBStyleEdit::endLockScrollbars() {
- packed.lock_scrollbars_counter--;
- if ((listener != nullptr) && packed.lock_scrollbars_counter == 0) {
- listener->updateScrollbars();
- }
-}
-
-void TBStyleEdit::setLayoutSize(int32_t width, int32_t height, bool isVirtualReformat) {
- if (width == layout_width && height == layout_height) {
- return;
- }
-
- bool doReformat = layout_width != width;
- layout_width = width;
- layout_height = height;
-
- if (doReformat && getSizeAffectsLayout()) {
- reformat(false);
- }
-
- caret.updatePos();
- caret.updateWantedX();
-
- if (!isVirtualReformat) {
- setScrollPos(scroll_x, scroll_y); ///< Trig a bounds check (scroll if outside)
- }
-}
-
-bool TBStyleEdit::getSizeAffectsLayout() const {
- return packed.wrapping || align != TB_TEXT_ALIGN_LEFT;
-}
-
-void TBStyleEdit::reformat(bool updateFragments) {
- int ypos = 0;
- beginLockScrollbars();
- TBBlock *block = blocks.getFirst();
- while (block != nullptr) {
- // Update ypos directly instead of using "propagate_height" since propagating
- // would iterate forward through all remaining blocks and we're going to visit
- // them all anyway.
- block->ypos = ypos;
- block->layout(updateFragments, false);
- ypos += block->height;
- block = block->getNext();
- }
- endLockScrollbars();
- listener->invalidate(TBRect(0, 0, layout_width, layout_height));
-}
-
-int32_t TBStyleEdit::getContentWidth() {
- if (packed.calculate_content_width_needed) {
- packed.calculate_content_width_needed = 0;
- content_width = 0;
- TBBlock *block = blocks.getFirst();
- while (block != nullptr) {
- content_width = Max(content_width, block->line_width_max);
- block = block->getNext();
- }
- }
- return content_width;
-}
-
-int32_t TBStyleEdit::getContentHeight() const {
- return content_height;
-}
-
-void TBStyleEdit::paint(const TBRect &rect, const TBFontDescription &fontDesc, const TBColor &textColor) {
- text_props.reset(fontDesc, textColor);
-
- // Find the first visible block
- TBBlock *first_visible_block = blocks.getFirst();
- while (first_visible_block != nullptr) {
- if (first_visible_block->ypos + first_visible_block->height - scroll_y >= 0) {
- break;
- }
- first_visible_block = first_visible_block->getNext();
- }
-
- // Get the selection region for all visible blocks
- TBRegion bg_region;
- TBRegion fg_region;
- if (selection.isSelected()) {
- TBBlock *block = first_visible_block;
- while (block != nullptr) {
- if (block->ypos - scroll_y > rect.y + rect.h) {
- break;
- }
- block->buildSelectionRegion(-scroll_x, -scroll_y, &text_props, bg_region, fg_region);
- block = block->getNext();
- }
-
- // Paint bg selection
- for (int i = 0; i < bg_region.getNumRects(); i++) {
- listener->drawTextSelectionBg(bg_region.getRect(i));
- }
- }
-
- // Paint the content
- TBBlock *block = first_visible_block;
- while (block != nullptr) {
- if (block->ypos - scroll_y > rect.y + rect.h) {
- break;
- }
- block->paint(-scroll_x, -scroll_y, &text_props);
- block = block->getNext();
- }
-
- // Paint fg selection
- for (int i = 0; i < fg_region.getNumRects(); i++) {
- listener->drawTextSelectionBg(fg_region.getRect(i));
- }
-
- // Paint caret
- caret.paint(-scroll_x, -scroll_y);
-}
-
-void TBStyleEdit::insertBreak() {
- if (!packed.multiline_on) {
- return;
- }
-
- const char *new_line_str = "\n";
-
- // If we stand at the end and don't have any ending break, we're standing at the last line and
- // should insert breaks twice. One to end the current line, and one for the new empty line.
- if (caret.pos.ofs == caret.pos.block->str_len && !caret.pos.block->fragments.getLast()->isBreak()) {
- new_line_str = "\n\n";
- }
-
- insertText(new_line_str);
-
- caret.avoidLineBreak();
- if (caret.pos.block->getNext() != nullptr) {
- caret.place(caret.pos.block->getNext(), 0);
- }
-}
-
-void TBStyleEdit::insertText(const char *text, bool afterLast, bool clearUndoRedo) {
- const int len = SDL_strlen(text);
- selection.removeContent();
-
- if (afterLast) {
- caret.place(blocks.getLast(), blocks.getLast()->str_len, false);
- }
-
- int32_t len_inserted = caret.pos.block->insertText(caret.pos.ofs, text, len, true);
- if (clearUndoRedo) {
- undoredo.clear(true, true);
- } else {
- undoredo.commit(this, caret.getGlobalOfs(), len_inserted, text, true);
- }
-
- caret.place(caret.pos.block, caret.pos.ofs + len, false);
- caret.updatePos();
- caret.updateWantedX();
-}
-
-TBBlock *TBStyleEdit::findBlock(int32_t y) const {
- TBBlock *block = blocks.getFirst();
- while (block != nullptr) {
- if (y < block->ypos + block->height) {
- return block;
- }
- block = block->getNext();
- }
- return blocks.getLast();
-}
-
-bool TBStyleEdit::keyDown(int key, SPECIAL_KEY specialKey, MODIFIER_KEYS modifierkeys) {
- if (select_state != 0) {
- return false;
- }
-
- bool handled = true;
- bool move_caret = specialKey == TB_KEY_LEFT || specialKey == TB_KEY_RIGHT || specialKey == TB_KEY_UP ||
- specialKey == TB_KEY_DOWN || specialKey == TB_KEY_HOME || specialKey == TB_KEY_END ||
- specialKey == TB_KEY_PAGE_UP || specialKey == TB_KEY_PAGE_DOWN;
-
- if (((modifierkeys & TB_SHIFT) == 0U) && move_caret) {
- selection.selectNothing();
- }
-
- TBTextOfs old_caret_pos = caret.pos;
- TBTextFragment *old_caret_elm = caret.getFragment();
-
- if ((specialKey == TB_KEY_UP || specialKey == TB_KEY_DOWN) && ((modifierkeys & TB_CTRL) != 0U)) {
- int32_t line_height = old_caret_pos.block->calculateLineHeight(font);
- int32_t new_y = scroll_y + (specialKey == TB_KEY_UP ? -line_height : line_height);
- setScrollPos(scroll_x, new_y);
- } else if (specialKey == TB_KEY_LEFT) {
- caret.move(false, (modifierkeys & TB_CTRL) != 0U);
- } else if (specialKey == TB_KEY_RIGHT) {
- caret.move(true, (modifierkeys & TB_CTRL) != 0U);
- } else if (specialKey == TB_KEY_UP) {
- handled = caret.place(TBPoint(caret.wanted_x, old_caret_pos.block->ypos + old_caret_elm->line_ypos - 1));
- } else if (specialKey == TB_KEY_DOWN) {
- handled = caret.place(TBPoint(caret.wanted_x, old_caret_pos.block->ypos + old_caret_elm->line_ypos +
- old_caret_elm->line_height + 1));
- } else if (specialKey == TB_KEY_PAGE_UP) {
- caret.place(TBPoint(caret.wanted_x, caret.y - layout_height));
- } else if (specialKey == TB_KEY_PAGE_DOWN) {
- caret.place(TBPoint(caret.wanted_x, caret.y + layout_height + old_caret_elm->line_height));
- } else if (specialKey == TB_KEY_HOME && ((modifierkeys & TB_CTRL) != 0U)) {
- caret.place(TBPoint(0, 0));
- } else if (specialKey == TB_KEY_END && ((modifierkeys & TB_CTRL) != 0U)) {
- caret.place(TBPoint(32000, blocks.getLast()->ypos + blocks.getLast()->height));
- } else if (specialKey == TB_KEY_HOME) {
- caret.place(TBPoint(0, caret.y));
- } else if (specialKey == TB_KEY_END) {
- caret.place(TBPoint(32000, caret.y));
- } else if (key == '8' && ((modifierkeys & TB_CTRL) != 0U)) {
- packed.show_whitespace = !packed.show_whitespace;
- listener->invalidate(TBRect(0, 0, layout_width, layout_height));
- } else if (!packed.read_only && (specialKey == TB_KEY_DELETE || specialKey == TB_KEY_BACKSPACE)) {
- if (!selection.isSelected()) {
- caret.move(specialKey == TB_KEY_DELETE, (modifierkeys & TB_CTRL) != 0U);
- selection.selectToCaret(old_caret_pos.block, old_caret_pos.ofs);
- }
- selection.removeContent();
- } else if (!packed.read_only && ((modifierkeys & TB_SHIFT) == 0U) &&
- (specialKey == TB_KEY_TAB && packed.multiline_on)) {
- insertText("\t", 1);
- } else if (!packed.read_only && (specialKey == TB_KEY_ENTER && packed.multiline_on) &&
- ((modifierkeys & TB_CTRL) == 0U)) {
- insertBreak();
- } else if (!packed.read_only && ((key != 0) && ((modifierkeys & TB_CTRL) == 0U)) && specialKey != TB_KEY_ENTER) {
- char utf8[8];
- const int len = utf8::encode(key, utf8);
- utf8[len] = '\0';
- insertText(utf8);
- } else {
- handled = false;
- }
-
- if (((modifierkeys & TB_SHIFT) != 0U) && move_caret) {
- selection.selectToCaret(old_caret_pos.block, old_caret_pos.ofs);
- }
-
- if (!(specialKey == TB_KEY_UP || specialKey == TB_KEY_DOWN || specialKey == TB_KEY_PAGE_UP ||
- specialKey == TB_KEY_PAGE_DOWN)) {
- caret.updateWantedX();
- }
-
- caret.resetBlink();
-
- // Hooks
- if (!move_caret && handled) {
- invokeOnChange();
- }
- if (specialKey == TB_KEY_ENTER && ((modifierkeys & TB_CTRL) == 0U)) {
- if (listener->onEnter()) {
- handled = true;
- }
- }
- if (handled) {
- scrollIfNeeded();
- }
-
- return handled;
-}
-
-void TBStyleEdit::cut() {
- if (packed.password_on) {
- return;
- }
- copy();
- keyDown(0, TB_KEY_DELETE, TB_MODIFIER_NONE);
-}
-
-void TBStyleEdit::copy() {
- if (packed.password_on) {
- return;
- }
- selection.copyToClipboard();
-}
-
-void TBStyleEdit::paste() {
- core::String text;
- if (TBClipboard::hasText() && TBClipboard::getText(text)) {
- insertText(text.c_str(), text.size());
- scrollIfNeeded(true, true);
- invokeOnChange();
- }
-}
-
-void TBStyleEdit::del() {
- if (selection.isSelected()) {
- selection.removeContent();
- invokeOnChange();
- }
-}
-
-void TBStyleEdit::undo() {
- if (canUndo()) {
- undoredo.undo(this);
- invokeOnChange();
- }
-}
-
-void TBStyleEdit::redo() {
- if (canRedo()) {
- undoredo.redo(this);
- invokeOnChange();
- }
-}
-
-bool TBStyleEdit::mouseDown(const TBPoint &point, int button, int clicks, MODIFIER_KEYS modifierkeys, bool touch) {
- if (button != 1) {
- return false;
- }
-
- if (touch) {
- mousedown_point = TBPoint(point.x + scroll_x, point.y + scroll_y);
- } else if (packed.selection_on) {
- // if (modifierkeys & P_SHIFT) // Select to new caretpos
- //{
- //}
- // else // Start selection
- {
- mousedown_point = TBPoint(point.x + scroll_x, point.y + scroll_y);
- selection.selectNothing();
-
- // clicks is 1 to infinite, and here we support only doubleclick, so make it either single or double.
- select_state = ((clicks - 1) % 2) + 1;
-
- mouseMove(point);
-
- if (caret.pos.block != nullptr) {
- mousedown_fragment =
- caret.pos.block->findFragment(mousedown_point.x, mousedown_point.y - caret.pos.block->ypos);
- }
- }
- caret.resetBlink();
- }
- return true;
-}
-
-bool TBStyleEdit::mouseUp(const TBPoint &point, int button, MODIFIER_KEYS modifierkeys, bool touch) {
- if (button != 1) {
- return false;
- }
-
- if (touch && !TBWidget::cancel_click) {
- selection.selectNothing();
- caret.place(mousedown_point);
- caret.updateWantedX();
- caret.resetBlink();
- }
-
- select_state = 0;
- if ((caret.pos.block != nullptr) && !TBWidget::cancel_click) {
- TBTextFragment *fragment =
- caret.pos.block->findFragment(point.x + scroll_x, point.y + scroll_y - caret.pos.block->ypos);
- if ((fragment != nullptr) && fragment == mousedown_fragment) {
- fragment->click(caret.pos.block, button, modifierkeys);
- }
- }
- return true;
-}
-
-bool TBStyleEdit::mouseMove(const TBPoint &point) {
- if (select_state != 0) {
- TBPoint p(point.x + scroll_x, point.y + scroll_y);
- selection.select(mousedown_point, p);
-
- if (select_state == 2) {
- bool has_initial_selection = selection.isSelected();
-
- if (has_initial_selection) {
- caret.place(selection.start.block, selection.start.ofs);
- }
- caret.move(false, true);
- selection.start.set(caret.pos);
-
- if (has_initial_selection) {
- caret.place(selection.stop.block, selection.stop.ofs);
- }
- caret.move(true, true);
- selection.stop.set(caret.pos);
-
- selection.correctOrder();
- caret.updateWantedX();
- }
- return true;
- }
- return false;
-}
-
-void TBStyleEdit::focus(bool focus) {
- if (focus) {
- listener->caretBlinkStart();
- } else {
- listener->caretBlinkStop();
- }
-
- caret.on = focus;
- caret.invalidate();
- selection.invalidate();
-}
-
-bool TBStyleEdit::setText(const char *text, TB_CARET_POS pos) {
- return setText(text, SDL_strlen(text), pos);
-}
-
-bool TBStyleEdit::setText(const char *text, int textLen, TB_CARET_POS pos) {
- if ((text == nullptr) || (*text == 0)) {
- clear(true);
- caret.updateWantedX();
- scrollIfNeeded(true, true);
- return true;
- }
-
- clear(true);
- blocks.getFirst()->insertText(0, text, textLen, true);
-
- caret.place(blocks.getFirst(), 0);
- caret.updateWantedX();
- scrollIfNeeded(true, false);
-
- if (pos == TB_CARET_POS_END) {
- caret.place(blocks.getLast(), blocks.getLast()->str_len);
- }
-
- invokeOnChange();
- return true;
-}
-
-bool TBStyleEdit::getText(core::String &text) {
- TBSelection tmp_selection(this);
- tmp_selection.selectAll();
- return tmp_selection.getText(text);
-}
-
-void TBStyleEdit::invokeOnChange() {
- listener->onChange();
- if (syntax_highlighter != nullptr) {
- syntax_highlighter->onChange(this);
- }
-}
-
-bool TBStyleEdit::isEmpty() const {
- return blocks.getFirst() == blocks.getLast() && blocks.getFirst()->str.empty();
-}
-
-void TBStyleEdit::setAlign(TB_TEXT_ALIGN align) {
- this->align = align;
- // Call SetAlign on all blocks currently selected, or the block of the current caret position.
- TBBlock *start = selection.isSelected() ? selection.start.block : caret.pos.block;
- TBBlock *stop = selection.isSelected() ? selection.stop.block : caret.pos.block;
- while ((start != nullptr) && start != stop->getNext()) {
- start->setAlign(align);
- start = start->getNext();
- }
-}
-
-void TBStyleEdit::setMultiline(bool multiline) {
- packed.multiline_on = multiline;
-}
-
-void TBStyleEdit::setStyling(bool styling) {
- packed.styling_on = styling;
-}
-
-void TBStyleEdit::setReadOnly(bool readonly) {
- packed.read_only = readonly;
-}
-
-void TBStyleEdit::setSelection(bool selection) {
- packed.selection_on = selection;
-}
-
-void TBStyleEdit::setPassword(bool password) {
- if (packed.password_on == static_cast(password)) {
- return;
- }
- packed.password_on = password;
- reformat(true);
-}
-
-void TBStyleEdit::setWrapping(bool wrapping) {
- if (packed.wrapping == static_cast(wrapping)) {
- return;
- }
- packed.wrapping = wrapping;
- reformat(false);
-}
-
-// == TBUndoRedoStack ==================================================
-
-TBUndoRedoStack::~TBUndoRedoStack() {
- clear(true, true);
-}
-
-void TBUndoRedoStack::undo(TBStyleEdit *styledit) {
- if (undos.getNumItems() == 0) {
- return;
- }
- TBUndoEvent *e = undos.remove(undos.getNumItems() - 1);
- redos.add(e);
- apply(styledit, e, true);
-}
-
-void TBUndoRedoStack::redo(TBStyleEdit *styledit) {
- if (redos.getNumItems() == 0) {
- return;
- }
- TBUndoEvent *e = redos.remove(redos.getNumItems() - 1);
- undos.add(e);
- apply(styledit, e, false);
-}
-
-void TBUndoRedoStack::apply(TBStyleEdit *styledit, TBUndoEvent *e, bool reverse) {
- applying = true;
- if (e->insert == reverse) {
- styledit->selection.selectNothing();
- styledit->caret.setGlobalOfs(e->gofs, false);
- core_assert(TBTextOfs(styledit->caret.pos).getGlobalOfs(styledit) == e->gofs);
-
- TBTextOfs start = styledit->caret.pos;
- styledit->caret.setGlobalOfs(e->gofs + e->text.size(), false);
- core_assert(TBTextOfs(styledit->caret.pos).getGlobalOfs(styledit) == e->gofs + (int32_t)e->text.size());
-
- styledit->selection.select(start, styledit->caret.pos);
- styledit->selection.removeContent();
- } else {
- styledit->selection.selectNothing();
- styledit->caret.setGlobalOfs(e->gofs, true, true);
- styledit->insertText(e->text.c_str());
- int text_len = e->text.size();
- if (text_len > 1) {
- styledit->selection.select(e->gofs, e->gofs + text_len);
- }
- }
- styledit->scrollIfNeeded(true, true);
- applying = false;
-}
-
-void TBUndoRedoStack::clear(bool clearUndo, bool clearRedo) {
- core_assert(!applying);
- if (clearUndo) {
- undos.deleteAll();
- }
- if (clearRedo) {
- redos.deleteAll();
- }
-}
-
-TBUndoEvent *TBUndoRedoStack::commit(TBStyleEdit *styledit, int32_t gofs, int32_t len, const char *text, bool insert) {
- if (applying || styledit->packed.read_only) {
- return nullptr;
- }
- clear(false, true);
-
- // If we're inserting a single character, check if we want to append it to the previous event.
- if (insert && (undos.getNumItems() != 0)) {
- int num_char = utf8::count_characters(text, len);
- TBUndoEvent *e = undos[undos.getNumItems() - 1];
- if (num_char == 1 && e->insert && e->gofs + (int32_t)e->text.size() == gofs) {
- // Appending a space to other space(s) should append
- if ((text[0] == ' ' && (strpbrk(e->text.c_str(), "\r\n") == nullptr)) ||
- // But non spaces should not
- (strpbrk(e->text.c_str(), " \r\n") == nullptr)) {
- e->text.append(text, len);
- return e;
- }
- }
- }
-
- // Create a new event
- if (TBUndoEvent *e = new TBUndoEvent()) {
- e->gofs = gofs;
- e->text = core::String(text, len);
- e->insert = insert;
- undos.add(e);
- return e;
- }
-
- // OOM
- clear(true, true);
- return nullptr;
-}
-
-} // namespace tb
diff --git a/src/modules/ui/turbobadger/tb/tb_style_edit.h b/src/modules/ui/turbobadger/tb/tb_style_edit.h
deleted file mode 100644
index b7f59275d..000000000
--- a/src/modules/ui/turbobadger/tb/tb_style_edit.h
+++ /dev/null
@@ -1,516 +0,0 @@
-/**
- * @file
- */
-
-#pragma once
-
-#include "tb_core.h"
-#include "tb_linklist.h"
-#include "tb_list.h"
-#include "tb_widgets_common.h"
-
-namespace tb {
-
-class TBStyleEdit;
-class TBBlock;
-class TBTextFragment;
-class TBTextFragmentContent;
-class TBTextFragmentContentFactory;
-
-/** Listener for TBStyleEdit. Implement in the enviorment the TBStyleEdit should render its content. */
-class TBStyleEditListener {
-public:
- virtual ~TBStyleEditListener() {
- }
-
- virtual void onChange(){};
- virtual bool onEnter() {
- return false;
- };
- virtual void invalidate(const TBRect &rect) = 0;
- virtual void drawString(int32_t x, int32_t y, TBFontFace *font, const TBColor &color, const char *str,
- int32_t len) = 0;
- virtual void drawRect(const TBRect &rect, const TBColor &color) = 0;
- virtual void drawRectFill(const TBRect &rect, const TBColor &color) = 0;
- virtual void drawTextSelectionBg(const TBRect &rect) = 0;
- virtual void drawContentSelectionFg(const TBRect &rect) = 0;
- virtual void drawCaret(const TBRect &rect) = 0;
- virtual void scroll(int32_t dx, int32_t dy) = 0;
- virtual void updateScrollbars() = 0;
- virtual void caretBlinkStart() = 0;
- virtual void caretBlinkStop() = 0;
-};
-
-/** Creates TBTextFragmentContent if the sequence of text matches known content. */
-
-class TBTextFragmentContentFactory {
-public:
- virtual ~TBTextFragmentContentFactory() {
- }
- /** Should return then length of the text that represents content
- that can be created by this factory, or 0 there's no match with any content.
-
- F.ex if we can create content for @c <u> it should return 3 if that is the beginning of
- text. That length will be consumed from the text output for the created content. */
- virtual int getContent(const char *text);
-
- /** Create content for a string previosly consumed by calling GetContent. */
- virtual TBTextFragmentContent *createFragmentContent(const char *text, int text_len);
-};
-
-class TBTextOfs {
-public:
- TBTextOfs() : block(nullptr), ofs(0) {
- }
- TBTextOfs(TBBlock *block, int32_t ofs) : block(block), ofs(ofs) {
- }
-
- void set(TBBlock *newBlock, int32_t newOfs) {
- block = newBlock;
- ofs = newOfs;
- }
- void set(const TBTextOfs &pos) {
- block = pos.block;
- ofs = pos.ofs;
- }
-
- int32_t getGlobalOfs(TBStyleEdit *se) const;
- bool setGlobalOfs(TBStyleEdit *se, int32_t gofs);
-
-public:
- TBBlock *block;
- int32_t ofs;
-};
-
-/** Handles the selected text in a TBStyleEdit. */
-
-class TBSelection {
-public:
- TBSelection(TBStyleEdit *styledit);
- void invalidate() const;
- void select(const TBTextOfs &newStart, const TBTextOfs &newStop);
- void select(const TBPoint &from, const TBPoint &to);
- void select(int globOfsFrom, int globOfsTo);
- void selectToCaret(TBBlock *oldCaretBlock, int32_t oldCaretOfs);
- void selectAll();
- void selectNothing();
- void correctOrder();
- void copyToClipboard();
- bool isBlockSelected(const TBBlock *block) const;
- bool isFragmentSelected(const TBBlock *block, TBTextFragment *elm) const;
- bool isSelected() const;
- void removeContent();
- bool getText(core::String &text) const;
-
-public:
- TBStyleEdit *styledit;
- TBTextOfs start, stop;
-};
-
-enum TB_CARET_POS { TB_CARET_POS_BEGINNING, TB_CARET_POS_END };
-
-/** The caret in a TBStyleEdit. */
-class TBCaret {
-public:
- TBCaret(TBStyleEdit *styledit);
- void invalidate();
- void updatePos();
- bool move(bool forward, bool word);
- bool place(const TBPoint &point);
- bool place(TBBlock *block, int ofs, bool allowSnap = true, bool snapForward = false);
- void place(TB_CARET_POS pos);
- void avoidLineBreak();
- void paint(int32_t translateX, int32_t translateY);
- void resetBlink();
- void updateWantedX();
-
- int32_t getGlobalOfs() const {
- return pos.getGlobalOfs(styledit);
- }
- void setGlobalOfs(int32_t gofs, bool allowSnap = true, bool snapForward = false);
-
- TBTextFragment *getFragment();
-
-private:
- void switchBlock(bool second);
-
-public:
- TBStyleEdit *styledit;
- int32_t x, y; ///< Relative to the styledit
- int32_t width;
- int32_t height;
- int32_t wanted_x;
- bool on;
- bool prefer_first;
- TBTextOfs pos;
-};
-
-/** TBTextProps is a stack of properties used during layout & paint of TBStyleEdit. */
-
-class TBTextProps {
-public:
- class Data {
- public:
- TBFontDescription font_desc;
- TBColor text_color;
- bool underline = false;
- };
- TBTextProps() {
- }
- ~TBTextProps() {
- while (list.getNumItems() > 0) {
- delete list.get(0);
- list.remove(0);
- }
- }
-
- void reset(const TBFontDescription &fontDesc, const TBColor &textColor);
- Data *push();
- void pop();
-
- /** Get the font face from the current font description. */
- TBFontFace *getFont() const;
-
-public:
- int next_index = 0;
- TBListOf list;
- Data base;
- Data *data = nullptr;
-};
-
-/** TBPaintProps holds paint related data during paint of TBStyleEdit. */
-
-class TBPaintProps {
-public:
- TBBlock *block;
- TBTextProps *props;
- int32_t translate_x;
- int32_t translate_y;
-};
-
-/** A block of text (a line, that might be wrapped) */
-
-class TBBlock : public TBLinkOf {
-public:
- TBBlock(TBStyleEdit *styledit);
- ~TBBlock();
-
- void clear();
- void set(const char *newstr, int32_t len);
- void setAlign(TB_TEXT_ALIGN align);
-
- int32_t insertText(int32_t ofs, const char *text, int32_t len, bool allow_line_recurse);
- void removeContent(int32_t ofs, int32_t len);
-
- /** Check if this block contains extra line breaks and split into new blocks if it does. */
- void split();
-
- /** Check if we've lost the ending break on this block and if so merge it with the next block. */
- void merge();
-
- /** Layout the block. To be called when the text has changed or the layout width has changed.
- @param updateFragments Should be true if the text has been changed (will recreate elements).
- @param propagateHeight If true, all following blocks will be moved if the height changed. */
- void layout(bool updateFragments, bool propagateHeight);
-
- /** Update the size of this block. If propagate_height is true, all following blocks will be
- moved if the height changed. */
- void setSize(int32_t oldW, int32_t newW, int32_t newH, bool propagateHeight);
-
- TBTextFragment *findFragment(int32_t ofs, bool prefer_first = false) const;
- TBTextFragment *findFragment(int32_t x, int32_t y) const;
-
- int32_t calculateStringWidth(TBFontFace *font, const char *str, int len) const;
- int32_t calculateTabWidth(TBFontFace *font, int32_t xpos) const;
- int32_t calculateLineHeight(TBFontFace *font) const;
- int32_t calculateBaseline(TBFontFace *font) const;
-
- void invalidate() const;
- void buildSelectionRegion(int32_t translateX, int32_t translateY, TBTextProps *props, TBRegion &bgRegion,
- TBRegion &fgRegion);
- void paint(int32_t translateX, int32_t translateY, TBTextProps *props);
-
-public:
- TBStyleEdit *styledit;
- TBLinkListOf fragments;
-
- int32_t ypos;
- int16_t height;
- int8_t align;
- int line_width_max;
-
- core::String str;
- int32_t str_len;
- uint32_t syntax_data; ///< Free to use in any way from TBSyntaxHighlighter subclasses
-
-private:
- int getStartIndentation(TBFontFace *font, int first_line_len) const;
-};
-
-/** Event in the TBUndoRedoStack. Each insert or remove change is stored as a TBUndoEvent, but they may also be merged
- * when appropriate. */
-
-class TBUndoEvent {
-public:
- int32_t gofs;
- core::String text;
- bool insert;
-};
-
-/** Keeps track of all TBUndoEvents used for undo and redo functionality. */
-
-class TBUndoRedoStack {
-public:
- TBUndoRedoStack() : applying(false) {
- }
- ~TBUndoRedoStack();
-
- void undo(TBStyleEdit *styledit);
- void redo(TBStyleEdit *styledit);
- void clear(bool clearUndo, bool clearRedo);
-
- TBUndoEvent *commit(TBStyleEdit *styledit, int32_t gofs, int32_t len, const char *text, bool insert);
-
-public:
- TBListOf undos;
- TBListOf redos;
- bool applying;
-
-private:
- void apply(TBStyleEdit *styledit, TBUndoEvent *e, bool reverse);
-};
-
-/** TBSyntaxHighlighter can be subclassed to give syntax highlighting on TBStyleEdit
- without altering the text (without inserting style markup) */
-class TBSyntaxHighlighter {
-public:
- virtual ~TBSyntaxHighlighter() {
- }
-
- /** Called when all fragments has been updated in the given block and syntax info should
- be updated. syntax_data can be stored in TBBlock and TBTextFragment */
- virtual void onFragmentsUpdated(TBBlock *block) {
- }
-
- /** Called after any change in TBStyleEdit when all blocks that changed have been updated. */
- virtual void onChange(TBStyleEdit *styledit) {
- }
-
- /** Called before painting each block */
- virtual void onPaintBlock(const TBPaintProps *props) {
- }
-
- /** Called before painting each fragment */
- virtual void onBeforePaintFragment(const TBPaintProps *props, TBTextFragment *fragment) {
- }
-
- /** Called after painting each fragment */
- virtual void onAfterPaintFragment(const TBPaintProps *props, TBTextFragment *fragment) {
- }
-};
-
-/** The textfragment baseclass for TBStyleEdit.
-
- TODO: This object is allocated on vast amounts and need
- to shrink in size. Remove all cached positioning
- and implement a fragment traverser (for TBBlock).
- Also allocate fragments in chunks. */
-
-class TBTextFragment : public TBLinkOf {
-public:
- TBTextFragment(TBTextFragmentContent *content = nullptr)
- : xpos(0), ypos(0), ofs(0), len(0), line_ypos(0), line_height(0), m_packed_init(0), content(content) {
- }
- ~TBTextFragment();
-
- void init(const TBBlock *block, uint16_t ofs, uint16_t len);
-
- void updateContentPos(const TBBlock *block);
-
- void buildSelectionRegion(const TBPaintProps *props, TBRegion &bgRegion, TBRegion &fgRegion);
- void paint(const TBPaintProps *props);
- void click(const TBBlock *block, int button, uint32_t modifierkeys);
-
- bool isText() const {
- return !isEmbedded();
- }
- bool isEmbedded() const {
- return content != nullptr;
- }
- bool isBreak() const {
- return m_packed.is_break != 0;
- }
- bool isSpace() const {
- return m_packed.is_space != 0;
- }
- bool isTab() const {
- return m_packed.is_tab != 0;
- }
-
- int32_t getCharX(const TBBlock *block, TBFontFace *font, int32_t ofs);
- int32_t getCharOfs(const TBBlock *block, TBFontFace *font, int32_t x);
-
- /** Get the stringwidth. Handles passwordmode, tab, linebreaks etc automatically. */
- int32_t getStringWidth(const TBBlock *block, TBFontFace *font, const char *str, int len);
-
- bool getAllowBreakBefore(const TBBlock *block) const;
- bool getAllowBreakAfter(const TBBlock *block) const;
-
- const char *str(const TBBlock *block) const {
- return block->str.c_str() + ofs;
- }
-
- int32_t getWidth(const TBBlock *block, TBFontFace *font);
- int32_t getHeight(const TBBlock *block, TBFontFace *font);
- int32_t getBaseline(const TBBlock *block, TBFontFace *font);
-
-public:
- int16_t xpos, ypos;
- uint16_t ofs, len;
- uint16_t line_ypos, line_height;
- union {
- struct {
- uint32_t is_break : 1; ///< Fragment is hard line break
- uint32_t is_space : 1; ///< Fragment is white space
- uint32_t is_tab : 1; ///< Fragment is tab
- uint32_t syntax_data : 10; ///< Free to use in any way from TBSyntaxHighlighter subclasses
- uint32_t width : 11; ///< width cache. Bit number need to match shift in WIDTH_CACHE_MASK.
- uint32_t is_width_valid : 1; ///< width cache is set
- } m_packed;
- uint32_t m_packed_init;
- };
- static const uint32_t WIDTH_CACHE_MASK = (1 << 11) - 1;
- TBTextFragmentContent *content;
-};
-
-/** Edit and formats TBTextFragment's. It handles the text in a TBStyleEditView. */
-
-class TBStyleEdit {
-public:
- TBStyleEdit();
- virtual ~TBStyleEdit();
-
- void setListener(TBStyleEditListener *listener);
- void setContentFactory(TBTextFragmentContentFactory *content_factory);
- void setSyntaxHighlighter(TBSyntaxHighlighter *syntax_highlighter);
-
- void setFont(const TBFontDescription &font_desc);
-
- void paint(const TBRect &rect, const TBFontDescription &fontDesc, const TBColor &textColor);
- bool keyDown(int key, SPECIAL_KEY special_key, MODIFIER_KEYS modifierkeys);
- bool mouseDown(const TBPoint &point, int button, int clicks, MODIFIER_KEYS modifierkeys, bool touch);
- bool mouseUp(const TBPoint &point, int button, MODIFIER_KEYS modifierkeys, bool touch);
- bool mouseMove(const TBPoint &point);
- void focus(bool focus);
-
- void clear(bool init_new = true);
- bool setText(const char *text, TB_CARET_POS pos = TB_CARET_POS_BEGINNING);
- bool setText(const char *text, int text_len, TB_CARET_POS pos = TB_CARET_POS_BEGINNING);
- bool getText(core::String &text);
- bool isEmpty() const;
-
- /** Set the default text alignment and all currently selected blocks,
- or the block of the current caret position if nothing is selected. */
- void setAlign(TB_TEXT_ALIGN align);
- void setMultiline(bool multiline = true);
- void setStyling(bool styling = true);
- void setReadOnly(bool readonly = true);
- void setSelection(bool selection = true);
- void setPassword(bool password = true);
- void setWrapping(bool wrapping = true);
-
- void cut();
- void copy();
- void paste();
- void del();
-
- void undo();
- void redo();
- bool canUndo() const {
- return undoredo.undos.getNumItems() != 0;
- }
- bool canRedo() const {
- return undoredo.redos.getNumItems() != 0;
- }
-
- void insertText(const char *text, bool afterLast = false,
- bool clearUndoRedo = false);
- void appendText(const char *text, bool clearUndoRedo = false) {
- insertText(text, true, clearUndoRedo);
- }
- void insertBreak();
-
- TBBlock *findBlock(int32_t y) const;
-
- void scrollIfNeeded(bool x = true, bool y = true);
- void setScrollPos(int32_t x, int32_t y);
- void setLayoutSize(int32_t width, int32_t height, bool is_virtual_reformat);
- void reformat(bool update_fragments);
-
- int32_t getContentWidth();
- int32_t getContentHeight() const;
-
- int32_t getOverflowX() const {
- return Max(content_width - layout_width, 0);
- }
- int32_t getOverflowY() const {
- return Max(content_height - layout_height, 0);
- }
-
-public:
- TBStyleEditListener *listener;
- TBTextFragmentContentFactory default_content_factory;
- TBTextFragmentContentFactory *content_factory;
- TBSyntaxHighlighter *syntax_highlighter;
- int32_t layout_width;
- int32_t layout_height;
- int32_t content_width;
- int32_t content_height;
-
- TBLinkListOf