From 2e5c0de21b0f35531e3d42e63c27df80cf3fad02 Mon Sep 17 00:00:00 2001 From: dam Date: Wed, 1 Dec 2021 02:26:44 +0000 Subject: Convert from native to godot --- project.godot | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 project.godot (limited to 'project.godot') diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..8bc4dca --- /dev/null +++ b/project.godot @@ -0,0 +1,35 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +[application] + +config/name="Surgery Log" +run/main_scene="res://main.tscn" +boot_splash/image="res://icon.png" +boot_splash/fullsize=false +boot_splash/use_filter=false +boot_splash/bg_color=Color( 0, 0, 0, 1 ) +config/icon="res://icon.png" + +[display] + +window/size/width=720 +window/size/height=1280 +window/energy_saving/keep_screen_on=false +window/handheld/orientation="portrait" + +[physics] + +common/enable_pause_aware_picking=true + +[rendering] + +vram_compression/import_etc=true +environment/default_environment="res://default_env.tres" -- cgit v1.2.3 From 7d515712404db480b6ba6eb45576ecc74988acd3 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 2 Dec 2021 22:19:02 +0000 Subject: Implement date picker prototype. --- date_picker/date_picker.tscn | 147 +++++++++++++++++++++++++++++++++++++++++++ date_picker/scroll_picker.gd | 118 ++++++++++++++++++++++++++++++++++ export_presets.cfg | 6 +- main.tscn | 66 +++++++++++++------ project.godot | 4 ++ 5 files changed, 319 insertions(+), 22 deletions(-) create mode 100644 date_picker/date_picker.tscn create mode 100644 date_picker/scroll_picker.gd (limited to 'project.godot') diff --git a/date_picker/date_picker.tscn b/date_picker/date_picker.tscn new file mode 100644 index 0000000..88f98d8 --- /dev/null +++ b/date_picker/date_picker.tscn @@ -0,0 +1,147 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://date_picker/scroll_picker.gd" type="Script" id=1] + +[node name="date_picker" type="HBoxContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +alignment = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="day_scroll" type="Control" parent="."] +margin_left = 5.0 +margin_right = 239.0 +margin_bottom = 1280.0 +rect_min_size = Vector2( 234, 0 ) +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="label" type="Label" parent="day_scroll"] +anchor_right = 1.0 +text = "day" +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value_previous" type="Label" parent="day_scroll"] +anchor_right = 1.0 +margin_bottom = 80.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value" type="Label" parent="day_scroll"] +anchor_right = 1.0 +margin_top = 80.0 +margin_bottom = 160.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value_next" type="Label" parent="day_scroll"] +anchor_right = 1.0 +margin_top = 160.0 +margin_bottom = 240.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="month_scroll" type="Control" parent="."] +margin_left = 243.0 +margin_right = 477.0 +margin_bottom = 1280.0 +rect_min_size = Vector2( 234, 0 ) +script = ExtResource( 1 ) + +[node name="label" type="Label" parent="month_scroll"] +anchor_right = 1.0 +text = "month" +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value_previous" type="Label" parent="month_scroll"] +anchor_right = 1.0 +margin_bottom = 80.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value" type="Label" parent="month_scroll"] +anchor_right = 1.0 +margin_top = 80.0 +margin_bottom = 160.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value_next" type="Label" parent="month_scroll"] +anchor_right = 1.0 +margin_top = 160.0 +margin_bottom = 240.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="year_scroll" type="Control" parent="."] +margin_left = 481.0 +margin_right = 715.0 +margin_bottom = 1280.0 +rect_min_size = Vector2( 234, 0 ) +script = ExtResource( 1 ) + +[node name="label" type="Label" parent="year_scroll"] +anchor_right = 1.0 +text = "year" +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value_previous" type="Label" parent="year_scroll"] +anchor_right = 1.0 +margin_bottom = 80.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value" type="Label" parent="year_scroll"] +anchor_right = 1.0 +margin_top = 80.0 +margin_bottom = 160.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="value_next" type="Label" parent="year_scroll"] +anchor_right = 1.0 +margin_top = 160.0 +margin_bottom = 240.0 +mouse_filter = 1 +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/date_picker/scroll_picker.gd b/date_picker/scroll_picker.gd new file mode 100644 index 0000000..ba70084 --- /dev/null +++ b/date_picker/scroll_picker.gd @@ -0,0 +1,118 @@ +extends Control + +const MAX_POINTERS = 10 + +var pointer: Dictionary +var value: float = 0.0 +var anchor: float = 0.0 +var pointer_id: int = -1 +var start_pos: float = 0.0 +var pos: float = 0.0 + + +func _ready(): + pointer = { + index = -1, + initial_position = Vector2.ZERO, + current_position = Vector2.ZERO, + relative = Vector2.ZERO, + velocity = Vector2.ZERO, + is_active = false, + timestamp = 0 + } + + + +func _process(delta: float): +# $label.text = "%s" % pointer.index + pointer.velocity *= clamp((1.0 - 5.5 * delta), 0.0, 1.0) # pow(1.0-0.995, delta) + if pointer.is_active: + value = anchor + (pointer.current_position.y - pointer.initial_position.y) + elif is_zero_approx(pointer.velocity.y) == false: + value += pointer.velocity.y * delta + if abs(pointer.velocity.y) < 50.0: + var max_value := 10 + var scroll_unit_height := 80 + var normalized_value := -value / scroll_unit_height + var normalized_int_value := round(normalized_value) as int + var logic_value := fposmod(normalized_int_value, max_value) + var fix := ((normalized_int_value as float) - normalized_value) * scroll_unit_height + value -= fix * 5.0 * delta + +# pointer.timestamp = OS.get_ticks_msec() +# ($test as TextureRect).rect_global_position.y = value +# $debug.text = "value: %s\nvelocity: %s\n%s" % [value, pointer.velocity, pointer.relative] + var current_pos = value + var turn_over := 800 + if current_pos >= turn_over || current_pos < 0.0: + value = fposmod(current_pos, turn_over) +# elif current_pos < 0: +# value = 800 - current_pos + + + var max_value := 10 + var scroll_unit_height := 40 + var normalized_value := -value / scroll_unit_height + var normalized_int_value := round(normalized_value) as int + var logic_value := fposmod(normalized_int_value, max_value) + var logic_next_value := fposmod(normalized_int_value + 1, max_value) + var logic_previous_value := fposmod(normalized_int_value - 1, max_value) + + var value_base_position := 140.0 # 180.0 + var value_next_base_position := 180.0 # 260.0 + var value_previous_base_position := 100.0 + + $value.text = "%d" % logic_value + $value_next.text = "%d" % logic_next_value + $value_previous.text = "%d" % logic_previous_value +# $debug.text = "%s" % normalized_value + + ($value as Label).rect_position.y = value_base_position - (normalized_value - normalized_int_value) * scroll_unit_height + ($value_previous as Label).rect_position.y = value_previous_base_position - (normalized_value - normalized_int_value) * scroll_unit_height + ($value_next as Label).rect_position.y = value_next_base_position - (normalized_value - normalized_int_value) * scroll_unit_height + +# ($value as Label).modulate.a = (scroll_unit_height - (normalized_value - normalized_int_value) * scroll_unit_height) / (scroll_unit_height as float) +# $debug.text = "%s ..." % [normalized_int_value - normalized_value] + ($value_next as Label).modulate.a = ((normalized_value - normalized_int_value) + 0.5) + ($value_previous as Label).modulate.a = ((normalized_int_value - normalized_value) + 0.5) +# ($value_previous as Label).modulate.a = ((normalized_value + normalized_int_value) * scroll_unit_height) / (scroll_unit_height as float) +# +#func _input(event: InputEvent): +# $log.text += "> input: %s\n" % event.to_string() +# if event is InputEventScreenTouch && event.pressed == false: +# pointer.index = -1 + +func _gui_input(event: InputEvent): +# get_tree().set_input_as_handled() +# if event is InputEventScreenTouch && event.pressed == false: +# $label.text = "AUTCH" +# $log.text += "> event: %s\n" % event.to_string() + + if event is InputEventScreenTouch: +# if (event is InputEventScreenTouch && pointer.is_active && pointer.index == event.index +# || event is InputEventScreenTouch && pointer.is_active == false): + var touch := event as InputEventScreenTouch + pointer.is_active = event.pressed + pointer.current_position = touch.position + var time := OS.get_ticks_msec() + if pointer.is_active: + pointer.index = touch.index + pointer.initial_position = touch.position + anchor = value + else: + pointer.index = -1 +# elif abs(pointer.timestamp - time) > 50.0: +# pointer.velocity = Vector2.ZERO +# if pointer.is_active == false: +# $output.text += "%10d: touch %d\n" % [abs(pointer.timestamp - time), touch.index] + + if event is InputEventScreenDrag: # && pointer.index == event.index: + var drag := event as InputEventScreenDrag + pointer.current_position = drag.position + pointer.velocity = drag.speed +# $label.text = "%s"%drag.speed + pointer.relative = drag.relative + pointer.timestamp = OS.get_ticks_msec() +# $output.text += "%10d: drag %d\n" % [pointer.timestamp, drag.index] + + diff --git a/export_presets.cfg b/export_presets.cfg index 468f32f..5c563c9 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -7,7 +7,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="../builds/test.apk" +export_path="../builds/test_pico_debug.apk" script_export_mode=1 script_encryption_key="" @@ -27,7 +27,7 @@ keystore/debug_password="debug.password" keystore/release="" keystore/release_user="" keystore/release_password="" -one_click_deploy/clear_previous_install=false +one_click_deploy/clear_previous_install=true version/code=1 version/name="1.0" package/unique_name="com.gudinoff.$genname" @@ -42,7 +42,7 @@ graphics/32_bits_framebuffer=true graphics/opengl_debug=false xr_features/xr_mode=0 xr_features/hand_tracking=0 -screen/immersive_mode=true +screen/immersive_mode=false screen/support_small=true screen/support_normal=true screen/support_large=true diff --git a/main.tscn b/main.tscn index 16e73df..c3a8f2b 100644 --- a/main.tscn +++ b/main.tscn @@ -1,107 +1,119 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=3 format=2] [ext_resource path="res://main.gd" type="Script" id=1] +[ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] [node name="main" type="Node"] -[node name="ScrollContainer" type="ScrollContainer" parent="."] +[node name="TabContainer" type="TabContainer" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 32.0 +margin_right = -4.0 +margin_bottom = -4.0 scroll_horizontal_enabled = false __meta__ = { "_edit_use_anchors_": false } -[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/ScrollContainer"] margin_right = 720.0 margin_bottom = 548.0 rect_min_size = Vector2( 720, 0 ) rect_clip_content = true script = ExtResource( 1 ) -[node name="process_number" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="process_number" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_right = 720.0 margin_bottom = 24.0 placeholder_text = "Nº Processo" caret_blink = true -[node name="surgery_number" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="surgery_number" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 28.0 margin_right = 720.0 margin_bottom = 52.0 placeholder_text = "Nº Cirurgia" caret_blink = true -[node name="place" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="place" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 56.0 margin_right = 720.0 margin_bottom = 80.0 placeholder_text = "Local" caret_blink = true -[node name="anesthesia" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="anesthesia" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 84.0 margin_right = 720.0 margin_bottom = 108.0 placeholder_text = "Anesthesics" caret_blink = true -[node name="first_aider" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="first_aider" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 112.0 margin_right = 720.0 margin_bottom = 136.0 placeholder_text = "1º Ajudante" caret_blink = true -[node name="type" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="type" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 140.0 margin_right = 720.0 margin_bottom = 164.0 placeholder_text = "Tipo" caret_blink = true -[node name="sub_type" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="sub_type" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 168.0 margin_right = 720.0 margin_bottom = 192.0 placeholder_text = "Subtipo" caret_blink = true -[node name="sub_sub_type" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="sub_sub_type" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 196.0 margin_right = 720.0 margin_bottom = 220.0 placeholder_text = "Sub-Subtipo" caret_blink = true -[node name="pathology" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="pathology" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 224.0 margin_right = 720.0 margin_bottom = 248.0 placeholder_text = "Patologia" caret_blink = true -[node name="intervention" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="intervention" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 252.0 margin_right = 720.0 margin_bottom = 276.0 placeholder_text = "Intervenção" caret_blink = true -[node name="urgency" type="CheckBox" parent="ScrollContainer/VBoxContainer"] +[node name="urgency" type="CheckBox" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 280.0 margin_right = 720.0 margin_bottom = 304.0 text = "Urgência" -[node name="notes" type="LineEdit" parent="ScrollContainer/VBoxContainer"] +[node name="notes" type="LineEdit" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 308.0 margin_right = 720.0 margin_bottom = 332.0 placeholder_text = "Notas" caret_blink = true -[node name="output" type="RichTextLabel" parent="ScrollContainer/VBoxContainer"] +[node name="output" type="RichTextLabel" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 336.0 margin_right = 720.0 margin_bottom = 386.0 @@ -110,7 +122,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="timer" type="RichTextLabel" parent="ScrollContainer/VBoxContainer"] +[node name="timer" type="RichTextLabel" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 390.0 margin_right = 720.0 margin_bottom = 440.0 @@ -119,7 +131,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="button" type="Button" parent="ScrollContainer/VBoxContainer"] +[node name="button" type="Button" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 444.0 margin_right = 720.0 margin_bottom = 494.0 @@ -131,7 +143,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="log" type="RichTextLabel" parent="ScrollContainer/VBoxContainer"] +[node name="log" type="RichTextLabel" parent="TabContainer/ScrollContainer/VBoxContainer"] margin_top = 498.0 margin_right = 720.0 margin_bottom = 548.0 @@ -139,3 +151,19 @@ rect_min_size = Vector2( 0, 50 ) __meta__ = { "_edit_use_anchors_": false } + +[node name="ScrollContainer2" type="ScrollContainer" parent="TabContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 32.0 +margin_right = -4.0 +margin_bottom = -4.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/ScrollContainer2"] +margin_right = 710.0 + +[node name="date_picker" parent="TabContainer/ScrollContainer2/VBoxContainer" instance=ExtResource( 2 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 710.0 diff --git a/project.godot b/project.godot index 8bc4dca..fa00ba4 100644 --- a/project.godot +++ b/project.godot @@ -25,6 +25,10 @@ window/size/height=1280 window/energy_saving/keep_screen_on=false window/handheld/orientation="portrait" +[input_devices] + +pointing/emulate_touch_from_mouse=true + [physics] common/enable_pause_aware_picking=true -- cgit v1.2.3 From ab3e8de3e1d107d42ba62571ea7d17e741203123 Mon Sep 17 00:00:00 2001 From: dam Date: Mon, 6 Dec 2021 00:45:18 +0000 Subject: Avoid invalid dates on date picker. --- date_picker/date_picker.gd | 65 ++++++++++++++++++++ date_picker/date_picker.tscn | 48 +++++++-------- date_picker/scroll_picker.gd | 137 ------------------------------------------- date_picker/value_picker.gd | 126 +++++++++++++++++++++++++++++++++++++++ project.godot | 16 +++++ 5 files changed, 232 insertions(+), 160 deletions(-) create mode 100644 date_picker/date_picker.gd delete mode 100644 date_picker/scroll_picker.gd create mode 100644 date_picker/value_picker.gd (limited to 'project.godot') diff --git a/date_picker/date_picker.gd b/date_picker/date_picker.gd new file mode 100644 index 0000000..6298156 --- /dev/null +++ b/date_picker/date_picker.gd @@ -0,0 +1,65 @@ +extends Control + +class_name DatePicker + +const days_per_month: Dictionary = { + 1: 31, + 2: 28, + 3: 31, + 4: 30, + 5: 31, + 6: 30, + 7: 31, + 8: 31, + 9: 30, + 10: 31, + 11: 30, + 12: 31, +} + +onready var year_picker: ValuePicker = get_node("year") +onready var month_picker: ValuePicker = get_node("month") +onready var day_picker: ValuePicker = get_node("day") + + +func _process(delta: float): + var year := year_picker.value + var month := month_picker.value + var day := day_picker.value + var days_on_month: int = days_per_month[month] + + var is_leap_year := (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 + if is_leap_year && month == 2: + days_on_month = 29 + + if day > days_on_month: + day_picker.value = days_on_month + day_picker.max_value = days_on_month + + +func get_day() -> int: + return day_picker.value + + +func get_month() -> int: + return month_picker.value + + +func get_year() -> int: + return year_picker.value + + +func get_date() -> Dictionary: + return { + year = year_picker.value, + month = month_picker.value, + day = day_picker.value, + } + + +func set_date(new_year: int, new_month: int, new_day: int): + year_picker.value = new_year + month_picker.value = new_month + day_picker.value = new_day + + diff --git a/date_picker/date_picker.tscn b/date_picker/date_picker.tscn index 3414283..c7fc7c7 100644 --- a/date_picker/date_picker.tscn +++ b/date_picker/date_picker.tscn @@ -1,16 +1,18 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://date_picker/scroll_picker.gd" type="Script" id=1] +[ext_resource path="res://date_picker/value_picker.gd" type="Script" id=1] +[ext_resource path="res://date_picker/date_picker.gd" type="Script" id=2] [node name="date_picker" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 mouse_filter = 2 +script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false } -[node name="year_value" type="Control" parent="."] +[node name="year" type="Control" parent="."] anchor_right = 0.333 anchor_bottom = 1.0 script = ExtResource( 1 ) @@ -19,7 +21,7 @@ __meta__ = { } max_value = 9999 -[node name="previous" type="Label" parent="year_value"] +[node name="previous" type="Label" parent="year"] anchor_right = 1.0 anchor_bottom = 0.333 mouse_filter = 1 @@ -29,7 +31,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="current" type="Label" parent="year_value"] +[node name="current" type="Label" parent="year"] anchor_top = 0.333 anchor_right = 1.0 anchor_bottom = 0.666 @@ -40,16 +42,16 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="input" type="LineEdit" parent="year_value/current"] +[node name="input" type="LineEdit" parent="year/current"] visible = false anchor_right = 1.0 anchor_bottom = 1.0 -focus_next = NodePath("../../../month_value/current/input") +focus_next = NodePath("../../../month/current/input") align = 1 max_length = 4 caret_blink = true -[node name="next" type="Label" parent="year_value"] +[node name="next" type="Label" parent="year"] anchor_top = 0.666 anchor_right = 1.0 anchor_bottom = 1.0 @@ -60,7 +62,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="month_value" type="Control" parent="."] +[node name="month" type="Control" parent="."] anchor_left = 0.333 anchor_right = 0.666 anchor_bottom = 1.0 @@ -68,7 +70,7 @@ script = ExtResource( 1 ) min_value = 1 max_value = 12 -[node name="previous" type="Label" parent="month_value"] +[node name="previous" type="Label" parent="month"] anchor_right = 1.0 anchor_bottom = 0.333 mouse_filter = 1 @@ -78,7 +80,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="current" type="Label" parent="month_value"] +[node name="current" type="Label" parent="month"] anchor_top = 0.333 anchor_right = 1.0 anchor_bottom = 0.666 @@ -89,17 +91,17 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="input" type="LineEdit" parent="month_value/current"] +[node name="input" type="LineEdit" parent="month/current"] visible = false anchor_right = 1.0 anchor_bottom = 1.0 -focus_next = NodePath("../../../day_value/current/input") -focus_previous = NodePath("../../../year_value/current/input") +focus_next = NodePath("../../../day/current/input") +focus_previous = NodePath("../../../year/current/input") align = 1 max_length = 2 caret_blink = true -[node name="next" type="Label" parent="month_value"] +[node name="next" type="Label" parent="month"] anchor_top = 0.666 anchor_right = 1.0 anchor_bottom = 1.0 @@ -110,7 +112,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="day_value" type="Control" parent="."] +[node name="day" type="Control" parent="."] anchor_left = 0.666 anchor_right = 1.0 anchor_bottom = 1.0 @@ -121,7 +123,7 @@ __meta__ = { min_value = 1 max_value = 31 -[node name="previous" type="Label" parent="day_value"] +[node name="previous" type="Label" parent="day"] anchor_right = 1.0 anchor_bottom = 0.333 mouse_filter = 1 @@ -131,7 +133,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="current" type="Label" parent="day_value"] +[node name="current" type="Label" parent="day"] anchor_top = 0.333 anchor_right = 1.0 anchor_bottom = 0.666 @@ -142,16 +144,16 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="input" type="LineEdit" parent="day_value/current"] +[node name="input" type="LineEdit" parent="day/current"] visible = false anchor_right = 1.0 anchor_bottom = 1.0 -focus_previous = NodePath("../../../month_value/current/input") +focus_previous = NodePath("../../../month/current/input") align = 1 max_length = 2 caret_blink = true -[node name="next" type="Label" parent="day_value"] +[node name="next" type="Label" parent="day"] anchor_top = 0.666 anchor_right = 1.0 anchor_bottom = 1.0 @@ -162,7 +164,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="split_previous" type="ColorRect" parent="."] +[node name="split_upper" type="ColorRect" parent="."] anchor_top = 0.333 anchor_right = 1.0 anchor_bottom = 0.343 @@ -171,7 +173,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="split_next" type="ColorRect" parent="."] +[node name="split_lower" type="ColorRect" parent="."] anchor_top = 0.666 anchor_right = 1.0 anchor_bottom = 0.676 diff --git a/date_picker/scroll_picker.gd b/date_picker/scroll_picker.gd deleted file mode 100644 index 7d3004a..0000000 --- a/date_picker/scroll_picker.gd +++ /dev/null @@ -1,137 +0,0 @@ -extends Control - -const VELOCITY_DECAYING_FACTOR: float = 5.5 -const BINNING_THRESHOLD: float = 0.75 -const BINNING_ADJUST_P: float = 5.0 - -export var min_value: int -export var max_value: int - -var pointer: Dictionary -var anchor: float -var value: int -var offset: float - -var input: LineEdit -var label_previous: Label -var label_current: Label -var label_next: Label - -var scroll_unit_height: float -var label_previous_base_position: float -var label_current_base_position: float -var label_next_base_position: float - - -func _ready(): - pointer = { - index = -1, - initial_position = Vector2.ZERO, - current_position = Vector2.ZERO, - velocity = Vector2.ZERO, - was_dragged = false, - is_active = false, - } - - input = get_node("current/input") - input.connect("text_entered", self, "input_text_entered") - input.connect("focus_entered", self, "input_focus_entered") - input.connect("focus_exited", self, "input_focus_exited") - - label_previous = get_node("previous") - label_current = get_node("current") - label_next = get_node("next") - - scroll_unit_height = label_current.rect_size.y - label_previous_base_position = label_previous.rect_position.y - label_current_base_position = label_current.rect_position.y - label_next_base_position = label_next.rect_position.y - - value = min_value - offset = 0.0 - - -func _process(delta: float): - - if pointer.is_active: - var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y) - offset = anchor + (dragged_distance / scroll_unit_height) - value = int(offset) - offset -= value - else: - pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) - offset -= pointer.velocity.y * delta / scroll_unit_height - if abs(pointer.velocity.y) < BINNING_THRESHOLD * scroll_unit_height: - offset -= offset * BINNING_ADJUST_P * delta - - # Using 'offset * 2.0' (equivalent to 'offset / 0.5') rounds the value based on 0.5 units. - var cummulative_displacement := int(offset * 2.0) - value = wrapi(value + cummulative_displacement, min_value, max_value + 1) - offset -= cummulative_displacement - - label_current.text = "%d" % value - label_next.text = "%d" % wrapi(value + 1, min_value, max_value + 1) - label_previous.text = "%d" % wrapi(value - 1, min_value, max_value + 1) - - var offset_position := offset * scroll_unit_height - label_current.rect_position.y = label_current_base_position - offset_position - label_previous.rect_position.y = label_previous_base_position - offset_position - label_next.rect_position.y = label_next_base_position - offset_position - - label_previous.modulate.a = 0.5 - offset - label_next.modulate.a = offset + 0.5 - - -func _gui_input(event: InputEvent): - - # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. - if event is InputEventScreenTouch || event is InputEventScreenDrag: - if event.index != 0: - return - - if event is InputEventScreenTouch && (pointer.is_active == false || pointer.index == event.index): - var touch := event as InputEventScreenTouch - pointer.is_active = event.pressed - pointer.current_position = touch.position - if pointer.is_active: - input.release_focus() - pointer.index = touch.index - pointer.initial_position = touch.position - anchor = value + offset - else: - if pointer.was_dragged == false: # Click detected. - input.grab_focus() - pointer.index = -1 - pointer.was_dragged = false - - if event is InputEventScreenDrag && event.index == pointer.index: - var drag := event as InputEventScreenDrag - pointer.current_position = drag.position - pointer.velocity = drag.speed - pointer.was_dragged = true - - -func input_text_entered(new_text: String): - input.release_focus() - - -func input_focus_entered(): - input.text = "%d" % value - input.visible = true - input.select_all() - - -func input_focus_exited(): - if input.text.is_valid_integer(): - value = int(input.text) - input.visible = false - - -func set_value(new_value: int): - value = new_value - - -func get_value() -> int: - return value - - diff --git a/date_picker/value_picker.gd b/date_picker/value_picker.gd new file mode 100644 index 0000000..98c9755 --- /dev/null +++ b/date_picker/value_picker.gd @@ -0,0 +1,126 @@ +extends Control + +class_name ValuePicker + +const VELOCITY_DECAYING_FACTOR: float = 5.5 +const BINNING_THRESHOLD: float = 0.75 +const BINNING_ADJUST_P: float = 5.0 + +export var min_value: int +export var max_value: int + +onready var input: LineEdit = get_node("current/input") +onready var label_previous: Label = get_node("previous") +onready var label_current: Label = get_node("current") +onready var label_next: Label = get_node("next") + +var pointer: Dictionary +var anchor: float +var value: int +var offset: float + +var scroll_unit_height: float +var label_previous_base_position: float +var label_current_base_position: float +var label_next_base_position: float + + +func _ready(): + pointer = { + index = -1, + initial_position = Vector2.ZERO, + current_position = Vector2.ZERO, + velocity = Vector2.ZERO, + was_dragged = false, + is_active = false, + } + + input.connect("text_entered", self, "input_text_entered") + input.connect("focus_entered", self, "input_focus_entered") + input.connect("focus_exited", self, "input_focus_exited") + + scroll_unit_height = label_current.rect_size.y + label_previous_base_position = label_previous.rect_position.y + label_current_base_position = label_current.rect_position.y + label_next_base_position = label_next.rect_position.y + + value = min_value + offset = 0.0 + + +func _process(delta: float): + + if pointer.is_active: + var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y) + offset = anchor + (dragged_distance / scroll_unit_height) + value = int(offset) + offset -= value + else: + pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) + offset -= pointer.velocity.y * delta / scroll_unit_height + if abs(pointer.velocity.y) < BINNING_THRESHOLD * scroll_unit_height: + offset -= offset * BINNING_ADJUST_P * delta + + # Using 'offset * 2.0' (equivalent to 'offset / 0.5') rounds the value based on 0.5 units. + var cummulative_displacement := int(offset * 2.0) + value = wrapi(value + cummulative_displacement, min_value, max_value + 1) + offset -= cummulative_displacement + + label_current.text = "%d" % value + label_next.text = "%d" % wrapi(value + 1, min_value, max_value + 1) + label_previous.text = "%d" % wrapi(value - 1, min_value, max_value + 1) + + var offset_position := offset * scroll_unit_height + label_current.rect_position.y = label_current_base_position - offset_position + label_previous.rect_position.y = label_previous_base_position - offset_position + label_next.rect_position.y = label_next_base_position - offset_position + + label_previous.modulate.a = 0.5 - offset + label_next.modulate.a = offset + 0.5 + + +func _gui_input(event: InputEvent): + + # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. + if event is InputEventScreenTouch || event is InputEventScreenDrag: + if event.index != 0: + return + + if event is InputEventScreenTouch && (pointer.is_active == false || pointer.index == event.index): + var touch := event as InputEventScreenTouch + pointer.is_active = event.pressed + pointer.current_position = touch.position + if pointer.is_active: + input.release_focus() + pointer.index = touch.index + pointer.initial_position = touch.position + anchor = value + offset + else: + if pointer.was_dragged == false: # Click detected. + input.grab_focus() + pointer.index = -1 + pointer.was_dragged = false + + if event is InputEventScreenDrag && event.index == pointer.index: + var drag := event as InputEventScreenDrag + pointer.current_position = drag.position + pointer.velocity = drag.speed + pointer.was_dragged = true + + +func input_text_entered(new_text: String): + input.release_focus() + + +func input_focus_entered(): + input.text = "%d" % value + input.visible = true + input.select_all() + + +func input_focus_exited(): + if input.text.is_valid_integer(): + value = int(input.text) + input.visible = false + + diff --git a/project.godot b/project.godot index fa00ba4..adc16f7 100644 --- a/project.godot +++ b/project.godot @@ -8,6 +8,22 @@ config_version=4 +_global_script_classes=[ { +"base": "Control", +"class": "DatePicker", +"language": "GDScript", +"path": "res://date_picker/date_picker.gd" +}, { +"base": "Control", +"class": "ValuePicker", +"language": "GDScript", +"path": "res://date_picker/value_picker.gd" +} ] +_global_script_class_icons={ +"DatePicker": "", +"ValuePicker": "" +} + [application] config/name="Surgery Log" -- cgit v1.2.3 From 229bfb4b0ffaf7940317ffeba96f6537da9cc1df Mon Sep 17 00:00:00 2001 From: dam Date: Mon, 6 Dec 2021 11:28:48 +0000 Subject: Tweak project settings. --- export_presets.cfg | 2 +- project.godot | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'project.godot') diff --git a/export_presets.cfg b/export_presets.cfg index 5c563c9..da53431 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -7,7 +7,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="../builds/test_pico_debug.apk" +export_path="build/debug.apk" script_export_mode=1 script_encryption_key="" diff --git a/project.godot b/project.godot index adc16f7..4c68d91 100644 --- a/project.godot +++ b/project.godot @@ -38,6 +38,8 @@ config/icon="res://icon.png" window/size/width=720 window/size/height=1280 +window/size/test_width=576 +window/size/test_height=1024 window/energy_saving/keep_screen_on=false window/handheld/orientation="portrait" -- cgit v1.2.3 From 2c1085cf56e8fa1baf3c764752828e7f04391d7e Mon Sep 17 00:00:00 2001 From: dam Date: Mon, 6 Dec 2021 18:42:53 +0000 Subject: Add file dialogs for import/export filters. Height adjusted to virtual keyboard. --- export_presets.cfg | 6 +- fonts/font_regular.tres | 1 + licenses/font_b612.txt | 93 ------------------------- licenses/godot.txt | 20 ------ licenses/licenses.gd | 23 ------- main.gd | 45 ++++++------ main.tscn | 179 +++++++++++++++++++++++++++++++++--------------- menu/font_b612.txt | 93 +++++++++++++++++++++++++ menu/godot.txt | 20 ++++++ menu/menu.gd | 112 ++++++++++++++++++++++++++++++ project.godot | 4 +- readme.md | 8 +++ 12 files changed, 383 insertions(+), 221 deletions(-) delete mode 100644 licenses/font_b612.txt delete mode 100644 licenses/godot.txt delete mode 100644 licenses/licenses.gd create mode 100644 menu/font_b612.txt create mode 100644 menu/godot.txt create mode 100644 menu/menu.gd (limited to 'project.godot') diff --git a/export_presets.cfg b/export_presets.cfg index da53431..ae6c4cf 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -27,7 +27,7 @@ keystore/debug_password="debug.password" keystore/release="" keystore/release_user="" keystore/release_password="" -one_click_deploy/clear_previous_install=true +one_click_deploy/clear_previous_install=false version/code=1 version/name="1.0" package/unique_name="com.gudinoff.$genname" @@ -137,7 +137,7 @@ permissions/process_outgoing_calls=false permissions/read_calendar=false permissions/read_call_log=false permissions/read_contacts=false -permissions/read_external_storage=false +permissions/read_external_storage=true permissions/read_frame_buffer=false permissions/read_history_bookmarks=false permissions/read_input_state=false @@ -188,7 +188,7 @@ permissions/write_apn_settings=false permissions/write_calendar=false permissions/write_call_log=false permissions/write_contacts=false -permissions/write_external_storage=false +permissions/write_external_storage=true permissions/write_gservices=false permissions/write_history_bookmarks=false permissions/write_profile=false diff --git a/fonts/font_regular.tres b/fonts/font_regular.tres index 714269f..095114d 100644 --- a/fonts/font_regular.tres +++ b/fonts/font_regular.tres @@ -3,5 +3,6 @@ [ext_resource path="res://fonts/B612Mono-Regular.ttf" type="DynamicFontData" id=1] [resource] +size = 34 use_filter = true font_data = ExtResource( 1 ) diff --git a/licenses/font_b612.txt b/licenses/font_b612.txt deleted file mode 100644 index 2826948..0000000 --- a/licenses/font_b612.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2012 The B612 Project Authors (https://github.com/polarsys/b612) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/licenses/godot.txt b/licenses/godot.txt deleted file mode 100644 index bee83fb..0000000 --- a/licenses/godot.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. -Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/licenses/licenses.gd b/licenses/licenses.gd deleted file mode 100644 index 87a8d47..0000000 --- a/licenses/licenses.gd +++ /dev/null @@ -1,23 +0,0 @@ -extends Node - -const font_b612: String = "res://licenses/font_b612.txt" -const godot: String = "res://licenses/godot.txt" - -# @DAM For now, it just keeping track of licenses and storing a sample code of how to read the files. - -func _ready(): -# load_file(file) - pass - -func load_file(file: String): - var f = File.new() - f.open(file, File.READ) - var index = 1 - while not f.eof_reached(): # iterate through all lines until the end of file is reached - var line = f.get_line() - line += " " - print(line + str(index)) - - index += 1 - f.close() - return diff --git a/main.gd b/main.gd index f6c1f88..803c2d4 100644 --- a/main.gd +++ b/main.gd @@ -1,38 +1,37 @@ extends Control - -# Declare member variables here. Examples: -# var a = 2 -# var b = "text" -var _timeout: float - -# Called when the node enters the scene tree for the first time. -func _ready(): - $output.text = "Hello!" - $button.connect("pressed", self, "_pressed") +var timeout: float +onready var controls_sensible_to_keyboard: Array = [ + self, + get_node("/root/main/about"), + get_node("/root/main/delete_filters"), + get_node("/root/main/import_filters"), + get_node("/root/main/export_filters"), +] func _process(delta: float): - $output.text = "%s" % Engine.get_frames_per_second() - $timer.text = "%s" % _timeout - if _timeout > 0.0: - _timeout -= delta + + var keyboard_height: int = OS.get_virtual_keyboard_height() + for it in controls_sensible_to_keyboard: + it.margin_bottom = -keyboard_height + + # @DAM Debug information. +# $debug.text = "%s" % Engine.get_frames_per_second() +# $debug.text = "%s" % timeout + if timeout > 0.0: + timeout -= delta else: Engine.target_fps = 10.0 -func _pressed(): - $log.text += "PRESSED\n" - -# Called every frame. 'delta' is the elapsed time since the previous frame. -#func _process(delta): -# pass - func _input(event): Engine.target_fps = 0 - _timeout = 5.0 + timeout = 3.5 func _unhandled_input(event): Engine.target_fps = 0 - _timeout = 5.0 + timeout = 3.5 + + diff --git a/main.tscn b/main.tscn index adec227..83ee8d3 100644 --- a/main.tscn +++ b/main.tscn @@ -1,13 +1,15 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] [ext_resource path="res://theme_white.tres" type="Theme" id=3] +[ext_resource path="res://menu/menu.gd" type="Script" id=4] [node name="main" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 theme = ExtResource( 3 ) +script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false } @@ -24,7 +26,7 @@ __meta__ = { anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 4.0 -margin_top = 30.0 +margin_top = 60.0 margin_right = -4.0 margin_bottom = -4.0 scroll_horizontal_enabled = false @@ -33,24 +35,23 @@ __meta__ = { } [node name="VBoxContainer" type="VBoxContainer" parent="body/record"] -margin_right = 712.0 -margin_bottom = 1246.0 +margin_right = 1072.0 +margin_bottom = 1856.0 rect_clip_content = true size_flags_horizontal = 3 size_flags_vertical = 3 -script = ExtResource( 1 ) [node name="process_number" type="LineEdit" parent="body/record/VBoxContainer"] -margin_right = 712.0 -margin_bottom = 30.0 +margin_right = 1072.0 +margin_bottom = 52.0 placeholder_text = "Nº Processo" caret_blink = true caret_blink_speed = 0.5 [node name="surgery_number" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 34.0 -margin_right = 712.0 -margin_bottom = 64.0 +margin_top = 56.0 +margin_right = 1072.0 +margin_bottom = 108.0 placeholder_text = "Nº Cirurgia" caret_blink = true caret_blink_speed = 0.5 @@ -58,111 +59,111 @@ caret_blink_speed = 0.5 [node name="date_picker" parent="body/record/VBoxContainer" instance=ExtResource( 2 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 68.0 -margin_right = 712.0 -margin_bottom = 268.0 +margin_top = 112.0 +margin_right = 1072.0 +margin_bottom = 312.0 rect_min_size = Vector2( 400, 200 ) [node name="place" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 272.0 -margin_right = 712.0 -margin_bottom = 302.0 +margin_top = 316.0 +margin_right = 1072.0 +margin_bottom = 368.0 placeholder_text = "Local" caret_blink = true caret_blink_speed = 0.5 [node name="anesthesia" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 306.0 -margin_right = 712.0 -margin_bottom = 336.0 +margin_top = 372.0 +margin_right = 1072.0 +margin_bottom = 424.0 placeholder_text = "Anesthesics" caret_blink = true caret_blink_speed = 0.5 [node name="first_aider" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 340.0 -margin_right = 712.0 -margin_bottom = 370.0 +margin_top = 428.0 +margin_right = 1072.0 +margin_bottom = 480.0 placeholder_text = "1º Ajudante" caret_blink = true caret_blink_speed = 0.5 [node name="type" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 374.0 -margin_right = 712.0 -margin_bottom = 404.0 +margin_top = 484.0 +margin_right = 1072.0 +margin_bottom = 536.0 placeholder_text = "Tipo" caret_blink = true caret_blink_speed = 0.5 [node name="sub_type" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 408.0 -margin_right = 712.0 -margin_bottom = 438.0 +margin_top = 540.0 +margin_right = 1072.0 +margin_bottom = 592.0 placeholder_text = "Subtipo" caret_blink = true caret_blink_speed = 0.5 [node name="sub_sub_type" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 442.0 -margin_right = 712.0 -margin_bottom = 472.0 +margin_top = 596.0 +margin_right = 1072.0 +margin_bottom = 648.0 placeholder_text = "Sub-Subtipo" caret_blink = true caret_blink_speed = 0.5 [node name="pathology" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 476.0 -margin_right = 712.0 -margin_bottom = 506.0 +margin_top = 652.0 +margin_right = 1072.0 +margin_bottom = 704.0 placeholder_text = "Patologia" caret_blink = true caret_blink_speed = 0.5 [node name="intervention" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 510.0 -margin_right = 712.0 -margin_bottom = 540.0 +margin_top = 708.0 +margin_right = 1072.0 +margin_bottom = 760.0 placeholder_text = "Intervenção" caret_blink = true caret_blink_speed = 0.5 [node name="urgency" type="CheckBox" parent="body/record/VBoxContainer"] -margin_top = 544.0 -margin_right = 712.0 -margin_bottom = 572.0 +margin_top = 764.0 +margin_right = 1072.0 +margin_bottom = 814.0 text = "Urgência" [node name="notes" type="LineEdit" parent="body/record/VBoxContainer"] -margin_top = 576.0 -margin_right = 712.0 -margin_bottom = 606.0 +margin_top = 818.0 +margin_right = 1072.0 +margin_bottom = 870.0 placeholder_text = "Notas" caret_blink = true caret_blink_speed = 0.5 [node name="output" type="RichTextLabel" parent="body/record/VBoxContainer"] -margin_top = 610.0 -margin_right = 712.0 -margin_bottom = 660.0 +margin_top = 874.0 +margin_right = 1072.0 +margin_bottom = 924.0 rect_min_size = Vector2( 0, 50 ) __meta__ = { "_edit_use_anchors_": false } [node name="timer" type="RichTextLabel" parent="body/record/VBoxContainer"] -margin_top = 664.0 -margin_right = 712.0 -margin_bottom = 714.0 +margin_top = 928.0 +margin_right = 1072.0 +margin_bottom = 978.0 rect_min_size = Vector2( 0, 50 ) __meta__ = { "_edit_use_anchors_": false } [node name="button" type="Button" parent="body/record/VBoxContainer"] -margin_top = 718.0 -margin_right = 712.0 -margin_bottom = 768.0 +margin_top = 982.0 +margin_right = 1072.0 +margin_bottom = 1032.0 grow_horizontal = 2 grow_vertical = 2 rect_min_size = Vector2( 0, 50 ) @@ -172,9 +173,9 @@ __meta__ = { } [node name="log" type="RichTextLabel" parent="body/record/VBoxContainer"] -margin_top = 772.0 -margin_right = 712.0 -margin_bottom = 822.0 +margin_top = 1036.0 +margin_right = 1072.0 +margin_bottom = 1086.0 rect_min_size = Vector2( 0, 50 ) __meta__ = { "_edit_use_anchors_": false @@ -198,8 +199,72 @@ anchor_left = 1.0 anchor_right = 1.0 margin_left = -32.0 margin_bottom = 26.0 -text = "#" -items = [ "Importar filtros", null, 0, false, false, 0, 0, null, "", false, "Exportar filtros", null, 0, false, false, 1, 0, null, "", false, "Apagar filtros", null, 0, false, false, 2, 0, null, "", false, "Sobre", null, 0, false, false, 3, 0, null, "", false ] +text = "≡" +script = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="about" type="AcceptDialog" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +window_title = "" +dialog_autowrap = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="delete_filters" type="ConfirmationDialog" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +window_title = "" +dialog_text = "Are you sure you want to delete all filters?" +dialog_autowrap = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="import_filters" type="FileDialog" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +window_title = "" +mode = 0 +access = 2 +filters = PoolStringArray( "*.csv" ) +show_hidden_files = true +current_dir = "" +current_path = "" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="export_filters" type="FileDialog" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +window_title = "" +access = 2 +filters = PoolStringArray( "*.csv" ) +show_hidden_files = true +current_dir = "" +current_path = "" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="debug" type="Label" parent="."] +anchor_left = 1.0 +anchor_right = 1.0 +margin_left = -571.0 +margin_top = 220.0 +margin_bottom = 829.0 __meta__ = { "_edit_use_anchors_": false } diff --git a/menu/font_b612.txt b/menu/font_b612.txt new file mode 100644 index 0000000..2826948 --- /dev/null +++ b/menu/font_b612.txt @@ -0,0 +1,93 @@ +Copyright 2012 The B612 Project Authors (https://github.com/polarsys/b612) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/menu/godot.txt b/menu/godot.txt new file mode 100644 index 0000000..bee83fb --- /dev/null +++ b/menu/godot.txt @@ -0,0 +1,20 @@ +Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. +Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/menu/menu.gd b/menu/menu.gd new file mode 100644 index 0000000..55c74fa --- /dev/null +++ b/menu/menu.gd @@ -0,0 +1,112 @@ +extends MenuButton + +const menu_items: Array = [ + { label = "IMPORT FILTERS", action = "_menu_import_filters_action" }, + { label = "EXPORT FILTERS", action = "_menu_export_filters_action" }, + { label = "CLEAR FILTERS", action = "_menu_clear_filters_action" }, + { label = "ABOUT", action = "_menu_about_action" }, +] +const license_font_b612: String = "res://licenses/font_b612.txt" +const license_godot: String = "res://licenses/godot.txt" + +onready var popup: PopupMenu = get_popup() +onready var debug: Label = get_node("/root/main/debug") as Label + +func _ready(): + + for idx in range(menu_items.size()): + popup.add_item(menu_items[idx].label, idx) + popup.connect("id_pressed", self, "id_pressed") + +# load_file(file) + + + +func id_pressed(id: int): + debug.text += "'%d':'%s'" % [id, menu_items[id].action] + self.call_deferred(menu_items[id].action) + debug.text += "!\n" + + +var csv_file: Array +var has_permissions := false +func _menu_import_filters_action(): + +# printerr("pressed: %s" % get_stack()[0]); + debug.text += "> import: " + + if OS.get_name() == "Android": + while not has_permissions: + var permissions := Array(OS.get_granted_permissions()) + if not permissions.has("android.permission.READ_EXTERNAL_STORAGE") \ + or not permissions.has("android.permission.WRITE_EXTERNAL_STORAGE"): + OS.request_permissions() + # await get_tree().create_timer(1).timeout + yield(get_tree().create_timer(1), "timeout") # - for Godot 3 branch + else: + has_permissions = true + + + + var file_dialog := get_node("/root/main/import_filters") as FileDialog + file_dialog.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_dialog.connect("file_selected", self, "file_selected", [], CONNECT_ONESHOT) + file_dialog.show_modal(true) + file_dialog.invalidate() +# printerr("download: '%s'" % OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS)) + +func file_selected(path: String): + debug.text += "'%s'\n" % path + + var file = File.new() + file.open(path, File.READ) + while file.eof_reached() == false: + var line = file.get_line() + csv_file.append(line) + printerr("%s" % line) + file.close() + +func _menu_export_filters_action(): + debug.text += "> export: \n" +# printerr("pressed: %s" % get_stack()[0]); + var file_dialog := get_node("/root/main/export_filters") as FileDialog + file_dialog.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_dialog.connect("file_selected", self, "file_selected_export", [], CONNECT_ONESHOT) + file_dialog.show_modal(true) + file_dialog.invalidate() + +func file_selected_export(path: String): + debug.text += "'%s'\n" % path + var file = File.new() + file.open(path, File.WRITE) + for ln in csv_file: + file.store_line(ln) + file.close() + + +func _menu_clear_filters_action(): + debug.text += "> clear\n" +# printerr("pressed: %s" % get_stack()[0]); + (get_node("/root/main/delete_filters") as ConfirmationDialog).show_modal(true) + + +func _menu_about_action(): +# printerr("pressed: %s" % get_stack()[0]); + debug.text += "> about\n" + (get_node("/root/main/about") as AcceptDialog).show_modal() + + +#func load_file(file: String): +# var f = File.new() +# f.open(file, File.READ) +# var index = 1 +# while not f.eof_reached(): # iterate through all lines until the end of file is reached +# var line = f.get_line() +# line += " " +# print(line + str(index)) +# +# index += 1 +# f.close() +# return + + diff --git a/project.godot b/project.godot index 4c68d91..6657a50 100644 --- a/project.godot +++ b/project.godot @@ -36,8 +36,8 @@ config/icon="res://icon.png" [display] -window/size/width=720 -window/size/height=1280 +window/size/width=1080 +window/size/height=1920 window/size/test_width=576 window/size/test_height=1024 window/energy_saving/keep_screen_on=false diff --git a/readme.md b/readme.md index deaf374..8dae6e0 100644 --- a/readme.md +++ b/readme.md @@ -7,5 +7,13 @@ Surgery Log - [ ] Share DB: - share db via html email with db inserted in encoded downliadable field; - Use this to send email: https://docs.godotengine.org/en/stable/classes/class_os.html#class-os-method-shell-open +- [ ] File dialogs should be dismissed when back button is pressed (instead of closing the app); +- [ ] Translations: + - https://docs.godotengine.org/en/stable/getting_started/workflow/assets/importing_translations.html + - https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html#introduction +- [ ] Set tabs titles dynamically: https://docs.godotengine.org/en/stable/classes/class_tabcontainer.html?highlight=tabcontainer#class-tabcontainer-method-set-tab-title +- [ ] Create two themes: + - [ ] theme_light + - [ ] theme_dark -- cgit v1.2.3 From 9724fb73abf9fd3760a4f3f3ac941a119708c97b Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 16 Dec 2021 01:17:34 +0000 Subject: First prototype with working database and staging area. Fix incorrect warp in date picker. Disable physics engine. --- date_picker/date_picker.gd | 1 - date_picker/date_picker.tscn | 1 + date_picker/value_picker.gd | 2 +- icon.png | Bin 118840 -> 0 bytes icon.png.import | 35 ------- icons/add.png | Bin 0 -> 3030 bytes icons/add.png.import | 38 ++++++++ icons/delete.png | Bin 0 -> 4410 bytes icons/delete.png.import | 38 ++++++++ icons/edit.png | Bin 0 -> 5449 bytes icons/edit.png.import | 38 ++++++++ icons/icon.png | Bin 0 -> 19327 bytes icons/icon.png.import | 35 +++++++ logic/database.gd | 226 +++++++++++++++++++++++++++++++++++++++++++ logic/stage.gd | 88 +++++++++++++++++ main.gd | 8 +- main.tscn | 190 ++++++++++++++++++++---------------- project.godot | 17 +++- readme.md | 11 ++- 19 files changed, 602 insertions(+), 126 deletions(-) delete mode 100755 icon.png delete mode 100644 icon.png.import create mode 100644 icons/add.png create mode 100644 icons/add.png.import create mode 100644 icons/delete.png create mode 100644 icons/delete.png.import create mode 100755 icons/edit.png create mode 100644 icons/edit.png.import create mode 100755 icons/icon.png create mode 100644 icons/icon.png.import create mode 100644 logic/database.gd create mode 100644 logic/stage.gd (limited to 'project.godot') diff --git a/date_picker/date_picker.gd b/date_picker/date_picker.gd index 6298156..fb9cca2 100644 --- a/date_picker/date_picker.gd +++ b/date_picker/date_picker.gd @@ -1,5 +1,4 @@ extends Control - class_name DatePicker const days_per_month: Dictionary = { diff --git a/date_picker/date_picker.tscn b/date_picker/date_picker.tscn index 6506c31..21573dc 100644 --- a/date_picker/date_picker.tscn +++ b/date_picker/date_picker.tscn @@ -19,6 +19,7 @@ script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false } +min_value = 1 max_value = 9999 [node name="previous" type="Label" parent="year"] diff --git a/date_picker/value_picker.gd b/date_picker/value_picker.gd index d25a143..5e77294 100644 --- a/date_picker/value_picker.gd +++ b/date_picker/value_picker.gd @@ -120,7 +120,7 @@ func input_focus_entered(): func input_focus_exited(): if input.text.is_valid_integer(): - value = wrapi(int(input.text), min_value, max_value) + value = wrapi(int(input.text), min_value, max_value + 1) input.visible = false diff --git a/icon.png b/icon.png deleted file mode 100755 index e4d20ec..0000000 Binary files a/icon.png and /dev/null differ diff --git a/icon.png.import b/icon.png.import deleted file mode 100644 index a4c02e6..0000000 --- a/icon.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture" -path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://icon.png" -dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 -compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 -process/fix_alpha_border=true -process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -process/normal_map_invert_y=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 diff --git a/icons/add.png b/icons/add.png new file mode 100644 index 0000000..074a6c1 Binary files /dev/null and b/icons/add.png differ diff --git a/icons/add.png.import b/icons/add.png.import new file mode 100644 index 0000000..f726327 --- /dev/null +++ b/icons/add.png.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="StreamTexture" +path.s3tc="res://.import/add.png-21abb41ff0da259ea2ccbb4becce111a.s3tc.stex" +path.etc2="res://.import/add.png-21abb41ff0da259ea2ccbb4becce111a.etc2.stex" +path.etc="res://.import/add.png-21abb41ff0da259ea2ccbb4becce111a.etc.stex" +metadata={ +"imported_formats": [ "s3tc", "etc2", "etc" ], +"vram_texture": true +} + +[deps] + +source_file="res://icons/add.png" +dest_files=[ "res://.import/add.png-21abb41ff0da259ea2ccbb4becce111a.s3tc.stex", "res://.import/add.png-21abb41ff0da259ea2ccbb4becce111a.etc2.stex", "res://.import/add.png-21abb41ff0da259ea2ccbb4becce111a.etc.stex" ] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=true +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=false +process/premult_alpha=true +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/icons/delete.png b/icons/delete.png new file mode 100644 index 0000000..2b1f562 Binary files /dev/null and b/icons/delete.png differ diff --git a/icons/delete.png.import b/icons/delete.png.import new file mode 100644 index 0000000..eaad4c1 --- /dev/null +++ b/icons/delete.png.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="StreamTexture" +path.s3tc="res://.import/delete.png-48500a9e66ed6e102e89aa5542feee73.s3tc.stex" +path.etc2="res://.import/delete.png-48500a9e66ed6e102e89aa5542feee73.etc2.stex" +path.etc="res://.import/delete.png-48500a9e66ed6e102e89aa5542feee73.etc.stex" +metadata={ +"imported_formats": [ "s3tc", "etc2", "etc" ], +"vram_texture": true +} + +[deps] + +source_file="res://icons/delete.png" +dest_files=[ "res://.import/delete.png-48500a9e66ed6e102e89aa5542feee73.s3tc.stex", "res://.import/delete.png-48500a9e66ed6e102e89aa5542feee73.etc2.stex", "res://.import/delete.png-48500a9e66ed6e102e89aa5542feee73.etc.stex" ] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=true +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=false +process/premult_alpha=true +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/icons/edit.png b/icons/edit.png new file mode 100755 index 0000000..01fb607 Binary files /dev/null and b/icons/edit.png differ diff --git a/icons/edit.png.import b/icons/edit.png.import new file mode 100644 index 0000000..baee812 --- /dev/null +++ b/icons/edit.png.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="StreamTexture" +path.s3tc="res://.import/edit.png-d9148ff44b5b1c8f3b0a53a3c3c7c1c0.s3tc.stex" +path.etc2="res://.import/edit.png-d9148ff44b5b1c8f3b0a53a3c3c7c1c0.etc2.stex" +path.etc="res://.import/edit.png-d9148ff44b5b1c8f3b0a53a3c3c7c1c0.etc.stex" +metadata={ +"imported_formats": [ "s3tc", "etc2", "etc" ], +"vram_texture": true +} + +[deps] + +source_file="res://icons/edit.png" +dest_files=[ "res://.import/edit.png-d9148ff44b5b1c8f3b0a53a3c3c7c1c0.s3tc.stex", "res://.import/edit.png-d9148ff44b5b1c8f3b0a53a3c3c7c1c0.etc2.stex", "res://.import/edit.png-d9148ff44b5b1c8f3b0a53a3c3c7c1c0.etc.stex" ] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=true +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=false +process/premult_alpha=true +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/icons/icon.png b/icons/icon.png new file mode 100755 index 0000000..4b35a32 Binary files /dev/null and b/icons/icon.png differ diff --git a/icons/icon.png.import b/icons/icon.png.import new file mode 100644 index 0000000..bc6c6d2 --- /dev/null +++ b/icons/icon.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-66e56a551f174bdc993eb27d415a6710.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icons/icon.png" +dest_files=[ "res://.import/icon.png-66e56a551f174bdc993eb27d415a6710.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/logic/database.gd b/logic/database.gd new file mode 100644 index 0000000..1abb984 --- /dev/null +++ b/logic/database.gd @@ -0,0 +1,226 @@ +extends ItemList +class_name Database + +const DATABASE_FILE_PATH: String = "user://database.csv" +const DATE_SEPARATOR: String = "-" +const DATE_FORMAT: String = "%04d-%02d-%02d" +const ENTRY_PROTOTYPE: Dictionary = { + "process_id": "", + "surgery_id": "", + "place": "", + "date": "", + "date_year": 0, + "date_month": 0, + "date_day": 0, + "anesthetic": "", + "first_assistant": "", + "type": "", + "sub_type": "", + "sub_sub_type": "", + "pathology": "", + "intervention": "", + "is_urgency": false, + "notes": "", +} + +var db: Array +var staged_idx: int + +onready var delete_button: Button = get_node("actions/delete") +onready var edit_button: Button = get_node("actions/edit") +onready var add_button: Button = get_node("actions/add") + +onready var stage: Stage = get_node("/root/main/stage") + + +func _init(): + staged_idx = -1 + load_database() + store_database() # @DAM Only for testing. + + +# @DAM WIP +#func _notification(what: int): +# if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: +# clear_selection() + + +func _ready(): + self.connect("nothing_selected", self, "clear_selection") + delete_button.connect("pressed", self, "delete_action") + edit_button.connect("pressed", self, "edit_action") + add_button.connect("pressed", self, "add_action") + stage.connect("save", self, "save") + stage.connect("discard", self, "discard") + refresh_list() + + +func get_entry_view(database_entry: Dictionary) -> String: + return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, get_entry_date(database_entry)] + + +func refresh_list(): + self.clear() + for it in db: + self.add_item(get_entry_view(it)) + + +func clear_selection(): + unselect_all() + + +func delete_action(): + # @DAM Could do some performance improvements + var selected_entries_idx := self.get_selected_items() + var sorted_idx := Array(selected_entries_idx) + sorted_idx.sort() + sorted_idx.invert() + for idx in sorted_idx: + db.remove(idx) + self.remove_item(idx) + + +func edit_action(): + var selected_entries_idx := self.get_selected_items() + if selected_entries_idx.size() != 1: + return + staged_idx = selected_entries_idx[0] + self.visible = false + stage.visible = true + stage.set_stage(db[staged_idx]) + + +func add_action(): + self.visible = false + stage.visible = true + var staged := instance_entry() + stage.set_stage(staged) + # @DAM This signal is connected but, if we select "DISCARD" it stays connectd. + # Maybe I should always keep the connection and use two different buttons on sage screen. + stage.connect("save", self, "save_new", [], CONNECT_ONESHOT) + + +func save(database_entry: Dictionary): + if staged_idx >= 0: + db[staged_idx] = database_entry + set_item_text(staged_idx, get_entry_view(database_entry)) +# items[staged_idx] = get_entry_view(database_entry) + else: + db.append(database_entry) + add_item(get_entry_view(database_entry)) + + staged_idx = -1 + self.visible = true + + +func discard(): + staged_idx = -1 + self.visible = true + + +func load_database(): + var file := File.new() + file.open(DATABASE_FILE_PATH, File.READ_WRITE) + var headers: PoolStringArray + var is_first_line := true +# while database_file.eof_reached() == false: + while file.get_position() < file.get_len(): + var csv_entry := file.get_csv_line() + if is_first_line: + is_first_line = false + headers = csv_entry + continue + var entry = ENTRY_PROTOTYPE.duplicate(true) + for idx in headers.size(): + var field_name := headers[idx] + var field_value := csv_entry[idx] + match field_name: + "date_year", "date_month", "date_day": + entry[field_name] = int(field_value) + "is_urgency": + entry[field_name] = true if field_value.strip_edges().to_lower() == "true" else false + _: + entry[field_name] = field_value + db.append(entry) + return + db = [ + instance_entry({ + "process_id": "000001", + "surgery_id": "100000", + "place": "central", + "date": "2020-01-31", + }), + instance_entry({ + "process_id": "000002", + "surgery_id": "200000", + "place": "central", + "date": "2020-02-31", + }), + instance_entry({ + "process_id": "000003", + "surgery_id": "300000", + "place": "central", + "date": "2020-03-31", + }), + instance_entry({ + "process_id": "000004", + "surgery_id": "400000", + "place": "central", + "date": "2020-04-31", + }), + instance_entry({ + "process_id": "000012", + "surgery_id": "210000", + "place": "central", + "date": "2020-12-31", + }), + ] + + +func store_database(): + var file := File.new() + file.open(DATABASE_FILE_PATH, File.WRITE) + var header := PoolStringArray(ENTRY_PROTOTYPE.keys()) + file.store_csv_line(header) + var entry := PoolStringArray() + for it in db: + file.store_csv_line(it.values()) + file.close() + + +func instance_entry(params: Dictionary = {}) -> Dictionary: + var new_entry := ENTRY_PROTOTYPE.duplicate(true) + new_entry.process_id = params.get("process_id", "") + new_entry.surgery_id = params.get("surgery_id", "") + new_entry.place = params.get("place", "") + + var today = OS.get_date() + set_entry_date(new_entry, params.get("date", DATE_FORMAT % [today.year, today.month, today.day])) + + new_entry.anesthetic = params.get("anesthetic", "") + new_entry.first_assistant = params.get("first_assistant", "") + new_entry.type = params.get("type", "") + new_entry.sub_type = params.get("sub_type", "") + new_entry.sub_sub_type = params.get("sub_sub_type", "") + new_entry.pathology = params.get("pathology", "") + new_entry.intervention = params.get("intervention", "") + new_entry.is_urgency = params.get("is_urgency", false) + new_entry.notes = params.get("notes", "") + + return new_entry + + +func get_entry_date(entry: Dictionary) -> String: + return DATE_FORMAT % [entry.date_year, entry.date_month, entry.date_day] + + +func set_entry_date(entry: Dictionary, date: String): + date = date.strip_edges().replace(" ", DATE_SEPARATOR).replace("/", DATE_SEPARATOR).replace("\\", DATE_SEPARATOR) + var year_month_idx := date.find(DATE_SEPARATOR) + var month_day_idx := date.find(DATE_SEPARATOR, year_month_idx + 1) + entry.date = date + entry.date_year = int(date.substr(0, year_month_idx)) + entry.date_month = int(date.substr(year_month_idx + 1, month_day_idx - year_month_idx - 1)) + entry.date_day = int(date.substr(month_day_idx + 1)) + + diff --git a/logic/stage.gd b/logic/stage.gd new file mode 100644 index 0000000..a9f4fee --- /dev/null +++ b/logic/stage.gd @@ -0,0 +1,88 @@ +extends Control +class_name Stage + +signal save # (database_entry: Dictionary) +signal discard # () + +onready var process_id: LineEdit = get_node("controls/process_id") +onready var surgery_id: LineEdit = get_node("controls/surgery_id") +onready var date: DatePicker = get_node("controls/date_picker") +onready var place: LineEdit = get_node("controls/place") +onready var anesthetic: LineEdit = get_node("controls/anesthetic") +onready var first_assistant: LineEdit = get_node("controls/first_assistant") +onready var type: LineEdit = get_node("controls/type") +onready var sub_type: LineEdit = get_node("controls/sub_type") +onready var sub_sub_type: LineEdit = get_node("controls/sub_sub_type") +onready var pathology: LineEdit = get_node("controls/pathology") +onready var intervention: LineEdit = get_node("controls/intervention") +onready var is_urgency: Button = get_node("controls/is_urgency") +onready var notes: LineEdit = get_node("controls/notes") +onready var save_button: Button = get_node("controls/save") +onready var discard_button: Button = get_node("controls/discard") + + +func _ready(): + save_button.connect("pressed", self, "save_action") + discard_button.connect("pressed", self, "discard_action") + + +func save_action(): + self.visible = false + emit_signal("save", get_stage()) + + +func discard_action(): + self.visible = false + emit_signal("discard") + + +func set_stage(entry: Dictionary): + process_id.text = entry.process_id + surgery_id.text = entry.surgery_id + date.set_date(entry.date_year, entry.date_month, entry.date_day) + place.text = entry.place + anesthetic.text = entry.anesthetic + first_assistant.text = entry.first_assistant + type.text = entry.type + sub_type.text = entry.sub_type + sub_sub_type.text = entry.sub_sub_type + pathology.text = entry.pathology + intervention.text = entry.intervention + is_urgency.pressed = entry.is_urgency + notes.text = entry.notes + self.scroll_vertical = 0 # @DAM TODO + + +func get_stage() -> Dictionary: + var entry: Dictionary + entry.process_id = process_id.text + entry.surgery_id = surgery_id.text + entry.date_year = date.get_year() + entry.date_month = date.get_month() + entry.date_day = date.get_day() + entry.place = place.text + entry.anesthetic = anesthetic.text + entry.first_assistant = first_assistant.text + entry.type = type.text + entry.sub_type = sub_type.text + entry.sub_sub_type = sub_sub_type.text + entry.pathology = pathology.text + entry.intervention = intervention.text + entry.is_urgency = is_urgency.pressed + entry.notes = notes.text + return entry + + +func _notification(what: int): + if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: + discard_action() + + +func _unhandled_input(event): + get_node("/root/main/debug").text += "%s\n" % event.to_string() + + +func _unhandled_key_input(event): + get_node("/root/main/debug").text += "%s\n" % event.to_string() + + diff --git a/main.gd b/main.gd index 803c2d4..d242bda 100644 --- a/main.gd +++ b/main.gd @@ -1,6 +1,7 @@ extends Control var timeout: float + onready var controls_sensible_to_keyboard: Array = [ self, get_node("/root/main/about"), @@ -10,8 +11,13 @@ onready var controls_sensible_to_keyboard: Array = [ ] +func _init(): + Physics2DServer.set_active(false) + PhysicsServer.set_active(false) + + + func _process(delta: float): - var keyboard_height: int = OS.get_virtual_keyboard_height() for it in controls_sensible_to_keyboard: it.margin_bottom = -keyboard_height diff --git a/main.tscn b/main.tscn index 83ee8d3..53f083a 100644 --- a/main.tscn +++ b/main.tscn @@ -1,9 +1,14 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] [ext_resource path="res://theme_white.tres" type="Theme" id=3] [ext_resource path="res://menu/menu.gd" type="Script" id=4] +[ext_resource path="res://logic/database.gd" type="Script" id=5] +[ext_resource path="res://icons/edit.png" type="Texture" id=6] +[ext_resource path="res://icons/add.png" type="Texture" id=7] +[ext_resource path="res://icons/delete.png" type="Texture" id=8] +[ext_resource path="res://logic/stage.gd" type="Script" id=9] [node name="main" type="Control"] anchor_right = 1.0 @@ -14,192 +19,211 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="body" type="TabContainer" parent="."] +[node name="database" type="ItemList" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 -tab_align = 0 +margin_top = 60.0 +script = ExtResource( 5 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="actions" type="VBoxContainer" parent="database"] +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -140.0 +margin_top = -410.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="delete" type="Button" parent="database/actions"] +margin_right = 140.0 +margin_bottom = 134.0 +focus_mode = 0 +enabled_focus_mode = 0 +icon = ExtResource( 8 ) +flat = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="edit" type="Button" parent="database/actions"] +margin_top = 138.0 +margin_right = 140.0 +margin_bottom = 272.0 +focus_mode = 0 +enabled_focus_mode = 0 +icon = ExtResource( 6 ) +flat = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="add" type="Button" parent="database/actions"] +margin_top = 276.0 +margin_right = 140.0 +margin_bottom = 410.0 +focus_mode = 0 +enabled_focus_mode = 0 +icon = ExtResource( 7 ) +flat = true __meta__ = { "_edit_use_anchors_": false } -[node name="record" type="ScrollContainer" parent="body"] +[node name="stage" type="ScrollContainer" parent="."] +visible = false anchor_right = 1.0 anchor_bottom = 1.0 -margin_left = 4.0 margin_top = 60.0 -margin_right = -4.0 -margin_bottom = -4.0 scroll_horizontal_enabled = false +script = ExtResource( 9 ) __meta__ = { "_edit_use_anchors_": false } -[node name="VBoxContainer" type="VBoxContainer" parent="body/record"] -margin_right = 1072.0 -margin_bottom = 1856.0 -rect_clip_content = true +[node name="controls" type="VBoxContainer" parent="stage"] +margin_right = 1080.0 +margin_bottom = 1860.0 size_flags_horizontal = 3 size_flags_vertical = 3 +__meta__ = { +"_edit_use_anchors_": false +} -[node name="process_number" type="LineEdit" parent="body/record/VBoxContainer"] -margin_right = 1072.0 +[node name="process_id" type="LineEdit" parent="stage/controls"] +margin_right = 1080.0 margin_bottom = 52.0 placeholder_text = "Nº Processo" caret_blink = true caret_blink_speed = 0.5 -[node name="surgery_number" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="surgery_id" type="LineEdit" parent="stage/controls"] margin_top = 56.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 108.0 placeholder_text = "Nº Cirurgia" caret_blink = true caret_blink_speed = 0.5 -[node name="date_picker" parent="body/record/VBoxContainer" instance=ExtResource( 2 )] +[node name="date_picker" parent="stage/controls" instance=ExtResource( 2 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 112.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 312.0 rect_min_size = Vector2( 400, 200 ) -[node name="place" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="place" type="LineEdit" parent="stage/controls"] margin_top = 316.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 368.0 placeholder_text = "Local" caret_blink = true caret_blink_speed = 0.5 -[node name="anesthesia" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="anesthetic" type="LineEdit" parent="stage/controls"] margin_top = 372.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 424.0 placeholder_text = "Anesthesics" caret_blink = true caret_blink_speed = 0.5 -[node name="first_aider" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="first_assistant" type="LineEdit" parent="stage/controls"] margin_top = 428.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 480.0 placeholder_text = "1º Ajudante" caret_blink = true caret_blink_speed = 0.5 -[node name="type" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="type" type="LineEdit" parent="stage/controls"] margin_top = 484.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 536.0 placeholder_text = "Tipo" caret_blink = true caret_blink_speed = 0.5 -[node name="sub_type" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="sub_type" type="LineEdit" parent="stage/controls"] margin_top = 540.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 592.0 placeholder_text = "Subtipo" caret_blink = true caret_blink_speed = 0.5 -[node name="sub_sub_type" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="sub_sub_type" type="LineEdit" parent="stage/controls"] margin_top = 596.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 648.0 placeholder_text = "Sub-Subtipo" caret_blink = true caret_blink_speed = 0.5 -[node name="pathology" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="pathology" type="LineEdit" parent="stage/controls"] margin_top = 652.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 704.0 placeholder_text = "Patologia" caret_blink = true caret_blink_speed = 0.5 -[node name="intervention" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="intervention" type="LineEdit" parent="stage/controls"] margin_top = 708.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 760.0 placeholder_text = "Intervenção" caret_blink = true caret_blink_speed = 0.5 -[node name="urgency" type="CheckBox" parent="body/record/VBoxContainer"] +[node name="is_urgency" type="CheckBox" parent="stage/controls"] margin_top = 764.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 814.0 text = "Urgência" -[node name="notes" type="LineEdit" parent="body/record/VBoxContainer"] +[node name="notes" type="LineEdit" parent="stage/controls"] margin_top = 818.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 870.0 placeholder_text = "Notas" caret_blink = true caret_blink_speed = 0.5 -[node name="output" type="RichTextLabel" parent="body/record/VBoxContainer"] +[node name="save" type="Button" parent="stage/controls"] margin_top = 874.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 924.0 +grow_horizontal = 2 +grow_vertical = 2 rect_min_size = Vector2( 0, 50 ) +text = "save" __meta__ = { "_edit_use_anchors_": false } -[node name="timer" type="RichTextLabel" parent="body/record/VBoxContainer"] +[node name="discard" type="Button" parent="stage/controls"] margin_top = 928.0 -margin_right = 1072.0 +margin_right = 1080.0 margin_bottom = 978.0 -rect_min_size = Vector2( 0, 50 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="button" type="Button" parent="body/record/VBoxContainer"] -margin_top = 982.0 -margin_right = 1072.0 -margin_bottom = 1032.0 grow_horizontal = 2 grow_vertical = 2 rect_min_size = Vector2( 0, 50 ) -text = "PRESS ME" +text = "discard" __meta__ = { "_edit_use_anchors_": false } -[node name="log" type="RichTextLabel" parent="body/record/VBoxContainer"] -margin_top = 1036.0 -margin_right = 1072.0 -margin_bottom = 1086.0 -rect_min_size = Vector2( 0, 50 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="list" type="ScrollContainer" parent="body"] -visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_left = 4.0 -margin_top = 30.0 -margin_right = -4.0 -margin_bottom = -4.0 -scroll_horizontal_enabled = false - -[node name="ItemList" type="ItemList" parent="body/list"] -visible = false - [node name="menu" type="MenuButton" parent="."] -anchor_left = 1.0 anchor_right = 1.0 -margin_left = -32.0 -margin_bottom = 26.0 +margin_bottom = 48.0 text = "≡" +align = 2 script = ExtResource( 4 ) __meta__ = { "_edit_use_anchors_": false @@ -221,7 +245,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 size_flags_horizontal = 3 size_flags_vertical = 3 -window_title = "" +window_title = "delete filters" dialog_text = "Are you sure you want to delete all filters?" dialog_autowrap = true __meta__ = { @@ -233,7 +257,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 size_flags_horizontal = 3 size_flags_vertical = 3 -window_title = "" +window_title = "Open a File" mode = 0 access = 2 filters = PoolStringArray( "*.csv" ) @@ -249,7 +273,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 size_flags_horizontal = 3 size_flags_vertical = 3 -window_title = "" +window_title = "export filters" access = 2 filters = PoolStringArray( "*.csv" ) show_hidden_files = true @@ -260,11 +284,11 @@ __meta__ = { } [node name="debug" type="Label" parent="."] -anchor_left = 1.0 +visible = false anchor_right = 1.0 -margin_left = -571.0 -margin_top = 220.0 -margin_bottom = 829.0 +anchor_bottom = 1.0 +margin_top = 60.0 +valign = 2 __meta__ = { "_edit_use_anchors_": false } diff --git a/project.godot b/project.godot index 6657a50..41969be 100644 --- a/project.godot +++ b/project.godot @@ -9,18 +9,30 @@ config_version=4 _global_script_classes=[ { +"base": "ItemList", +"class": "Database", +"language": "GDScript", +"path": "res://logic/database.gd" +}, { "base": "Control", "class": "DatePicker", "language": "GDScript", "path": "res://date_picker/date_picker.gd" }, { "base": "Control", +"class": "Stage", +"language": "GDScript", +"path": "res://logic/stage.gd" +}, { +"base": "Control", "class": "ValuePicker", "language": "GDScript", "path": "res://date_picker/value_picker.gd" } ] _global_script_class_icons={ +"Database": "", "DatePicker": "", +"Stage": "", "ValuePicker": "" } @@ -28,11 +40,12 @@ _global_script_class_icons={ config/name="Surgery Log" run/main_scene="res://main.tscn" -boot_splash/image="res://icon.png" +boot_splash/image="res://icons/icon.png" boot_splash/fullsize=false boot_splash/use_filter=false boot_splash/bg_color=Color( 0, 0, 0, 1 ) -config/icon="res://icon.png" +config/icon="res://icons/icon.png" +config/quit_on_go_back=false [display] diff --git a/readme.md b/readme.md index 8dae6e0..c2d73b0 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,16 @@ Surgery Log =========== +# Notes +- Location of `user://`: `~/.local/share/godot/app_userdata/`. + # ToDo - [x] Datepicker: On click (without drag) reset velocity to 0; show and focus 'input' to allow introducing value. -- [ ] Input form fields is a column of input items; each input item has (from left to right) a 'LineEdit' and a 'Button'; pressing the button shows a list with possible entries for that field, and selecting an entry will copy that entry text to the 'LineEdit'; if the 'LineEdit' has text, it's 'Clear Button Enabled' is set and the 'Button' should become smaller (to allow more text to be visible. +- [x] Selecting last (year?)/month/day and de-selecting it, moves value to next; +- [x] Solve how entries are shared across db_screen and stage_screen; +- [x] Remove db_entry; +- [x] Rename db script/node to database; +- [ ] Input form fields is a column of input items; each input item has (from left to right) a 'LineEdit' and a 'Button'; pressing the button shows a list with possible entries for that field, and selecting an entry will coyp that entry text to the 'LineEdit'; if the 'LineEdit' has text, it's 'Clear Button Enabled' is set and the 'Button' should become smaller (to allow more text to be visible. - [ ] Share DB: - share db via html email with db inserted in encoded downliadable field; - Use this to send email: https://docs.godotengine.org/en/stable/classes/class_os.html#class-os-method-shell-open @@ -15,5 +22,3 @@ Surgery Log - [ ] Create two themes: - [ ] theme_light - [ ] theme_dark - - -- cgit v1.2.3 From 3f29bb41d713240eb7ba831f68981674d4db9eb9 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 16 Dec 2021 17:04:09 +0000 Subject: Fix issues when creating/editing entries. Fix android icon. --- export_presets.cfg | 6 ++--- icons/icon.png | Bin 19327 -> 42947 bytes icons/icon.xcf | Bin 0 -> 112237 bytes icons/icon_background.png | Bin 0 -> 36824 bytes icons/icon_background.png.import | 35 ++++++++++++++++++++++++++ icons/icon_foreground.png | Bin 0 -> 6327 bytes icons/icon_foreground.png.import | 35 ++++++++++++++++++++++++++ logic/database.gd | 52 ++++++++++++++++++--------------------- logic/stage.gd | 45 +++++++++++++++++++++------------ project.godot | 2 +- 10 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 icons/icon.xcf create mode 100644 icons/icon_background.png create mode 100644 icons/icon_background.png.import create mode 100644 icons/icon_foreground.png create mode 100644 icons/icon_foreground.png.import (limited to 'project.godot') diff --git a/export_presets.cfg b/export_presets.cfg index ae6c4cf..06377bd 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -35,9 +35,9 @@ package/name="" package/signed=true package/classify_as_game=false package/retain_data_on_uninstall=false -launcher_icons/main_192x192="" -launcher_icons/adaptive_foreground_432x432="" -launcher_icons/adaptive_background_432x432="" +launcher_icons/main_192x192="res://icons/icon.png" +launcher_icons/adaptive_foreground_432x432="res://icons/icon_foreground.png" +launcher_icons/adaptive_background_432x432="res://icons/icon_background.png" graphics/32_bits_framebuffer=true graphics/opengl_debug=false xr_features/xr_mode=0 diff --git a/icons/icon.png b/icons/icon.png index 4b35a32..63760ec 100755 Binary files a/icons/icon.png and b/icons/icon.png differ diff --git a/icons/icon.xcf b/icons/icon.xcf new file mode 100644 index 0000000..abfbec1 Binary files /dev/null and b/icons/icon.xcf differ diff --git a/icons/icon_background.png b/icons/icon_background.png new file mode 100644 index 0000000..6ee62e1 Binary files /dev/null and b/icons/icon_background.png differ diff --git a/icons/icon_background.png.import b/icons/icon_background.png.import new file mode 100644 index 0000000..7b6caab --- /dev/null +++ b/icons/icon_background.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon_background.png-7c479113bc74649f6884d5867344a330.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icons/icon_background.png" +dest_files=[ "res://.import/icon_background.png-7c479113bc74649f6884d5867344a330.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/icons/icon_foreground.png b/icons/icon_foreground.png new file mode 100644 index 0000000..919f2ff Binary files /dev/null and b/icons/icon_foreground.png differ diff --git a/icons/icon_foreground.png.import b/icons/icon_foreground.png.import new file mode 100644 index 0000000..8427899 --- /dev/null +++ b/icons/icon_foreground.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon_foreground.png-386f0ed4375c2b690a85127a54f3c7b2.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icons/icon_foreground.png" +dest_files=[ "res://.import/icon_foreground.png-386f0ed4375c2b690a85127a54f3c7b2.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/logic/database.gd b/logic/database.gd index 1abb984..db449ae 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -52,38 +52,34 @@ func _ready(): add_button.connect("pressed", self, "add_action") stage.connect("save", self, "save") stage.connect("discard", self, "discard") - refresh_list() + for it in db: + self.add_item(get_entry_view(it)) func get_entry_view(database_entry: Dictionary) -> String: return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, get_entry_date(database_entry)] -func refresh_list(): - self.clear() - for it in db: - self.add_item(get_entry_view(it)) - - func clear_selection(): unselect_all() func delete_action(): - # @DAM Could do some performance improvements var selected_entries_idx := self.get_selected_items() - var sorted_idx := Array(selected_entries_idx) - sorted_idx.sort() - sorted_idx.invert() - for idx in sorted_idx: - db.remove(idx) - self.remove_item(idx) + if selected_entries_idx.size() == 0: + return + assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") + var selected_idx = selected_entries_idx[0] + db.remove(selected_idx) + self.remove_item(selected_idx) + store_database() func edit_action(): var selected_entries_idx := self.get_selected_items() - if selected_entries_idx.size() != 1: + if selected_entries_idx.size() == 0: return + assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") staged_idx = selected_entries_idx[0] self.visible = false stage.visible = true @@ -95,20 +91,17 @@ func add_action(): stage.visible = true var staged := instance_entry() stage.set_stage(staged) - # @DAM This signal is connected but, if we select "DISCARD" it stays connectd. - # Maybe I should always keep the connection and use two different buttons on sage screen. - stage.connect("save", self, "save_new", [], CONNECT_ONESHOT) func save(database_entry: Dictionary): + database_entry = instance_entry(database_entry) # @DAM Maybe we could not be creating endless dictionaries? if staged_idx >= 0: db[staged_idx] = database_entry set_item_text(staged_idx, get_entry_view(database_entry)) -# items[staged_idx] = get_entry_view(database_entry) else: db.append(database_entry) add_item(get_entry_view(database_entry)) - + store_database() staged_idx = -1 self.visible = true @@ -118,9 +111,9 @@ func discard(): self.visible = true -func load_database(): +func load_database(file_path: String = DATABASE_FILE_PATH): var file := File.new() - file.open(DATABASE_FILE_PATH, File.READ_WRITE) + file.open(file_path, File.READ_WRITE) var headers: PoolStringArray var is_first_line := true # while database_file.eof_reached() == false: @@ -177,9 +170,9 @@ func load_database(): ] -func store_database(): +func store_database(file_path: String = DATABASE_FILE_PATH): var file := File.new() - file.open(DATABASE_FILE_PATH, File.WRITE) + file.open(file_path, File.WRITE) var header := PoolStringArray(ENTRY_PROTOTYPE.keys()) file.store_csv_line(header) var entry := PoolStringArray() @@ -188,14 +181,17 @@ func store_database(): file.close() -func instance_entry(params: Dictionary = {}) -> Dictionary: +static func instance_entry(params: Dictionary = {}) -> Dictionary: var new_entry := ENTRY_PROTOTYPE.duplicate(true) new_entry.process_id = params.get("process_id", "") new_entry.surgery_id = params.get("surgery_id", "") new_entry.place = params.get("place", "") var today = OS.get_date() - set_entry_date(new_entry, params.get("date", DATE_FORMAT % [today.year, today.month, today.day])) + new_entry.date_year = params.get("date_year", today.year) + new_entry.date_month = params.get("date_month", today.month) + new_entry.date_day = params.get("date_day", today.day) + new_entry.date = params.get("date", get_entry_date(new_entry)) new_entry.anesthetic = params.get("anesthetic", "") new_entry.first_assistant = params.get("first_assistant", "") @@ -210,11 +206,11 @@ func instance_entry(params: Dictionary = {}) -> Dictionary: return new_entry -func get_entry_date(entry: Dictionary) -> String: +static func get_entry_date(entry: Dictionary) -> String: return DATE_FORMAT % [entry.date_year, entry.date_month, entry.date_day] -func set_entry_date(entry: Dictionary, date: String): +static func set_entry_date(entry: Dictionary, date: String): date = date.strip_edges().replace(" ", DATE_SEPARATOR).replace("/", DATE_SEPARATOR).replace("\\", DATE_SEPARATOR) var year_month_idx := date.find(DATE_SEPARATOR) var month_day_idx := date.find(DATE_SEPARATOR, year_month_idx + 1) diff --git a/logic/stage.gd b/logic/stage.gd index a9f4fee..19018fa 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -54,22 +54,35 @@ func set_stage(entry: Dictionary): func get_stage() -> Dictionary: - var entry: Dictionary - entry.process_id = process_id.text - entry.surgery_id = surgery_id.text - entry.date_year = date.get_year() - entry.date_month = date.get_month() - entry.date_day = date.get_day() - entry.place = place.text - entry.anesthetic = anesthetic.text - entry.first_assistant = first_assistant.text - entry.type = type.text - entry.sub_type = sub_type.text - entry.sub_sub_type = sub_sub_type.text - entry.pathology = pathology.text - entry.intervention = intervention.text - entry.is_urgency = is_urgency.pressed - entry.notes = notes.text + +# var entry: Dictionary = Database.instance_entry({ +# "process_id": process_id.text, +# "surgery_id": surgery_id.text, +# "date_year": date.get_year(), +# "date_month": date.get_month(), +# "date_day": date.get_day(), +# "place": place.text, +# "anesthetic": anesthetic.text, +# "first_assistant": first_assistant.text, +# "type": type.text, +# }) + var entry: Dictionary = { + "process_id": process_id.text, + "surgery_id": surgery_id.text, + "date_year": date.get_year(), + "date_month": date.get_month(), + "date_day": date.get_day(), + "place": place.text, + "anesthetic": anesthetic.text, + "first_assistant": first_assistant.text, + "type": type.text, + "sub_type": sub_type.text, + "sub_sub_type": sub_sub_type.text, + "pathology": pathology.text, + "intervention": intervention.text, + "is_urgency": is_urgency.pressed, + "notes": notes.text, + } return entry diff --git a/project.godot b/project.godot index 41969be..584ffa8 100644 --- a/project.godot +++ b/project.godot @@ -43,7 +43,7 @@ run/main_scene="res://main.tscn" boot_splash/image="res://icons/icon.png" boot_splash/fullsize=false boot_splash/use_filter=false -boot_splash/bg_color=Color( 0, 0, 0, 1 ) +boot_splash/bg_color=Color( 0, 0, 0, 0 ) config/icon="res://icons/icon.png" config/quit_on_go_back=false -- cgit v1.2.3 From a2af4c7d07259a091deabdceaa5da1a2f7757c5e Mon Sep 17 00:00:00 2001 From: dam Date: Sat, 18 Dec 2021 03:14:52 +0000 Subject: Add drag detection threshold to date picker. Prototype touch drag on database screen. --- date_picker/value_picker.gd | 7 ++- icons/icon.png | Bin 42947 -> 43811 bytes icons/icon.xcf | Bin 112237 -> 151900 bytes icons/icon_background.png | Bin 36824 -> 37713 bytes logic/database.gd | 137 ++++++++++++++++++++++++++++++++++++++------ logic/stage.gd | 11 +++- main.tscn | 1 + project.godot | 2 +- touch_scroll.gd | 66 +++++++++++++++++++++ 9 files changed, 205 insertions(+), 19 deletions(-) create mode 100644 touch_scroll.gd (limited to 'project.godot') diff --git a/date_picker/value_picker.gd b/date_picker/value_picker.gd index 5e77294..fcd7dff 100644 --- a/date_picker/value_picker.gd +++ b/date_picker/value_picker.gd @@ -5,6 +5,7 @@ class_name ValuePicker const VELOCITY_DECAYING_FACTOR: float = 5.5 const BINNING_THRESHOLD: float = 0.75 const BINNING_ADJUST_P: float = 5.0 +const DRAG_THRESHOLD_CM: float = 0.250 export var min_value: int export var max_value: int @@ -19,6 +20,7 @@ var anchor: float var value: int var offset: float +var screen_dpcm: float var scroll_unit_height: float var label_previous_base_position: float var label_current_base_position: float @@ -39,6 +41,7 @@ func _ready(): input.connect("focus_entered", self, "input_focus_entered") input.connect("focus_exited", self, "input_focus_exited") + screen_dpcm = float(OS.get_screen_dpi()) / 2.54 scroll_unit_height = label_current.rect_size.y label_previous_base_position = label_previous.rect_position.y label_current_base_position = label_current.rect_position.y @@ -105,7 +108,8 @@ func _gui_input(event: InputEvent): var drag := event as InputEventScreenDrag pointer.current_position = drag.position pointer.velocity = drag.speed - pointer.was_dragged = true + if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM: + pointer.was_dragged = true func input_text_entered(new_text: String): @@ -113,6 +117,7 @@ func input_text_entered(new_text: String): func input_focus_entered(): + pointer.velocity = Vector2.ZERO # Avoid changing to other value once entering input. input.text = "%d" % value input.visible = true input.select_all() diff --git a/icons/icon.png b/icons/icon.png index 63760ec..95c7db3 100755 Binary files a/icons/icon.png and b/icons/icon.png differ diff --git a/icons/icon.xcf b/icons/icon.xcf index abfbec1..57986fb 100644 Binary files a/icons/icon.xcf and b/icons/icon.xcf differ diff --git a/icons/icon_background.png b/icons/icon_background.png index 6ee62e1..bbb555d 100644 Binary files a/icons/icon_background.png and b/icons/icon_background.png differ diff --git a/logic/database.gd b/logic/database.gd index db449ae..5f91c12 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -24,6 +24,7 @@ const ENTRY_PROTOTYPE: Dictionary = { } var db: Array +var selected_idx: int var staged_idx: int onready var delete_button: Button = get_node("actions/delete") @@ -34,18 +35,14 @@ onready var stage: Stage = get_node("/root/main/stage") func _init(): + selected_idx = -1 staged_idx = -1 load_database() store_database() # @DAM Only for testing. -# @DAM WIP -#func _notification(what: int): -# if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: -# clear_selection() - - func _ready(): + self.connect("item_selected", self, "item_selected") self.connect("nothing_selected", self, "clear_selection") delete_button.connect("pressed", self, "delete_action") edit_button.connect("pressed", self, "edit_action") @@ -56,31 +53,63 @@ func _ready(): self.add_item(get_entry_view(it)) +func _notification(what: int): + if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: + if selected_idx >= 0: + clear_selection() + else: + get_tree().quit() + + +# @DAM Testing +#var last_event +#var bypass: bool = false +#func _gui_input(event: InputEvent): +# if bypass == false: +# if event is InputEventScreenTouch && event.is_pressed(): +# accept_event() +# last_event = event +# elif event is InputEventScreenTouch && event.is_pressed() == false: +# bypass = true +# get_tree().input_event(event) +# bypass = false +# else: +# var x = 3 + + func get_entry_view(database_entry: Dictionary) -> String: return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, get_entry_date(database_entry)] +func item_selected(index: int): + if selected_idx >= 0: + set_item_text(selected_idx, get_entry_view(db[selected_idx])) + selected_idx = index + set_item_text(selected_idx, "> " + get_entry_view(db[selected_idx]) + " <") + + + func clear_selection(): + if selected_idx >= 0: + set_item_text(selected_idx, get_entry_view(db[selected_idx])) + selected_idx = -1 unselect_all() func delete_action(): - var selected_entries_idx := self.get_selected_items() - if selected_entries_idx.size() == 0: + if selected_idx < 0: return - assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") - var selected_idx = selected_entries_idx[0] + db.remove(selected_idx) self.remove_item(selected_idx) store_database() func edit_action(): - var selected_entries_idx := self.get_selected_items() - if selected_entries_idx.size() == 0: + if selected_idx < 0: return - assert(selected_entries_idx.size() == 1, "Multiple selected items not supported.") - staged_idx = selected_entries_idx[0] + + staged_idx = selected_idx self.visible = false stage.visible = true stage.set_stage(db[staged_idx]) @@ -116,7 +145,7 @@ func load_database(file_path: String = DATABASE_FILE_PATH): file.open(file_path, File.READ_WRITE) var headers: PoolStringArray var is_first_line := true -# while database_file.eof_reached() == false: +# while database_file.eof_reached() == false: # @DAM Why this? while file.get_position() < file.get_len(): var csv_entry := file.get_csv_line() if is_first_line: @@ -135,7 +164,10 @@ func load_database(file_path: String = DATABASE_FILE_PATH): _: entry[field_name] = field_value db.append(entry) + + fake_database() return + db = [ instance_entry({ "process_id": "000001", @@ -191,7 +223,7 @@ static func instance_entry(params: Dictionary = {}) -> Dictionary: new_entry.date_year = params.get("date_year", today.year) new_entry.date_month = params.get("date_month", today.month) new_entry.date_day = params.get("date_day", today.day) - new_entry.date = params.get("date", get_entry_date(new_entry)) + new_entry.date = params.get("date", get_entry_date(new_entry)) # @DAM We should store only one version of the date. new_entry.anesthetic = params.get("anesthetic", "") new_entry.first_assistant = params.get("first_assistant", "") @@ -220,3 +252,76 @@ static func set_entry_date(entry: Dictionary, date: String): entry.date_day = int(date.substr(month_day_idx + 1)) +func fake_database(): + db.resize(0) + for idx in range(50): + var date_year = 1 + int(float(idx) / 365.0) + var date_month = idx % 12 + var date_day = idx % 365 + db.append(instance_entry({ + "process_id": "%06d" % idx, + "surgery_id": "s%05d" % idx, + "date": "%04d-%02d-%02d" % [date_year, date_month, date_day] + })) + + + + + + + +# @DAM Testing. +export(float) var drag_threshold = 5 + +onready var touch_enabled = OS.has_touchscreen_ui_hint() +onready var v_scroll = get_v_scroll() + +var dragging = false +var pressed = false +var last_event +# must be _input, as _gui_input has bugs, with no touch.pressed = false events +# see: https://github.com/godotengine/godot/issues/16761 +func _gui_input(event): + + if event is InputEventScreenDrag: + self.v_scroll.value -= event.relative.y + + return + if not visible: + return + + if not touch_enabled: + return + + if event is InputEventScreenDrag: + accept_event() + if event.speed == Vector2(): + # we're on a device and speed is broken + # see: https://github.com/godotengine/godot/issues/3623 + event.speed = event.relative + if abs(event.speed.y) >= drag_threshold: + # scroll the list + dragging = true + v_scroll.value -= event.relative.y + return + + if event is InputEventScreenTouch: + if event.index == 0: + accept_event() + if dragging && event.pressed == false: + # prints("end drag") + dragging = false + pressed = false + else: + if event.pressed && pressed == false: + # prints("touch start") + pressed = true + accept_event() + # TODO: prevent select highlight + elif !event.pressed && pressed == true: + # prints("touch end and accept") + pressed = false + var ev = InputEventAction.new() + ev.action = "ui_accept" + ev.pressed = true + Input.parse_input_event(ev) diff --git a/logic/stage.gd b/logic/stage.gd index 19018fa..207b451 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -1,4 +1,4 @@ -extends Control +extends ScrollContainer class_name Stage signal save # (database_entry: Dictionary) @@ -66,6 +66,7 @@ func get_stage() -> Dictionary: # "first_assistant": first_assistant.text, # "type": type.text, # }) + # @DAM Simplify all this... avoid creating multiple entries/dictionaries. var entry: Dictionary = { "process_id": process_id.text, "surgery_id": surgery_id.text, @@ -86,6 +87,14 @@ func get_stage() -> Dictionary: return entry +# @DAM Testing. Needs all children controllers to have Mouse > Filter : Pass. +func _gui_input(event): + accept_event() + if event is InputEventScreenDrag: + self.scroll_vertical -= event.relative.y + return + + func _notification(what: int): if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: discard_action() diff --git a/main.tscn b/main.tscn index 53f083a..4096c59 100644 --- a/main.tscn +++ b/main.tscn @@ -116,6 +116,7 @@ margin_top = 112.0 margin_right = 1080.0 margin_bottom = 312.0 rect_min_size = Vector2( 400, 200 ) +mouse_filter = 0 [node name="place" type="LineEdit" parent="stage/controls"] margin_top = 316.0 diff --git a/project.godot b/project.godot index 584ffa8..3df8f21 100644 --- a/project.godot +++ b/project.godot @@ -19,7 +19,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://date_picker/date_picker.gd" }, { -"base": "Control", +"base": "ScrollContainer", "class": "Stage", "language": "GDScript", "path": "res://logic/stage.gd" diff --git a/touch_scroll.gd b/touch_scroll.gd new file mode 100644 index 0000000..ea92087 --- /dev/null +++ b/touch_scroll.gd @@ -0,0 +1,66 @@ +extends Control + + +func _gui_input(event: InputEvent): +#func _input(event: InputEvent): +# return + if event is InputEventScreenDrag: + self.v_scroll.value -= event.relative.y +# accept_event() + +#func _gui_input(event): +# accept_event() +# get_tree().set_input_as_handled() +# if event is InputEventScreenDrag: +# get_parent().v_scroll.value -= event.relative.y + + +export(float) var drag_threshold = 5 +onready var touch_enabled = OS.has_touchscreen_ui_hint() +onready var v_scroll = get_parent().get_v_scroll() + +var dragging = false +var pressed = false +var last_event +# must be _input, as _gui_input has bugs, with no touch.pressed = false events +# see: https://github.com/godotengine/godot/issues/16761 +func _input_disabled(event): +#func _gui_input(event): + + if not visible: + return + + if not touch_enabled: + return + + if event is InputEventScreenDrag: + accept_event() + if event.speed == Vector2(): + # we're on a device and speed is broken + # see: https://github.com/godotengine/godot/issues/3623 + event.speed = event.relative + if abs(event.speed.y) >= drag_threshold: + # scroll the list + dragging = true + v_scroll.value -= event.relative.y + return + + if event is InputEventScreenTouch: + if event.index == 0: + accept_event() + if dragging && event.pressed == false: + # prints("end drag") + dragging = false + pressed = false + else: + if event.pressed && pressed == false: + # prints("touch start") + pressed = true + # TODO: prevent select highlight + elif !event.pressed && pressed == true: + # prints("touch end and accept") + pressed = false + var ev = InputEventAction.new() + ev.action = "ui_accept" + ev.pressed = true + Input.parse_input_event(ev) -- cgit v1.2.3 From 7f0580b6b49a9dbafc54a0190bf573503c54417a Mon Sep 17 00:00:00 2001 From: dam Date: Fri, 31 Dec 2021 15:41:10 +0000 Subject: Prototype implementation of touch scroll on database and stage screens. --- date_picker/date_picker.tscn | 1 - logic/database.gd | 7 +++-- logic/stage.gd | 47 ++++++++++++++++++++++++++++---- main.tscn | 25 ++++++++--------- project.godot | 6 ++++ touch_scroll.gd | 65 ++++++++++++++++++++++++++++++++++---------- 6 files changed, 114 insertions(+), 37 deletions(-) (limited to 'project.godot') diff --git a/date_picker/date_picker.tscn b/date_picker/date_picker.tscn index 21573dc..54b2b82 100644 --- a/date_picker/date_picker.tscn +++ b/date_picker/date_picker.tscn @@ -6,7 +6,6 @@ [node name="date_picker" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 -mouse_filter = 2 script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false diff --git a/logic/database.gd b/logic/database.gd index ea02324..4f3e613 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -27,11 +27,11 @@ var db: Array var selected_idx: int var staged_idx: int +onready var stage: Stage = get_node("/root/main/stage") onready var delete_button: Button = get_node("actions/delete") onready var edit_button: Button = get_node("actions/edit") onready var add_button: Button = get_node("actions/add") - -onready var stage: Stage = get_node("/root/main/stage") +onready var v_scroll_bar: ScrollBar = get_v_scroll() func _init(): @@ -111,7 +111,7 @@ func add_action(): func scroll_down(): - get_v_scroll().value = get_v_scroll().max_value + v_scroll_bar.value = v_scroll_bar.max_value func save(database_entry: Dictionary): @@ -129,6 +129,7 @@ func save(database_entry: Dictionary): store_database() select(next_selected_idx) item_selected(next_selected_idx) # Calling "select" does not trigger the "item_selected" signal. + v_scroll_bar.value = float(next_selected_idx)/float(db.size()) * v_scroll_bar.max_value - (v_scroll_bar.page * 0.5) staged_idx = -1 self.visible = true diff --git a/logic/stage.gd b/logic/stage.gd index ac5e9aa..f7cced4 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -4,6 +4,22 @@ class_name Stage signal save # (database_entry: Dictionary) signal discard # () +#onready var process_id: LineEdit = get_node("touch_scroll/controls/process_id") +#onready var surgery_id: LineEdit = get_node("touch_scroll/controls/surgery_id") +#onready var date: DatePicker = get_node("touch_scroll/controls/date_picker") +#onready var place: LineEdit = get_node("touch_scroll/controls/place") +#onready var anesthetic: LineEdit = get_node("touch_scroll/controls/anesthetic") +#onready var first_assistant: LineEdit = get_node("touch_scroll/controls/first_assistant") +#onready var type: LineEdit = get_node("touch_scroll/controls/type") +#onready var sub_type: LineEdit = get_node("touch_scroll/controls/sub_type") +#onready var sub_sub_type: LineEdit = get_node("touch_scroll/controls/sub_sub_type") +#onready var pathology: LineEdit = get_node("touch_scroll/controls/pathology") +#onready var intervention: LineEdit = get_node("touch_scroll/controls/intervention") +#onready var is_urgency: Button = get_node("touch_scroll/controls/is_urgency") +#onready var notes: LineEdit = get_node("touch_scroll/controls/notes") +#onready var save_button: Button = get_node("touch_scroll/controls/save") +#onready var discard_button: Button = get_node("touch_scroll/controls/discard") + onready var process_id: LineEdit = get_node("controls/process_id") onready var surgery_id: LineEdit = get_node("controls/surgery_id") onready var date: DatePicker = get_node("controls/date_picker") @@ -21,9 +37,30 @@ onready var save_button: Button = get_node("controls/save") onready var discard_button: Button = get_node("controls/discard") + func _ready(): save_button.connect("pressed", self, "save_action") discard_button.connect("pressed", self, "discard_action") + + + for it in get_node("controls").get_children(): +# print("%s" % it.name) + match it.name: + "date_picker", "save", "discard": + print("- %s" % it.name) + + _: +# "first_assistant": + print("+ %s" % it.name) + var touch_scroll = TouchScroll.new() + touch_scroll.name = "touch_scroll" + touch_scroll.click_target_path = "../" + touch_scroll.scroll_target_path = "../../../" + touch_scroll.scroll_bar_get_method = "get_v_scrollbar" + touch_scroll.mouse_default_cursor_shape = Control.CURSOR_IBEAM + (it as Control).add_child(touch_scroll) + touch_scroll.anchor_right = 1.0 + touch_scroll.anchor_bottom = 1.0 func save_action(): @@ -88,11 +125,11 @@ func get_stage() -> Dictionary: # @DAM Testing. Needs all children controllers to have Mouse > Filter : Pass. -func _gui_input(event): - accept_event() - if event is InputEventScreenDrag: - self.scroll_vertical -= event.relative.y - return +#func _gui_input(event): +# accept_event() +# if event is InputEventScreenDrag: +# self.scroll_vertical -= event.relative.y +# return func _notification(what: int): diff --git a/main.tscn b/main.tscn index b584c88..9cb9220 100644 --- a/main.tscn +++ b/main.tscn @@ -37,6 +37,9 @@ script = ExtResource( 10 ) __meta__ = { "_edit_use_anchors_": false } +click_target_path = "../" +scroll_target_path = "../" +scroll_bar_get_method = "get_v_scroll" [node name="actions" type="VBoxContainer" parent="database"] anchor_left = 1.0 @@ -100,9 +103,6 @@ margin_right = 1080.0 margin_bottom = 1860.0 size_flags_horizontal = 3 size_flags_vertical = 3 -__meta__ = { -"_edit_use_anchors_": false -} [node name="process_id" type="LineEdit" parent="stage/controls"] margin_right = 1080.0 @@ -126,7 +126,6 @@ margin_top = 112.0 margin_right = 1080.0 margin_bottom = 312.0 rect_min_size = Vector2( 400, 200 ) -mouse_filter = 0 [node name="place" type="LineEdit" parent="stage/controls"] margin_top = 316.0 @@ -206,33 +205,33 @@ placeholder_text = "Notas" caret_blink = true caret_blink_speed = 0.5 -[node name="save" type="Button" parent="stage/controls"] -margin_top = 874.0 +[node name="discard" type="Button" parent="stage/controls"] +margin_top = 928.0 margin_right = 1080.0 -margin_bottom = 924.0 +margin_bottom = 978.0 grow_horizontal = 2 grow_vertical = 2 rect_min_size = Vector2( 0, 50 ) -text = "save" +text = "discard" __meta__ = { "_edit_use_anchors_": false } -[node name="discard" type="Button" parent="stage/controls"] -margin_top = 928.0 +[node name="save" type="Button" parent="stage/controls"] +margin_top = 874.0 margin_right = 1080.0 -margin_bottom = 978.0 +margin_bottom = 924.0 grow_horizontal = 2 grow_vertical = 2 rect_min_size = Vector2( 0, 50 ) -text = "discard" +text = "save" __meta__ = { "_edit_use_anchors_": false } [node name="menu" type="MenuButton" parent="."] anchor_right = 1.0 -margin_bottom = 48.0 +margin_bottom = 60.0 text = "≡" align = 2 script = ExtResource( 4 ) diff --git a/project.godot b/project.godot index 3df8f21..703d936 100644 --- a/project.godot +++ b/project.godot @@ -25,6 +25,11 @@ _global_script_classes=[ { "path": "res://logic/stage.gd" }, { "base": "Control", +"class": "TouchScroll", +"language": "GDScript", +"path": "res://touch_scroll.gd" +}, { +"base": "Control", "class": "ValuePicker", "language": "GDScript", "path": "res://date_picker/value_picker.gd" @@ -33,6 +38,7 @@ _global_script_class_icons={ "Database": "", "DatePicker": "", "Stage": "", +"TouchScroll": "", "ValuePicker": "" } diff --git a/touch_scroll.gd b/touch_scroll.gd index f2aeca7..7b6aefd 100644 --- a/touch_scroll.gd +++ b/touch_scroll.gd @@ -1,22 +1,45 @@ extends Control +class_name TouchScroll -const VELOCITY_DECAYING_FACTOR: float = 5.5 const DRAG_THRESHOLD_CM: float = 0.250 +export var click_target_path: String +export var scroll_target_path: String +export var scroll_bar_get_method: String +export var scroll_velocity_decaying_factor: float = 2.5 + var pointer: Dictionary var anchor: float var offset: float var screen_dpcm: float -onready var target: Control = get_parent() -onready var target_scroll: VScrollBar = get_parent().get_v_scroll() +var click_target: Control +var scroll_target: Control +var target_scroll_bar: VScrollBar + + + +# @DAM +# Change this into an event-driven approach by changing the touch_scroll into a signal emitter and +# the target scrollable control a signal consumer. This way, the signal consumer will behave as the +# central node and will have the capability to detect when different touch_scroll sensors are +# activated and stop previous inputs (if required). +# Signal emitters should signal: +# - when an input drag starts +# - when an input drag stops +# - when an input drags +# - when an input clicks func _ready(): + click_target = get_node(click_target_path) + scroll_target = get_node(scroll_target_path) + target_scroll_bar = scroll_target.call(scroll_bar_get_method) pointer = { index = -1, initial_position = Vector2.ZERO, current_position = Vector2.ZERO, + relative_position = Vector2.ZERO, velocity = Vector2.ZERO, was_dragged = false, is_active = false, @@ -25,14 +48,23 @@ func _ready(): func _process(delta: float): + # @DAM This only works for the stage... for the database this hides the touch_scroll after the first click. + if click_target.has_focus(): + mouse_filter = Control.MOUSE_FILTER_IGNORE + else: + mouse_filter = Control.MOUSE_FILTER_STOP + if pointer.is_active: var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y) offset = anchor + dragged_distance - self.target_scroll.value = offset +# self.target_scroll_bar.value = offset + self.target_scroll_bar.value -= pointer.relative_position.y + pointer.relative_position = Vector2.ZERO elif pointer.velocity.length() > 0.5: - pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) + pointer.velocity *= clamp((1.0 - scroll_velocity_decaying_factor * delta), 0.0, 1.0) offset -= pointer.velocity.y * delta - self.target_scroll.value = offset +# self.target_scroll_bar.value = offset + self.target_scroll_bar.value -= pointer.velocity.y * delta func _gui_input(event: InputEvent): @@ -45,11 +77,11 @@ func _gui_input(event: InputEvent): if event is InputEventScreenTouch && (pointer.is_active == false || pointer.index == event.index): var touch := event as InputEventScreenTouch pointer.is_active = event.pressed - pointer.current_position = touch.position + pointer.current_position = get_global_mouse_position() # touch.position if pointer.is_active: pointer.index = touch.index - pointer.initial_position = touch.position - anchor = self.target_scroll.value + pointer.initial_position = get_global_mouse_position() # touch.position + anchor = self.target_scroll_bar.value else: if pointer.was_dragged == false: # Click detected. simulate_gui_click() @@ -58,15 +90,16 @@ func _gui_input(event: InputEvent): if event is InputEventScreenDrag && event.index == pointer.index: var drag := event as InputEventScreenDrag - pointer.current_position = drag.position + pointer.current_position = get_global_mouse_position() # drag.position pointer.velocity = drag.speed + pointer.relative_position = drag.relative if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM: pointer.was_dragged = true func simulate_gui_click(): - var position := self.get_global_mouse_position() - target.rect_global_position + var position := self.get_global_mouse_position() - click_target.rect_global_position var event_touch := InputEventScreenTouch.new() event_touch.index = 0 @@ -79,12 +112,14 @@ func simulate_gui_click(): event_mouse.pressed = true event_touch.pressed = true - target._gui_input(event_mouse) - target._gui_input(event_touch) + click_target._gui_input(event_mouse) + click_target._gui_input(event_touch) + click_target.grab_focus() + event_mouse.pressed = false event_touch.pressed = false - target._gui_input(event_mouse) - target._gui_input(event_touch) + click_target._gui_input(event_mouse) + click_target._gui_input(event_touch) -- cgit v1.2.3 From c59f89e99c90c0e756cdf780bcbf04d782eb3e6f Mon Sep 17 00:00:00 2001 From: dam Date: Sat, 1 Jan 2022 04:56:58 +0000 Subject: Change touch scroll detection to pointer-input-sensor approach using signals/events. --- logic/database.gd | 60 ++++++++++++++++++++++- logic/stage.gd | 104 ++++++++++++++++++++++++++++------------ main.tscn | 7 +-- pointer_input_sensor.gd | 84 ++++++++++++++++++++++++++++++++ project.godot | 12 ++--- touch_scroll.gd | 125 ------------------------------------------------ 6 files changed, 224 insertions(+), 168 deletions(-) create mode 100644 pointer_input_sensor.gd delete mode 100644 touch_scroll.gd (limited to 'project.godot') diff --git a/logic/database.gd b/logic/database.gd index 4f3e613..41ba679 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -31,7 +31,8 @@ onready var stage: Stage = get_node("/root/main/stage") onready var delete_button: Button = get_node("actions/delete") onready var edit_button: Button = get_node("actions/edit") onready var add_button: Button = get_node("actions/add") -onready var v_scroll_bar: ScrollBar = get_v_scroll() +onready var v_scroll_bar: ScrollBar = get_v_scroll() # @DAM Stop scroll inertia when buttons are pressed. +onready var drag_sensor: PointerInputSensor = get_node("drag_sensor") func _init(): @@ -44,15 +45,72 @@ func _init(): func _ready(): self.connect("item_selected", self, "item_selected") self.connect("nothing_selected", self, "clear_selection") + delete_button.connect("pressed", self, "delete_action") edit_button.connect("pressed", self, "edit_action") add_button.connect("pressed", self, "add_action") + stage.connect("save", self, "save") stage.connect("discard", self, "discard") + + drag_sensor.connect("on_press", self, "on_press") + drag_sensor.connect("on_drag", self, "on_drag") + drag_sensor.connect("on_end_drag", self, "on_end_drag") + drag_sensor.connect("on_click", self, "on_click") + for it in db: self.add_item(get_entry_view(it)) +# @DAM Cleanup this code. +export var scroll_velocity_decaying_factor: float = 2.5 +var drag_velocity := 0.0 +var is_dragging := false + +func _process(delta: float): + if is_dragging == false && abs(drag_velocity) > 0.5: + drag_velocity *= clamp((1.0 - scroll_velocity_decaying_factor * delta), 0.0, 1.0) + v_scroll_bar.value -= drag_velocity * delta + +func on_click(pointer: PointerInputSensor.PointerInputData): + var target := self + var position := target.get_global_mouse_position() - target.rect_global_position + + var event_touch := InputEventScreenTouch.new() + event_touch.index = 0 + event_touch.position = position + + var event_mouse := InputEventMouseButton.new() + event_mouse.button_index = BUTTON_LEFT + event_mouse.button_mask = BUTTON_MASK_LEFT + event_mouse.position = position + + event_mouse.pressed = true + event_touch.pressed = true + target._gui_input(event_mouse) + target._gui_input(event_touch) + + target.grab_focus() + + event_mouse.pressed = false + event_touch.pressed = false + target._gui_input(event_mouse) + target._gui_input(event_touch) + +func on_press(pointer: PointerInputSensor.PointerInputData): + is_dragging = true + +func on_end_drag(pointer: PointerInputSensor.PointerInputData): + is_dragging = false + +func on_drag(pointer: PointerInputSensor.PointerInputData): + is_dragging = true + drag_velocity = pointer.velocity.y + v_scroll_bar.value -= pointer.relative_position.y + + + + func _notification(what: int): if visible == false: return diff --git a/logic/stage.gd b/logic/stage.gd index f7cced4..62e0a58 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -37,7 +37,6 @@ onready var save_button: Button = get_node("controls/save") onready var discard_button: Button = get_node("controls/discard") - func _ready(): save_button.connect("pressed", self, "save_action") discard_button.connect("pressed", self, "discard_action") @@ -48,19 +47,82 @@ func _ready(): match it.name: "date_picker", "save", "discard": print("- %s" % it.name) - + _: # "first_assistant": print("+ %s" % it.name) - var touch_scroll = TouchScroll.new() - touch_scroll.name = "touch_scroll" - touch_scroll.click_target_path = "../" - touch_scroll.scroll_target_path = "../../../" - touch_scroll.scroll_bar_get_method = "get_v_scrollbar" - touch_scroll.mouse_default_cursor_shape = Control.CURSOR_IBEAM - (it as Control).add_child(touch_scroll) - touch_scroll.anchor_right = 1.0 - touch_scroll.anchor_bottom = 1.0 + var drag_sensor = PointerInputSensor.new() + drag_sensor.name = "drag_sensor" + drag_sensor.mouse_default_cursor_shape = Control.CURSOR_IBEAM + (it as Control).add_child(drag_sensor) + drag_sensor.anchor_right = 1.0 + drag_sensor.anchor_bottom = 1.0 + + drag_sensor.connect("on_press", self, "on_press") + drag_sensor.connect("on_drag", self, "on_drag") + drag_sensor.connect("on_end_drag", self, "on_end_drag") + drag_sensor.connect("on_click", self, "on_click") + drag_sensor.on_process = funcref(self, "bazinga") + + +# @DAM Cleanup this code. +onready var v_scroll_bar: VScrollBar = get_v_scrollbar() +export var scroll_velocity_decaying_factor: float = 2.5 +var drag_velocity := 0.0 +var is_dragging := false + +func bazinga(delta: float, pointer: PointerInputSensor): + if (pointer.get_parent() as Control).has_focus(): + pointer.mouse_filter = Control.MOUSE_FILTER_IGNORE + else: + pointer.mouse_filter = Control.MOUSE_FILTER_STOP + +func _process(delta: float): + if is_dragging == false && abs(drag_velocity) > 0.5: + drag_velocity *= clamp((1.0 - scroll_velocity_decaying_factor * delta), 0.0, 1.0) + v_scroll_bar.value -= drag_velocity * delta + +func on_click(pointer: PointerInputSensor.PointerInputData): + var target: Control = pointer.target.get_parent() + var position := target.get_global_mouse_position() - target.rect_global_position + + var event_touch := InputEventScreenTouch.new() + event_touch.index = 0 + event_touch.position = position + + var event_mouse := InputEventMouseButton.new() + event_mouse.button_index = BUTTON_LEFT + event_mouse.button_mask = BUTTON_MASK_LEFT + event_mouse.position = position + + event_mouse.pressed = true + event_touch.pressed = true + target._gui_input(event_mouse) + target._gui_input(event_touch) + + target.grab_focus() + + event_mouse.pressed = false + event_touch.pressed = false + target._gui_input(event_mouse) + target._gui_input(event_touch) + +func on_press(pointer: PointerInputSensor.PointerInputData): + is_dragging = true + +func on_end_drag(pointer: PointerInputSensor.PointerInputData): + is_dragging = false + +func on_drag(pointer: PointerInputSensor.PointerInputData): + is_dragging = true + drag_velocity = pointer.velocity.y + v_scroll_bar.value -= pointer.relative_position.y + + + + + + func save_action(): @@ -91,18 +153,6 @@ func set_stage(entry: Dictionary): func get_stage() -> Dictionary: - -# var entry: Dictionary = Database.instance_entry({ -# "process_id": process_id.text, -# "surgery_id": surgery_id.text, -# "date_year": date.get_year(), -# "date_month": date.get_month(), -# "date_day": date.get_day(), -# "place": place.text, -# "anesthetic": anesthetic.text, -# "first_assistant": first_assistant.text, -# "type": type.text, -# }) # @DAM Simplify all this... avoid creating multiple entries/dictionaries. var entry: Dictionary = { "process_id": process_id.text, @@ -124,14 +174,6 @@ func get_stage() -> Dictionary: return entry -# @DAM Testing. Needs all children controllers to have Mouse > Filter : Pass. -#func _gui_input(event): -# accept_event() -# if event is InputEventScreenDrag: -# self.scroll_vertical -= event.relative.y -# return - - func _notification(what: int): if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: discard_action() diff --git a/main.tscn b/main.tscn index 9cb9220..331d94d 100644 --- a/main.tscn +++ b/main.tscn @@ -9,7 +9,7 @@ [ext_resource path="res://icons/add.png" type="Texture" id=7] [ext_resource path="res://icons/delete.png" type="Texture" id=8] [ext_resource path="res://logic/stage.gd" type="Script" id=9] -[ext_resource path="res://touch_scroll.gd" type="Script" id=10] +[ext_resource path="res://pointer_input_sensor.gd" type="Script" id=10] [node name="main" type="Control"] anchor_right = 1.0 @@ -29,7 +29,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="touch_scroll" type="Control" parent="database"] +[node name="drag_sensor" type="Control" parent="database"] anchor_right = 1.0 anchor_bottom = 1.0 margin_right = -8.0 @@ -37,9 +37,6 @@ script = ExtResource( 10 ) __meta__ = { "_edit_use_anchors_": false } -click_target_path = "../" -scroll_target_path = "../" -scroll_bar_get_method = "get_v_scroll" [node name="actions" type="VBoxContainer" parent="database"] anchor_left = 1.0 diff --git a/pointer_input_sensor.gd b/pointer_input_sensor.gd new file mode 100644 index 0000000..95e1b4b --- /dev/null +++ b/pointer_input_sensor.gd @@ -0,0 +1,84 @@ +extends Control +class_name PointerInputSensor + +export var drag_threshold_cm: float = 0.250 + +signal on_press +signal on_release +#signal on_release_outside +signal on_click +signal on_enter +signal on_exit +#signal on_exit_app_window +signal on_begin_drag +signal on_drag +signal on_end_drag + +class PointerInputData: + var target: PointerInputSensor + var index := -1 + var initial_position := Vector2.ZERO + var current_position := Vector2.ZERO + var relative_position = Vector2.ZERO + var velocity := Vector2.ZERO + var was_dragged := false + var is_pressed := false + +var pointer: PointerInputData +var screen_dpcm: float +var on_process: FuncRef + + +func _ready(): + screen_dpcm = float(OS.get_screen_dpi()) / 2.54 + pointer = PointerInputData.new() + pointer.target = self + connect("mouse_entered", self, "_on_enter_exit", [true]) + connect("mouse_entered", self, "_on_enter_exit", [false]) + + +func _process(delta: float): + if on_process != null && on_process.is_valid(): + on_process.call_func(delta, self) + + +func _on_enter_exit(is_inside: bool): + emit_signal("on_enter" if is_inside else "on_exit", pointer) + + +func _gui_input(event: InputEvent): + + # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. + if event is InputEventScreenTouch || event is InputEventScreenDrag: + if event.index != 0: + return + + if event is InputEventScreenTouch && (pointer.is_pressed == false || pointer.index == event.index): + var touch := event as InputEventScreenTouch + pointer.is_pressed = event.pressed + pointer.current_position = get_global_mouse_position() + if pointer.is_pressed: + pointer.index = touch.index + pointer.initial_position = get_global_mouse_position() + emit_signal("on_press", pointer) + else: + emit_signal("on_release", pointer) + if pointer.was_dragged == false: + emit_signal("on_click", pointer) + else: + emit_signal("on_end_drag", pointer) + pointer.index = -1 + pointer.was_dragged = false + + if event is InputEventScreenDrag && event.index == pointer.index: + var drag := event as InputEventScreenDrag + pointer.current_position = get_global_mouse_position() + pointer.velocity = drag.speed + pointer.relative_position = drag.relative + # @DAM Instead of constantly converting the pointer distance to cm... just conver the drag_threshold_cm to pixels + if pointer.was_dragged == false && pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > drag_threshold_cm: + pointer.was_dragged = true + emit_signal("on_begin_drag", pointer) + emit_signal("on_drag", pointer) + + diff --git a/project.godot b/project.godot index 703d936..f5dbe7a 100644 --- a/project.godot +++ b/project.godot @@ -19,17 +19,17 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://date_picker/date_picker.gd" }, { +"base": "Control", +"class": "PointerInputSensor", +"language": "GDScript", +"path": "res://pointer_input_sensor.gd" +}, { "base": "ScrollContainer", "class": "Stage", "language": "GDScript", "path": "res://logic/stage.gd" }, { "base": "Control", -"class": "TouchScroll", -"language": "GDScript", -"path": "res://touch_scroll.gd" -}, { -"base": "Control", "class": "ValuePicker", "language": "GDScript", "path": "res://date_picker/value_picker.gd" @@ -37,8 +37,8 @@ _global_script_classes=[ { _global_script_class_icons={ "Database": "", "DatePicker": "", +"PointerInputSensor": "", "Stage": "", -"TouchScroll": "", "ValuePicker": "" } diff --git a/touch_scroll.gd b/touch_scroll.gd deleted file mode 100644 index 7b6aefd..0000000 --- a/touch_scroll.gd +++ /dev/null @@ -1,125 +0,0 @@ -extends Control -class_name TouchScroll - -const DRAG_THRESHOLD_CM: float = 0.250 - -export var click_target_path: String -export var scroll_target_path: String -export var scroll_bar_get_method: String -export var scroll_velocity_decaying_factor: float = 2.5 - -var pointer: Dictionary -var anchor: float -var offset: float -var screen_dpcm: float - -var click_target: Control -var scroll_target: Control -var target_scroll_bar: VScrollBar - - - -# @DAM -# Change this into an event-driven approach by changing the touch_scroll into a signal emitter and -# the target scrollable control a signal consumer. This way, the signal consumer will behave as the -# central node and will have the capability to detect when different touch_scroll sensors are -# activated and stop previous inputs (if required). -# Signal emitters should signal: -# - when an input drag starts -# - when an input drag stops -# - when an input drags -# - when an input clicks - - -func _ready(): - click_target = get_node(click_target_path) - scroll_target = get_node(scroll_target_path) - target_scroll_bar = scroll_target.call(scroll_bar_get_method) - pointer = { - index = -1, - initial_position = Vector2.ZERO, - current_position = Vector2.ZERO, - relative_position = Vector2.ZERO, - velocity = Vector2.ZERO, - was_dragged = false, - is_active = false, - } - screen_dpcm = float(OS.get_screen_dpi()) / 2.54 - - -func _process(delta: float): - # @DAM This only works for the stage... for the database this hides the touch_scroll after the first click. - if click_target.has_focus(): - mouse_filter = Control.MOUSE_FILTER_IGNORE - else: - mouse_filter = Control.MOUSE_FILTER_STOP - - if pointer.is_active: - var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y) - offset = anchor + dragged_distance -# self.target_scroll_bar.value = offset - self.target_scroll_bar.value -= pointer.relative_position.y - pointer.relative_position = Vector2.ZERO - elif pointer.velocity.length() > 0.5: - pointer.velocity *= clamp((1.0 - scroll_velocity_decaying_factor * delta), 0.0, 1.0) - offset -= pointer.velocity.y * delta -# self.target_scroll_bar.value = offset - self.target_scroll_bar.value -= pointer.velocity.y * delta - - -func _gui_input(event: InputEvent): - - # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. - if event is InputEventScreenTouch || event is InputEventScreenDrag: - if event.index != 0: - return - - if event is InputEventScreenTouch && (pointer.is_active == false || pointer.index == event.index): - var touch := event as InputEventScreenTouch - pointer.is_active = event.pressed - pointer.current_position = get_global_mouse_position() # touch.position - if pointer.is_active: - pointer.index = touch.index - pointer.initial_position = get_global_mouse_position() # touch.position - anchor = self.target_scroll_bar.value - else: - if pointer.was_dragged == false: # Click detected. - simulate_gui_click() - pointer.index = -1 - pointer.was_dragged = false - - if event is InputEventScreenDrag && event.index == pointer.index: - var drag := event as InputEventScreenDrag - pointer.current_position = get_global_mouse_position() # drag.position - pointer.velocity = drag.speed - pointer.relative_position = drag.relative - if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM: - pointer.was_dragged = true - - -func simulate_gui_click(): - - var position := self.get_global_mouse_position() - click_target.rect_global_position - - var event_touch := InputEventScreenTouch.new() - event_touch.index = 0 - event_touch.position = position - - var event_mouse := InputEventMouseButton.new() - event_mouse.button_index = BUTTON_LEFT - event_mouse.button_mask = BUTTON_MASK_LEFT - event_mouse.position = position - - event_mouse.pressed = true - event_touch.pressed = true - click_target._gui_input(event_mouse) - click_target._gui_input(event_touch) - - click_target.grab_focus() - - event_mouse.pressed = false - event_touch.pressed = false - click_target._gui_input(event_mouse) - click_target._gui_input(event_touch) - - -- cgit v1.2.3 From 0eeacf3d142b40427ea5ca5b2806fe714c00f9b4 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 6 Jan 2022 11:39:06 +0000 Subject: Isolate database entry code to avoid cyclic references. --- logic/database.gd | 73 +++++-------------------------------------------- logic/database_entry.gd | 64 +++++++++++++++++++++++++++++++++++++++++++ logic/stage.gd | 2 +- project.godot | 6 ++++ 4 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 logic/database_entry.gd (limited to 'project.godot') diff --git a/logic/database.gd b/logic/database.gd index 47cddbc..551b9bf 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -2,26 +2,6 @@ extends ItemList class_name Database const DATABASE_FILE_PATH: String = "user://database.csv" -const DATE_SEPARATOR: String = "-" -const DATE_FORMAT: String = "%04d-%02d-%02d" -const ENTRY_PROTOTYPE: Dictionary = { - "process_id": "", - "surgery_id": "", - "place": "", - "date": "", - "date_year": 0, - "date_month": 0, - "date_day": 0, - "anesthesia": "", - "first_assistant": "", - "type": "", - "sub_type": "", - "sub_sub_type": "", - "pathology": "", - "intervention": "", - "is_urgency": false, - "notes": "", -} const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 var db: Array @@ -30,7 +10,7 @@ var staged_idx: int var is_pointer_dragging := false var pointer_drag_velocity := 0.0 -onready var stage := get_node("/root/main/stage") #as Stage # @DAM Solve cyclic load. +onready var stage := get_node("/root/main/stage") as Stage onready var delete_button := get_node("actions/delete") as Button onready var edit_button := get_node("actions/edit") as Button onready var add_button := get_node("actions/add") as Button @@ -85,7 +65,7 @@ func _notification(what: int): func get_entry_view(database_entry: Dictionary) -> String: - return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, get_entry_date(database_entry)] + return "%6s | %6s | %s" % [database_entry.process_id, database_entry.surgery_id, DatabaseEntry.get_entry_date(database_entry)] func item_selected(index: int): @@ -120,7 +100,7 @@ func edit_action(): func add_action(): self.visible = false stage.visible = true - var staged := instance_entry() + var staged := DatabaseEntry.instance_entry() stage.set_stage(staged) @@ -129,7 +109,7 @@ func scroll_down(): func save_stage(entry: Dictionary): - entry = instance_entry(entry) # @DAM Maybe we could not be creating endless dictionaries? + entry = DatabaseEntry.instance_entry(entry) # @DAM Maybe we could not be creating endless dictionaries? var next_selected_idx: int if staged_idx >= 0: db[staged_idx] = entry @@ -170,7 +150,7 @@ func load_database(file_path: String = DATABASE_FILE_PATH): is_first_line = false headers = csv_entry continue - var entry = ENTRY_PROTOTYPE.duplicate(true) + var entry = DatabaseEntry.instance_entry() for idx in headers.size(): var field_name := headers[idx] var field_value := csv_entry[idx] @@ -187,7 +167,7 @@ func load_database(file_path: String = DATABASE_FILE_PATH): func store_database(file_path: String = DATABASE_FILE_PATH): var file := File.new() file.open(file_path, File.WRITE) - var header := PoolStringArray(ENTRY_PROTOTYPE.keys()) + var header := PoolStringArray(DatabaseEntry.ENTRY_PROTOTYPE.keys()) file.store_csv_line(header) var entry := PoolStringArray() for it in db: @@ -203,52 +183,13 @@ func clear_database(save_changes: bool = false): store_database() -static func instance_entry(params: Dictionary = {}) -> Dictionary: - var new_entry := ENTRY_PROTOTYPE.duplicate(true) - new_entry.process_id = params.get("process_id", "") - new_entry.surgery_id = params.get("surgery_id", "") - new_entry.place = params.get("place", "") - - var today = OS.get_date() - new_entry.date_year = params.get("date_year", today.year) - new_entry.date_month = params.get("date_month", today.month) - new_entry.date_day = params.get("date_day", today.day) - new_entry.date = params.get("date", get_entry_date(new_entry)) # @DAM We should store only one version of the date. - - new_entry.anesthesia = params.get("anesthesia", "") - new_entry.first_assistant = params.get("first_assistant", "") - new_entry.type = params.get("type", "") - new_entry.sub_type = params.get("sub_type", "") - new_entry.sub_sub_type = params.get("sub_sub_type", "") - new_entry.pathology = params.get("pathology", "") - new_entry.intervention = params.get("intervention", "") - new_entry.is_urgency = params.get("is_urgency", false) - new_entry.notes = params.get("notes", "") - - return new_entry - - -static func get_entry_date(entry: Dictionary) -> String: - return DATE_FORMAT % [entry.date_year, entry.date_month, entry.date_day] - - -static func set_entry_date(entry: Dictionary, date: String): - date = date.strip_edges().replace(" ", DATE_SEPARATOR).replace("/", DATE_SEPARATOR).replace("\\", DATE_SEPARATOR) - var year_month_idx := date.find(DATE_SEPARATOR) - var month_day_idx := date.find(DATE_SEPARATOR, year_month_idx + 1) - entry.date = date - entry.date_year = int(date.substr(0, year_month_idx)) - entry.date_month = int(date.substr(year_month_idx + 1, month_day_idx - year_month_idx - 1)) - entry.date_day = int(date.substr(month_day_idx + 1)) - - func fake_database(save_changes: bool = false): clear_database() for idx in range(500): var date_year = 1 + int(float(idx) / 365.0) var date_month = idx % 12 var date_day = idx % 365 - var fake_entry = instance_entry({ + var fake_entry = DatabaseEntry.instance_entry({ "process_id": "%06d" % idx, "surgery_id": "s%05d" % idx, "date": "%04d-%02d-%02d" % [date_year, date_month, date_day] diff --git a/logic/database_entry.gd b/logic/database_entry.gd new file mode 100644 index 0000000..19f2255 --- /dev/null +++ b/logic/database_entry.gd @@ -0,0 +1,64 @@ +extends Reference +class_name DatabaseEntry + +const DATE_SEPARATOR: String = "-" +const DATE_FORMAT: String = "%04d-%02d-%02d" +const ENTRY_PROTOTYPE: Dictionary = { + "process_id": "", + "surgery_id": "", + "place": "", + "date": "", + "date_year": 0, + "date_month": 0, + "date_day": 0, + "anesthesia": "", + "first_assistant": "", + "type": "", + "sub_type": "", + "sub_sub_type": "", + "pathology": "", + "intervention": "", + "is_urgency": false, + "notes": "", +} + + +static func instance_entry(params: Dictionary = {}) -> Dictionary: + var new_entry := ENTRY_PROTOTYPE.duplicate(true) + new_entry.process_id = params.get("process_id", "") + new_entry.surgery_id = params.get("surgery_id", "") + new_entry.place = params.get("place", "") + + var today = OS.get_date() + new_entry.date_year = params.get("date_year", today.year) + new_entry.date_month = params.get("date_month", today.month) + new_entry.date_day = params.get("date_day", today.day) + new_entry.date = params.get("date", get_entry_date(new_entry)) # @DAM We should store only one version of the date. + + new_entry.anesthesia = params.get("anesthesia", "") + new_entry.first_assistant = params.get("first_assistant", "") + new_entry.type = params.get("type", "") + new_entry.sub_type = params.get("sub_type", "") + new_entry.sub_sub_type = params.get("sub_sub_type", "") + new_entry.pathology = params.get("pathology", "") + new_entry.intervention = params.get("intervention", "") + new_entry.is_urgency = params.get("is_urgency", false) + new_entry.notes = params.get("notes", "") + + return new_entry + + +static func get_entry_date(entry: Dictionary) -> String: + return DATE_FORMAT % [entry.date_year, entry.date_month, entry.date_day] + + +static func set_entry_date(entry: Dictionary, date: String): + date = date.strip_edges().replace(" ", DATE_SEPARATOR).replace("/", DATE_SEPARATOR).replace("\\", DATE_SEPARATOR) + var year_month_idx := date.find(DATE_SEPARATOR) + var month_day_idx := date.find(DATE_SEPARATOR, year_month_idx + 1) + entry.date = date + entry.date_year = int(date.substr(0, year_month_idx)) + entry.date_month = int(date.substr(year_month_idx + 1, month_day_idx - year_month_idx - 1)) + entry.date_day = int(date.substr(month_day_idx + 1)) + + diff --git a/logic/stage.gd b/logic/stage.gd index dd345e8..511068e 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -173,7 +173,7 @@ func load_filters(file_path: String = FILTERS_FILE_PATH): is_first_line = false headers = csv_entry continue - var entry = Database.ENTRY_PROTOTYPE.duplicate(true) +# var entry = DatabaseEntry.instance_entry() # for idx in headers.size(): # var field_name := headers[idx] # var field_value := csv_entry[idx] diff --git a/project.godot b/project.godot index f5dbe7a..cfdcbb8 100644 --- a/project.godot +++ b/project.godot @@ -14,6 +14,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://logic/database.gd" }, { +"base": "Reference", +"class": "DatabaseEntry", +"language": "GDScript", +"path": "res://logic/database_entry.gd" +}, { "base": "Control", "class": "DatePicker", "language": "GDScript", @@ -36,6 +41,7 @@ _global_script_classes=[ { } ] _global_script_class_icons={ "Database": "", +"DatabaseEntry": "", "DatePicker": "", "PointerInputSensor": "", "Stage": "", -- cgit v1.2.3 From 5ba40857cdc770841d216a27e2a9e8bb3ebf3186 Mon Sep 17 00:00:00 2001 From: dam Date: Sun, 9 Jan 2022 01:25:55 +0000 Subject: Split touch logic from database. Prototype of popup with list of options. --- logic/database.gd | 67 ++------------------------------ logic/popup_list.gd | 24 ++++++++++++ logic/stage.gd | 75 ++++++++++++++++++++++++++++++++---- main.tscn | 39 ++++++++++--------- pointer_input_sensor.gd | 22 +++++++++++ project.godot | 8 +++- readme.md | 2 + touch_item_list/touch_item_list.gd | 70 +++++++++++++++++++++++++++++++++ touch_item_list/touch_item_list.tscn | 23 +++++++++++ 9 files changed, 240 insertions(+), 90 deletions(-) create mode 100644 logic/popup_list.gd create mode 100644 touch_item_list/touch_item_list.gd create mode 100644 touch_item_list/touch_item_list.tscn (limited to 'project.godot') diff --git a/logic/database.gd b/logic/database.gd index 044681f..de978b7 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -1,21 +1,16 @@ -extends ItemList +extends TouchItemList class_name Database const DATABASE_FILE_PATH: String = "user://database.csv" -const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 var db: Array var selected_idx: int var staged_idx: int -var is_pointer_dragging := false -var pointer_drag_velocity := 0.0 onready var stage := get_node("/root/main/stage") as Stage onready var delete_button := get_node("actions/delete") as Button onready var edit_button := get_node("actions/edit") as Button onready var add_button := get_node("actions/add") as Button -onready var v_scroll_bar := get_v_scroll() as ScrollBar -onready var drag_sensor := get_node("drag_sensor") as PointerInputSensor func _init(): @@ -36,24 +31,13 @@ func _ready(): stage.connect("save", self, "save_stage") stage.connect("discard", self, "discard_stage") - drag_sensor.connect("on_press", self, "pointer_input_handler") - drag_sensor.connect("on_drag", self, "pointer_input_handler") - drag_sensor.connect("on_end_drag", self, "pointer_input_handler") - drag_sensor.connect("on_click", self, "pointer_input_handler") - for it in db: self.add_item(get_entry_view(it)) -func _process(delta: float): - # Apply drag movement inertia. - if is_pointer_dragging == false && abs(pointer_drag_velocity) > 0.5: - pointer_drag_velocity *= clamp((1.0 - POINTER_VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) - v_scroll_bar.value -= pointer_drag_velocity * delta - - func _notification(what: int): - # @DAM Yet to be polished. + # @DAM This code should be moved into the main.gd which should check which node was currently + # active and above, and send the signal there. if visible == false || has_focus() == false: return @@ -77,10 +61,6 @@ func clear_selection(): unselect_all() -func scroll_to_selected(): - v_scroll_bar.value = float(selected_idx)/float(db.size()) * v_scroll_bar.max_value - (v_scroll_bar.page * 0.5) - - func delete_action(): if selected_idx < 0: return @@ -125,7 +105,7 @@ func save_stage(entry: Dictionary): select(next_selected_idx) emit_signal("item_selected", next_selected_idx) # Calling "select" does not trigger the "item_selected" signal. set_item_text(selected_idx, get_entry_view(db[selected_idx])) - call_deferred("scroll_to_selected") + ensure_current_is_visible() store_database() @@ -203,42 +183,3 @@ func fake_database(save_changes: bool = false): store_database() -func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): - match pointer.action: - PointerInputSensor.PointerInputAction.ON_PRESS: - is_pointer_dragging = true - - PointerInputSensor.PointerInputAction.ON_DRAG: - is_pointer_dragging = true - pointer_drag_velocity = pointer.velocity.y - v_scroll_bar.value -= pointer.relative_position.y - - PointerInputSensor.PointerInputAction.ON_END_DRAG: - is_pointer_dragging = false - - PointerInputSensor.PointerInputAction.ON_CLICK: - var target := self - var position := target.get_global_mouse_position() - target.rect_global_position - - var event_touch := InputEventScreenTouch.new() - event_touch.index = 0 - event_touch.position = position - - var event_mouse := InputEventMouseButton.new() - event_mouse.button_index = BUTTON_LEFT - event_mouse.button_mask = BUTTON_MASK_LEFT - event_mouse.position = position - - event_mouse.pressed = true - event_touch.pressed = true - target._gui_input(event_mouse) - target._gui_input(event_touch) - - target.grab_focus() - - event_mouse.pressed = false - event_touch.pressed = false - target._gui_input(event_mouse) - target._gui_input(event_touch) - - diff --git a/logic/popup_list.gd b/logic/popup_list.gd new file mode 100644 index 0000000..1dd156c --- /dev/null +++ b/logic/popup_list.gd @@ -0,0 +1,24 @@ +extends Popup + +signal item_selected + +onready var item_list := get_node("list") as TouchItemList + + +func _ready(): + item_list.connect("item_selected", self, "selected") + + +func popup_options(options: Array): + item_list.v_scroll_bar.value = 0.0 + item_list.clear() + for it in options: + item_list.add_item(it) + self.popup_centered_ratio(0.9) + + +func selected(index: int): + self.hide() + emit_signal("item_selected", index) + + diff --git a/logic/stage.gd b/logic/stage.gd index f6f6e47..dc42273 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -8,7 +8,42 @@ const FILTERS_FILE_PATH: String = "user://filters.csv" const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 var staged_entry := {} -var filters := {} +var filters := { + "place": { + "bloco central": null, + "tondela": null, + "xpto_00": null, + "xpto_01": null, + "xpto_02": null, + "xpto_03": null, + "xpto_04": null, + "xpto_05": null, + "xpto_06": null, + "xpto_07": null, + "xpto_08": null, + "xpto_09": null, + "xpto_10": null, + "xpto_11": null, + "xpto_12": null, + "xpto_13": null, + "xpto_14": null, + "xpto_15": null, + "xpto_16": null, + "xpto_17": null, + "xpto_18": null, + "xpto_19": null, + "xpto_20": null, + "xpto_21": null, + "xpto_22": null, + "xpto_23": null, + "xpto_24": null, + "xpto_25": null, + "xpto_26": null, + "xpto_27": null, + "xpto_28": null, + "xpto_29": null, + }, +} var is_pointer_dragging := false var pointer_drag_velocity := 0.0 @@ -60,6 +95,22 @@ func _ready(): if it is LineEdit: it.connect("focus_exited", it, "deselect") + + var auto_place := place.get_node("auto") as Button + auto_place.connect("pressed", self, "auto_populate", ["place"]) + + +func auto_populate(field: String): + var stage_options = get_node("/root/main/popup_list") as Popup + stage_options.connect("item_selected", self, "auto_selected", [field], CONNECT_ONESHOT) + stage_options.popup_options(filters[field].keys()) + + +func auto_selected(index: int, field: String): + var field_input: LineEdit = self[field] + field_input.text = filters[field].keys()[index] + field_input.caret_position = field_input.text.length() + func _process(delta: float): @@ -116,11 +167,6 @@ func get_stage() -> Dictionary: return staged_entry -func _notification(what: int): - if what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: - discard_action() - - func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): match pointer.action: PointerInputSensor.PointerInputAction.ON_PRESS: @@ -135,9 +181,23 @@ func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): is_pointer_dragging = false PointerInputSensor.PointerInputAction.ON_CLICK: + + # @DAM Try this approach on the TouchItemList + var target: Control = pointer.target.get_parent() var position := target.get_global_mouse_position() - target.rect_global_position + var button: Button = target.get_node("auto") + if button != null && button.get_rect().has_point(position): + button.grab_focus() +# button.emit_signal("button_down") + button.emit_signal("pressed") +# button.emit_signal("button_up") + else: + target.grab_focus() + return + + var event_touch := InputEventScreenTouch.new() event_touch.index = 0 event_touch.position = position @@ -153,13 +213,14 @@ func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): target._gui_input(event_touch) target.grab_focus() - + event_mouse.pressed = false event_touch.pressed = false target._gui_input(event_mouse) target._gui_input(event_touch) + func load_filters(file_path: String = FILTERS_FILE_PATH): var file := File.new() file.open(file_path, File.READ_WRITE) diff --git a/main.tscn b/main.tscn index d4ff096..52d9ccf 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=11 format=2] +[gd_scene load_steps=12 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] @@ -9,7 +9,8 @@ [ext_resource path="res://icons/add.png" type="Texture" id=7] [ext_resource path="res://icons/delete.png" type="Texture" id=8] [ext_resource path="res://logic/stage.gd" type="Script" id=9] -[ext_resource path="res://pointer_input_sensor.gd" type="Script" id=10] +[ext_resource path="res://logic/popup_list.gd" type="Script" id=10] +[ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] [node name="main" type="Control"] anchor_right = 1.0 @@ -20,24 +21,8 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="database" type="ItemList" parent="."] -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_top = 60.0 -mouse_filter = 2 +[node name="database" parent="." instance=ExtResource( 11 )] script = ExtResource( 5 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="drag_sensor" type="Control" parent="database"] -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_right = -8.0 -script = ExtResource( 10 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="actions" type="VBoxContainer" parent="database"] anchor_left = 1.0 @@ -133,6 +118,12 @@ placeholder_text = "Local" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/place"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" + [node name="anesthesia" type="LineEdit" parent="stage/controls"] margin_top = 363.0 margin_right = 1080.0 @@ -243,6 +234,7 @@ anchor_bottom = 1.0 size_flags_horizontal = 3 size_flags_vertical = 3 window_title = "PICK FILE" +mode_overrides_title = false access = 2 filters = PoolStringArray( "*.csv" ) show_hidden_files = true @@ -261,6 +253,15 @@ window_title = "CONFIRM ACTION" dialog_text = "Are you sure you want to delete all filters?" dialog_autowrap = true +[node name="popup_list" type="Popup" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +popup_exclusive = true +script = ExtResource( 10 ) + +[node name="list" parent="popup_list" instance=ExtResource( 11 )] +margin_top = 0.0 + [node name="debug" type="Label" parent="."] visible = false anchor_right = 1.0 diff --git a/pointer_input_sensor.gd b/pointer_input_sensor.gd index 27f257c..ee5e390 100644 --- a/pointer_input_sensor.gd +++ b/pointer_input_sensor.gd @@ -12,6 +12,7 @@ signal on_exit signal on_begin_drag signal on_drag signal on_end_drag +signal on_scroll enum PointerInputAction { UNDEFINED, @@ -25,10 +26,12 @@ enum PointerInputAction { ON_BEGIN_DRAG, ON_DRAG, ON_END_DRAG, + ON_SCROLL, } class PointerInputData: var target: PointerInputSensor + var event: InputEvent var index := -1 var initial_position := Vector2.ZERO var current_position := Vector2.ZERO @@ -36,8 +39,10 @@ class PointerInputData: var velocity := Vector2.ZERO var was_dragged := false var is_pressed := false + var scroll := 0.0 var action: int = PointerInputAction.UNDEFINED + export var drag_threshold_cm: float = 0.250 var pointer: PointerInputData @@ -64,6 +69,12 @@ func _gui_input(event: InputEvent): if event.index != 0: return + pointer.event = event +# pointer.index = -1 +# pointer.scroll = 0.0 +# pointer.action = PointerInputAction.UNDEFINED +# pointer.velocity = Vector2.ZERO + if event is InputEventScreenTouch && (pointer.is_pressed == false || pointer.index == event.index): var touch := event as InputEventScreenTouch pointer.is_pressed = event.pressed @@ -84,6 +95,10 @@ func _gui_input(event: InputEvent): emit_signal("on_end_drag", pointer) pointer.index = -1 pointer.was_dragged = false + # @DAM Maybe add this. +# pointer.initial_position = Vector2.ZERO +# pointer.current_position = Vector2.ZERO +# pointer.relative_position = Vector2.ZERO if event is InputEventScreenDrag && event.index == pointer.index: var drag := event as InputEventScreenDrag @@ -96,5 +111,12 @@ func _gui_input(event: InputEvent): emit_signal("on_begin_drag", pointer) pointer.action = PointerInputAction.ON_DRAG emit_signal("on_drag", pointer) + + # @DAM Clean this code please. + if event is InputEventMouseButton && event.is_pressed(): + if event.button_index == BUTTON_WHEEL_UP || event.button_index == BUTTON_WHEEL_DOWN: + pointer.scroll = -1.0 if event.button_index == BUTTON_WHEEL_UP else 1.0 + pointer.action = PointerInputAction.ON_SCROLL + emit_signal("on_scroll", pointer) diff --git a/project.godot b/project.godot index cfdcbb8..d630b8d 100644 --- a/project.godot +++ b/project.godot @@ -9,7 +9,7 @@ config_version=4 _global_script_classes=[ { -"base": "ItemList", +"base": "TouchItemList", "class": "Database", "language": "GDScript", "path": "res://logic/database.gd" @@ -34,6 +34,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://logic/stage.gd" }, { +"base": "ItemList", +"class": "TouchItemList", +"language": "GDScript", +"path": "res://touch_item_list/touch_item_list.gd" +}, { "base": "Control", "class": "ValuePicker", "language": "GDScript", @@ -45,6 +50,7 @@ _global_script_class_icons={ "DatePicker": "", "PointerInputSensor": "", "Stage": "", +"TouchItemList": "", "ValuePicker": "" } diff --git a/readme.md b/readme.md index 0a85447..6a341e3 100644 --- a/readme.md +++ b/readme.md @@ -16,6 +16,8 @@ Surgery Log - [x] load/store database CSV file; - [x] export database to CSV file; - [x] allow to reset database; +- [x] split touch logic from database (create TouchItemList); +- [ ] split touch logic from stage (create TouchVerticalContainer); - [ ] load/store filters CSV file; - [ ] import/export filters to CSV file; - [ ] Implement file access permission check on Android: diff --git a/touch_item_list/touch_item_list.gd b/touch_item_list/touch_item_list.gd new file mode 100644 index 0000000..d2d0d37 --- /dev/null +++ b/touch_item_list/touch_item_list.gd @@ -0,0 +1,70 @@ +extends ItemList +class_name TouchItemList + +const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 + +var is_pointer_dragging := false +var pointer_drag_velocity := 0.0 + +onready var drag_sensor := get_node("drag_sensor") as PointerInputSensor +onready var v_scroll_bar := get_v_scroll() as ScrollBar + + +func _ready(): + drag_sensor.connect("on_press", self, "pointer_input_handler") + drag_sensor.connect("on_drag", self, "pointer_input_handler") + drag_sensor.connect("on_end_drag", self, "pointer_input_handler") + drag_sensor.connect("on_click", self, "pointer_input_handler") + drag_sensor.connect("on_scroll", self, "pointer_input_handler") + + +func _process(delta: float): + # Apply drag movement inertia. + if is_pointer_dragging == false && abs(pointer_drag_velocity) > 0.5: + pointer_drag_velocity *= clamp((1.0 - POINTER_VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) + v_scroll_bar.value -= pointer_drag_velocity * delta + + +func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): + match pointer.action: + PointerInputSensor.PointerInputAction.ON_PRESS: + is_pointer_dragging = true + + PointerInputSensor.PointerInputAction.ON_DRAG: + is_pointer_dragging = true + pointer_drag_velocity = pointer.velocity.y + v_scroll_bar.value -= pointer.relative_position.y + + PointerInputSensor.PointerInputAction.ON_END_DRAG: + is_pointer_dragging = false + + PointerInputSensor.PointerInputAction.ON_SCROLL: + var target := self + target._gui_input(pointer.event) + + PointerInputSensor.PointerInputAction.ON_CLICK: + var target := self + var position := target.get_global_mouse_position() - target.rect_global_position + + var event_touch := InputEventScreenTouch.new() + event_touch.index = 0 + event_touch.position = position + + var event_mouse := InputEventMouseButton.new() + event_mouse.button_index = BUTTON_LEFT + event_mouse.button_mask = BUTTON_MASK_LEFT + event_mouse.position = position + + event_mouse.pressed = true + event_touch.pressed = true + target._gui_input(event_mouse) + target._gui_input(event_touch) + + target.grab_focus() + + event_mouse.pressed = false + event_touch.pressed = false + target._gui_input(event_mouse) + target._gui_input(event_touch) + + diff --git a/touch_item_list/touch_item_list.tscn b/touch_item_list/touch_item_list.tscn new file mode 100644 index 0000000..6022ed4 --- /dev/null +++ b/touch_item_list/touch_item_list.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://pointer_input_sensor.gd" type="Script" id=1] +[ext_resource path="res://touch_item_list/touch_item_list.gd" type="Script" id=2] + +[node name="item_list" type="ItemList"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_top = 60.0 +mouse_filter = 2 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="drag_sensor" type="Control" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -8.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} -- cgit v1.2.3 From 81b602620412fbad0429e841051c30c537a1b461 Mon Sep 17 00:00:00 2001 From: dam Date: Mon, 10 Jan 2022 17:56:30 +0000 Subject: Split touch logic from stage --- logic/stage.gd | 99 ++-------------------- main.tscn | 48 +++++------ project.godot | 8 +- readme.md | 5 +- touch_item_list/touch_item_list.gd | 96 +++++++++++---------- touch_item_list/touch_item_list.tscn | 2 +- .../touch_vertical_container.gd | 78 +++++++++++++++++ .../touch_vertical_container.tscn | 18 ++++ 8 files changed, 183 insertions(+), 171 deletions(-) create mode 100644 touch_vertical_container/touch_vertical_container.gd create mode 100644 touch_vertical_container/touch_vertical_container.tscn (limited to 'project.godot') diff --git a/logic/stage.gd b/logic/stage.gd index dc42273..12457c9 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -1,11 +1,10 @@ -extends ScrollContainer +extends TouchVerticalContainer class_name Stage signal save # (database_entry: Dictionary) signal discard # () const FILTERS_FILE_PATH: String = "user://filters.csv" -const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 var staged_entry := {} var filters := { @@ -44,8 +43,6 @@ var filters := { "xpto_29": null, }, } -var is_pointer_dragging := false -var pointer_drag_velocity := 0.0 onready var process_id := get_node("controls/process_id") as LineEdit onready var surgery_id := get_node("controls/surgery_id") as LineEdit @@ -62,40 +59,16 @@ onready var is_urgency := get_node("controls/is_urgency") as Button onready var notes := get_node("controls/notes") as LineEdit onready var save_button := get_node("controls/save") as Button onready var discard_button := get_node("controls/discard") as Button -onready var v_scroll_bar := get_v_scrollbar() as VScrollBar + + +func _init(): + exclude_controls = ["date_picker", "save", "discard"] func _ready(): save_button.connect("pressed", self, "save_action") discard_button.connect("pressed", self, "discard_action") - for it in get_node("controls").get_children(): - it = it as Control - match it.name: - "date_picker", "save", "discard": - pass - - _: - var drag_sensor = PointerInputSensor.new() - it.add_child(drag_sensor) - - drag_sensor.name = "drag_sensor" - drag_sensor.anchor_right = 1.0 - drag_sensor.anchor_bottom = 1.0 - - drag_sensor.connect("on_press", self, "pointer_input_handler") - drag_sensor.connect("on_drag", self, "pointer_input_handler") - drag_sensor.connect("on_end_drag", self, "pointer_input_handler") - drag_sensor.connect("on_click", self, "pointer_input_handler") - - it.connect("focus_entered", drag_sensor, "set_mouse_filter", [Control.MOUSE_FILTER_IGNORE]) - it.connect("focus_entered", drag_sensor, "mouse_default_cursor_shape", [Control.CURSOR_IBEAM]) - it.connect("focus_exited", drag_sensor, "set_mouse_filter", [Control.MOUSE_FILTER_STOP]) - it.connect("focus_exited", drag_sensor, "mouse_default_cursor_shape", [Control.CURSOR_ARROW]) - - if it is LineEdit: - it.connect("focus_exited", it, "deselect") - var auto_place := place.get_node("auto") as Button auto_place.connect("pressed", self, "auto_populate", ["place"]) @@ -112,14 +85,6 @@ func auto_selected(index: int, field: String): field_input.caret_position = field_input.text.length() - -func _process(delta: float): - # Apply drag movement inertia. - if is_pointer_dragging == false && abs(pointer_drag_velocity) > 0.5: - pointer_drag_velocity *= clamp((1.0 - POINTER_VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) - v_scroll_bar.value -= pointer_drag_velocity * delta - - func save_action(): self.visible = false emit_signal("save", get_stage()) @@ -167,60 +132,6 @@ func get_stage() -> Dictionary: return staged_entry -func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): - match pointer.action: - PointerInputSensor.PointerInputAction.ON_PRESS: - is_pointer_dragging = true - - PointerInputSensor.PointerInputAction.ON_DRAG: - is_pointer_dragging = true - pointer_drag_velocity = pointer.velocity.y - v_scroll_bar.value -= pointer.relative_position.y - - PointerInputSensor.PointerInputAction.ON_END_DRAG: - is_pointer_dragging = false - - PointerInputSensor.PointerInputAction.ON_CLICK: - - # @DAM Try this approach on the TouchItemList - - var target: Control = pointer.target.get_parent() - var position := target.get_global_mouse_position() - target.rect_global_position - - var button: Button = target.get_node("auto") - if button != null && button.get_rect().has_point(position): - button.grab_focus() -# button.emit_signal("button_down") - button.emit_signal("pressed") -# button.emit_signal("button_up") - else: - target.grab_focus() - return - - - var event_touch := InputEventScreenTouch.new() - event_touch.index = 0 - event_touch.position = position - - var event_mouse := InputEventMouseButton.new() - event_mouse.button_index = BUTTON_LEFT - event_mouse.button_mask = BUTTON_MASK_LEFT - event_mouse.position = position - - event_mouse.pressed = true - event_touch.pressed = true - target._gui_input(event_mouse) - target._gui_input(event_touch) - - target.grab_focus() - - event_mouse.pressed = false - event_touch.pressed = false - target._gui_input(event_mouse) - target._gui_input(event_touch) - - - func load_filters(file_path: String = FILTERS_FILE_PATH): var file := File.new() file.open(file_path, File.READ_WRITE) diff --git a/main.tscn b/main.tscn index 52d9ccf..45cacd4 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=2] +[gd_scene load_steps=13 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] @@ -11,6 +11,7 @@ [ext_resource path="res://logic/stage.gd" type="Script" id=9] [ext_resource path="res://logic/popup_list.gd" type="Script" id=10] [ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] +[ext_resource path="res://touch_vertical_container/touch_vertical_container.tscn" type="PackedScene" id=12] [node name="main" type="Control"] anchor_right = 1.0 @@ -70,31 +71,22 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="stage" type="ScrollContainer" parent="."] +[node name="stage" parent="." instance=ExtResource( 12 )] visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 margin_top = 60.0 -scroll_horizontal_enabled = false script = ExtResource( 9 ) -__meta__ = { -"_edit_use_anchors_": false -} -[node name="controls" type="VBoxContainer" parent="stage"] -margin_right = 1080.0 +[node name="controls" parent="stage" index="0"] margin_bottom = 1860.0 -size_flags_horizontal = 3 -size_flags_vertical = 3 -[node name="process_id" type="LineEdit" parent="stage/controls"] +[node name="process_id" type="LineEdit" parent="stage/controls" index="0"] margin_right = 1080.0 margin_bottom = 49.0 placeholder_text = "Nº Processo" caret_blink = true caret_blink_speed = 0.5 -[node name="surgery_id" type="LineEdit" parent="stage/controls"] +[node name="surgery_id" type="LineEdit" parent="stage/controls" index="1"] margin_top = 53.0 margin_right = 1080.0 margin_bottom = 102.0 @@ -102,7 +94,7 @@ placeholder_text = "Nº Cirurgia" caret_blink = true caret_blink_speed = 0.5 -[node name="date_picker" parent="stage/controls" instance=ExtResource( 2 )] +[node name="date_picker" parent="stage/controls" index="2" instance=ExtResource( 2 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 106.0 @@ -110,7 +102,7 @@ margin_right = 1080.0 margin_bottom = 306.0 rect_min_size = Vector2( 400, 200 ) -[node name="place" type="LineEdit" parent="stage/controls"] +[node name="place" type="LineEdit" parent="stage/controls" index="3"] margin_top = 310.0 margin_right = 1080.0 margin_bottom = 359.0 @@ -124,7 +116,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 text = "X" -[node name="anesthesia" type="LineEdit" parent="stage/controls"] +[node name="anesthesia" type="LineEdit" parent="stage/controls" index="4"] margin_top = 363.0 margin_right = 1080.0 margin_bottom = 412.0 @@ -132,7 +124,7 @@ placeholder_text = "Anestesia" caret_blink = true caret_blink_speed = 0.5 -[node name="first_assistant" type="LineEdit" parent="stage/controls"] +[node name="first_assistant" type="LineEdit" parent="stage/controls" index="5"] margin_top = 416.0 margin_right = 1080.0 margin_bottom = 465.0 @@ -140,7 +132,7 @@ placeholder_text = "1º Ajudante" caret_blink = true caret_blink_speed = 0.5 -[node name="type" type="LineEdit" parent="stage/controls"] +[node name="type" type="LineEdit" parent="stage/controls" index="6"] margin_top = 469.0 margin_right = 1080.0 margin_bottom = 518.0 @@ -148,7 +140,7 @@ placeholder_text = "Tipo" caret_blink = true caret_blink_speed = 0.5 -[node name="sub_type" type="LineEdit" parent="stage/controls"] +[node name="sub_type" type="LineEdit" parent="stage/controls" index="7"] margin_top = 522.0 margin_right = 1080.0 margin_bottom = 571.0 @@ -156,7 +148,7 @@ placeholder_text = "Subtipo" caret_blink = true caret_blink_speed = 0.5 -[node name="sub_sub_type" type="LineEdit" parent="stage/controls"] +[node name="sub_sub_type" type="LineEdit" parent="stage/controls" index="8"] margin_top = 575.0 margin_right = 1080.0 margin_bottom = 624.0 @@ -164,7 +156,7 @@ placeholder_text = "Sub-Subtipo" caret_blink = true caret_blink_speed = 0.5 -[node name="pathology" type="LineEdit" parent="stage/controls"] +[node name="pathology" type="LineEdit" parent="stage/controls" index="9"] margin_top = 628.0 margin_right = 1080.0 margin_bottom = 677.0 @@ -172,7 +164,7 @@ placeholder_text = "Patologia" caret_blink = true caret_blink_speed = 0.5 -[node name="intervention" type="LineEdit" parent="stage/controls"] +[node name="intervention" type="LineEdit" parent="stage/controls" index="10"] margin_top = 681.0 margin_right = 1080.0 margin_bottom = 730.0 @@ -180,13 +172,13 @@ placeholder_text = "Intervenção" caret_blink = true caret_blink_speed = 0.5 -[node name="is_urgency" type="CheckBox" parent="stage/controls"] +[node name="is_urgency" type="CheckBox" parent="stage/controls" index="11"] margin_top = 734.0 margin_right = 1080.0 margin_bottom = 781.0 text = "Urgência" -[node name="notes" type="LineEdit" parent="stage/controls"] +[node name="notes" type="LineEdit" parent="stage/controls" index="12"] margin_top = 785.0 margin_right = 1080.0 margin_bottom = 834.0 @@ -194,7 +186,7 @@ placeholder_text = "Notas" caret_blink = true caret_blink_speed = 0.5 -[node name="discard" type="Button" parent="stage/controls"] +[node name="discard" type="Button" parent="stage/controls" index="13"] margin_top = 838.0 margin_right = 1080.0 margin_bottom = 888.0 @@ -206,7 +198,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="save" type="Button" parent="stage/controls"] +[node name="save" type="Button" parent="stage/controls" index="14"] margin_top = 892.0 margin_right = 1080.0 margin_bottom = 942.0 @@ -271,3 +263,5 @@ valign = 2 __meta__ = { "_edit_use_anchors_": false } + +[editable path="stage"] diff --git a/project.godot b/project.godot index d630b8d..9067744 100644 --- a/project.godot +++ b/project.godot @@ -29,7 +29,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://pointer_input_sensor.gd" }, { -"base": "ScrollContainer", +"base": "TouchVerticalContainer", "class": "Stage", "language": "GDScript", "path": "res://logic/stage.gd" @@ -39,6 +39,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://touch_item_list/touch_item_list.gd" }, { +"base": "ScrollContainer", +"class": "TouchVerticalContainer", +"language": "GDScript", +"path": "res://touch_vertical_container/touch_vertical_container.gd" +}, { "base": "Control", "class": "ValuePicker", "language": "GDScript", @@ -51,6 +56,7 @@ _global_script_class_icons={ "PointerInputSensor": "", "Stage": "", "TouchItemList": "", +"TouchVerticalContainer": "", "ValuePicker": "" } diff --git a/readme.md b/readme.md index 6a341e3..ccfbca1 100644 --- a/readme.md +++ b/readme.md @@ -17,7 +17,10 @@ Surgery Log - [x] export database to CSV file; - [x] allow to reset database; - [x] split touch logic from database (create TouchItemList); -- [ ] split touch logic from stage (create TouchVerticalContainer); +- [x] split touch logic from stage (create TouchVerticalContainer); +- [ ] on-press: + - highlight item on lists + - mark auto buttons as pressed - [ ] load/store filters CSV file; - [ ] import/export filters to CSV file; - [ ] Implement file access permission check on Android: diff --git a/touch_item_list/touch_item_list.gd b/touch_item_list/touch_item_list.gd index d2d0d37..0534bb2 100644 --- a/touch_item_list/touch_item_list.gd +++ b/touch_item_list/touch_item_list.gd @@ -6,16 +6,16 @@ const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 var is_pointer_dragging := false var pointer_drag_velocity := 0.0 -onready var drag_sensor := get_node("drag_sensor") as PointerInputSensor +onready var sensor := get_node("sensor") as PointerInputSensor onready var v_scroll_bar := get_v_scroll() as ScrollBar func _ready(): - drag_sensor.connect("on_press", self, "pointer_input_handler") - drag_sensor.connect("on_drag", self, "pointer_input_handler") - drag_sensor.connect("on_end_drag", self, "pointer_input_handler") - drag_sensor.connect("on_click", self, "pointer_input_handler") - drag_sensor.connect("on_scroll", self, "pointer_input_handler") + sensor.connect("on_press", self, "pointer_input_on_press_handler") + sensor.connect("on_drag", self, "pointer_input_on_drag_handler") + sensor.connect("on_end_drag", self, "pointer_input_on_end_drag_handler") + sensor.connect("on_click", self, "pointer_input_on_click_handler") + sensor.connect("on_scroll", self, "pointer_input_on_scroll_handler") func _process(delta: float): @@ -25,46 +25,48 @@ func _process(delta: float): v_scroll_bar.value -= pointer_drag_velocity * delta -func pointer_input_handler(pointer: PointerInputSensor.PointerInputData): - match pointer.action: - PointerInputSensor.PointerInputAction.ON_PRESS: - is_pointer_dragging = true - - PointerInputSensor.PointerInputAction.ON_DRAG: - is_pointer_dragging = true - pointer_drag_velocity = pointer.velocity.y - v_scroll_bar.value -= pointer.relative_position.y - - PointerInputSensor.PointerInputAction.ON_END_DRAG: - is_pointer_dragging = false - - PointerInputSensor.PointerInputAction.ON_SCROLL: - var target := self - target._gui_input(pointer.event) - - PointerInputSensor.PointerInputAction.ON_CLICK: - var target := self - var position := target.get_global_mouse_position() - target.rect_global_position - - var event_touch := InputEventScreenTouch.new() - event_touch.index = 0 - event_touch.position = position - - var event_mouse := InputEventMouseButton.new() - event_mouse.button_index = BUTTON_LEFT - event_mouse.button_mask = BUTTON_MASK_LEFT - event_mouse.position = position - - event_mouse.pressed = true - event_touch.pressed = true - target._gui_input(event_mouse) - target._gui_input(event_touch) - - target.grab_focus() - - event_mouse.pressed = false - event_touch.pressed = false - target._gui_input(event_mouse) - target._gui_input(event_touch) +func pointer_input_on_press_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + + +func pointer_input_on_drag_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + pointer_drag_velocity = pointer.velocity.y + v_scroll_bar.value -= pointer.relative_position.y + + +func pointer_input_on_end_drag_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = false + + +func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): + var target := self + var position := target.get_global_mouse_position() - target.rect_global_position + + var event_touch := InputEventScreenTouch.new() + event_touch.index = 0 + event_touch.position = position + + var event_mouse := InputEventMouseButton.new() + event_mouse.button_index = BUTTON_LEFT + event_mouse.button_mask = BUTTON_MASK_LEFT + event_mouse.position = position + + event_mouse.pressed = true + event_touch.pressed = true + target._gui_input(event_mouse) + target._gui_input(event_touch) + + target.grab_focus() + + event_mouse.pressed = false + event_touch.pressed = false + target._gui_input(event_mouse) + target._gui_input(event_touch) + + +func pointer_input_on_scroll_handler(pointer: PointerInputSensor.PointerInputData): + var target := self + target._gui_input(pointer.event) diff --git a/touch_item_list/touch_item_list.tscn b/touch_item_list/touch_item_list.tscn index 6022ed4..6207e7d 100644 --- a/touch_item_list/touch_item_list.tscn +++ b/touch_item_list/touch_item_list.tscn @@ -13,7 +13,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="drag_sensor" type="Control" parent="."] +[node name="sensor" type="Control" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 margin_right = -8.0 diff --git a/touch_vertical_container/touch_vertical_container.gd b/touch_vertical_container/touch_vertical_container.gd new file mode 100644 index 0000000..10462fd --- /dev/null +++ b/touch_vertical_container/touch_vertical_container.gd @@ -0,0 +1,78 @@ +extends ScrollContainer +class_name TouchVerticalContainer + +const POINTER_VELOCITY_DECAYING_FACTOR: float = 2.5 + +var is_pointer_dragging := false +var pointer_drag_velocity := 0.0 +var exclude_controls := [] + + +func _ready(): + + for it in get_node("controls").get_children(): + it = it as Control + if exclude_controls.has(it.name): + continue + + var sensor = PointerInputSensor.new() + it.add_child(sensor) + + sensor.name = "sensor" + sensor.anchor_right = 1.0 + sensor.anchor_bottom = 1.0 + + sensor.connect("on_press", self, "pointer_input_on_press_handler") + sensor.connect("on_drag", self, "pointer_input_on_drag_handler") + sensor.connect("on_end_drag", self, "pointer_input_on_end_drag_handler") + sensor.connect("on_click", self, "pointer_input_on_click_handler") + + it.connect("focus_entered", sensor, "set_mouse_filter", [Control.MOUSE_FILTER_IGNORE]) + it.connect("focus_entered", sensor, "mouse_default_cursor_shape", [Control.CURSOR_IBEAM]) + it.connect("focus_exited", sensor, "set_mouse_filter", [Control.MOUSE_FILTER_STOP]) + it.connect("focus_exited", sensor, "mouse_default_cursor_shape", [Control.CURSOR_ARROW]) + + if it is LineEdit: + it.connect("focus_exited", it, "deselect") + + +func _process(delta: float): + # Apply drag movement inertia. + if is_pointer_dragging == false && abs(pointer_drag_velocity) > 0.5: + pointer_drag_velocity *= clamp((1.0 - POINTER_VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) + self.scroll_vertical -= pointer_drag_velocity * delta + + +func pointer_input_on_press_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + + +func pointer_input_on_drag_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + pointer_drag_velocity = pointer.velocity.y + self.scroll_vertical -= pointer.relative_position.y + + +func pointer_input_on_end_drag_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = false + + +func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): + var target: Control = pointer.target.get_parent() + var position := target.get_global_mouse_position() + target.grab_focus() + + var button: Button + if target is Button: + button = target + elif target.get_node("auto") is Button: + button = target.get_node("auto") + + if button != null && button.get_global_rect().has_point(position): + if button is CheckBox || button is CheckButton: + button.pressed = !button.pressed + button.emit_signal("button_down") + button.emit_signal("pressed") + button.emit_signal("button_up") + + diff --git a/touch_vertical_container/touch_vertical_container.tscn b/touch_vertical_container/touch_vertical_container.tscn new file mode 100644 index 0000000..770ac38 --- /dev/null +++ b/touch_vertical_container/touch_vertical_container.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://touch_vertical_container/touch_vertical_container.gd" type="Script" id=1] + +[node name="scroll_container" type="ScrollContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +scroll_horizontal_enabled = false +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="controls" type="VBoxContainer" parent="."] +margin_right = 1080.0 +margin_bottom = 1920.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 -- cgit v1.2.3 From 48a26128f175047528fcc1c96590f1a7bbc281eb Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 17 Feb 2022 00:30:16 +0000 Subject: Prototype with custom option set control. --- logic/stage.gd | 47 +++---- main.tscn | 151 ++++++--------------- option_set/option_set.gd | 15 ++ option_set/option_set.tscn | 34 +++++ project.godot | 6 + .../touch_vertical_container.gd | 35 ++++- 6 files changed, 146 insertions(+), 142 deletions(-) create mode 100644 option_set/option_set.gd create mode 100644 option_set/option_set.tscn (limited to 'project.godot') diff --git a/logic/stage.gd b/logic/stage.gd index 66d6d6d..3cc5943 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -26,14 +26,14 @@ onready var confirm_action := get_node("/root/main/confirm_action") as Confirmat onready var process_id := get_node("controls/process_id") as LineEdit onready var surgery_id := get_node("controls/surgery_id") as LineEdit onready var date := get_node("controls/date_picker") as DatePicker -onready var place := get_node("controls/place") as LineEdit -onready var anesthesia := get_node("controls/anesthesia") as LineEdit -onready var first_assistant := get_node("controls/first_assistant") as LineEdit -onready var type := get_node("controls/type") as LineEdit -onready var sub_type := get_node("controls/sub_type") as LineEdit -onready var sub_sub_type := get_node("controls/sub_sub_type") as LineEdit -onready var pathology := get_node("controls/pathology") as LineEdit -onready var intervention := get_node("controls/intervention") as LineEdit +onready var place := get_node("controls/place") as OptionSet +onready var anesthesia := get_node("controls/anesthesia") as OptionSet +onready var first_assistant := get_node("controls/first_assistant") as OptionSet +onready var type := get_node("controls/type") as OptionSet +onready var sub_type := get_node("controls/sub_type") as OptionSet +onready var sub_sub_type := get_node("controls/sub_sub_type") as OptionSet +onready var pathology := get_node("controls/pathology") as OptionSet +onready var intervention := get_node("controls/intervention") as OptionSet onready var is_urgency := get_node("controls/is_urgency") as Button onready var notes := get_node("controls/notes") as LineEdit onready var save_button := get_node("controls/save") as Button @@ -49,8 +49,9 @@ func _ready(): save_button.connect("pressed", self, "save_action") discard_button.connect("pressed", self, "discard_action") + # @DAM Not working because we changed the stage/controls/.. estructure with the new option_sets. + # @DAM We could try to do a recursive approach or, build a stack of next items to process. for it in get_node("controls").get_children(): - it = it as Control if it is LineEdit: it.connect("focus_entered", it, "set_cursor_position", [99999999]) # @DAM Use MAX_INT it.connect("focus_exited", it, "deselect") @@ -67,7 +68,12 @@ func _ready(): "intervention": intervention } for key in option_sets_map: - var button := option_sets_map[key].get_node("option_set") as Button +# var button := option_sets_map[key].get_node("option_set") as Button +# button.connect("pressed", self, "show_option_sets", [key]) + +# if key != "place": # @DAM DEBUG +# continue + var button := option_sets_map[key].get_node("options") as Button button.connect("pressed", self, "show_option_sets", [key]) @@ -89,6 +95,7 @@ func get_option_sets(field: String): return options +# @DAM WIP I suspect that these should go inside the option_set class... func show_option_sets(field: String): var stage_options = get_node("/root/main/popup_list") as Popup stage_options.connect("item_selected", self, "option_set_selected", [field], CONNECT_ONESHOT) @@ -96,7 +103,7 @@ func show_option_sets(field: String): func option_set_selected(index: int, field: String): - var field_input: LineEdit = self[field] + var field_input: LineEdit = self[field].get_node("input") field_input.text = get_option_sets(field)[index] field_input.caret_position = field_input.text.length() @@ -232,21 +239,3 @@ func clear_option_sets(save_changes: bool = false): store_option_sets() -func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): - .pointer_input_on_click_handler(pointer) - - var target: Control = pointer.target.get_parent() - var button: Button - if target is Button: - button = target - elif target.get_node("option_set") is Button: - button = target.get_node("option_set") - - if button != null && button.get_global_rect().has_point(pointer.current_position): - if button is CheckBox || button is CheckButton: - button.pressed = !button.pressed - button.emit_signal("button_down") - button.emit_signal("pressed") - button.emit_signal("button_up") - - diff --git a/main.tscn b/main.tscn index 6f38c89..db7c7f7 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=11 format=2] +[gd_scene load_steps=12 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] @@ -6,6 +6,7 @@ [ext_resource path="res://menu/menu.gd" type="Script" id=4] [ext_resource path="res://logic/database.gd" type="Script" id=5] [ext_resource path="res://fonts/font_icons.tres" type="DynamicFont" id=6] +[ext_resource path="res://option_set/option_set.tscn" type="PackedScene" id=7] [ext_resource path="res://logic/stage.gd" type="Script" id=9] [ext_resource path="res://logic/popup_list.gd" type="Script" id=10] [ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] @@ -52,6 +53,8 @@ __meta__ = { } [node name="delete" type="Button" parent="database/actions"] +margin_right = 95.0 +margin_bottom = 162.0 focus_mode = 0 custom_fonts/font = ExtResource( 6 ) enabled_focus_mode = 0 @@ -62,8 +65,9 @@ __meta__ = { } [node name="edit" type="Button" parent="database/actions"] -anchor_top = 0.333 -anchor_bottom = 0.333 +margin_top = 166.0 +margin_right = 95.0 +margin_bottom = 328.0 focus_mode = 0 custom_fonts/font = ExtResource( 6 ) enabled_focus_mode = 0 @@ -74,8 +78,9 @@ __meta__ = { } [node name="add" type="Button" parent="database/actions"] -anchor_top = 0.667 -anchor_bottom = 0.667 +margin_top = 332.0 +margin_right = 95.0 +margin_bottom = 494.0 focus_mode = 0 custom_fonts/font = ExtResource( 6 ) enabled_focus_mode = 0 @@ -114,141 +119,69 @@ margin_bottom = 332.0 rect_min_size = Vector2( 400, 200 ) size_flags_horizontal = 4 -[node name="place" type="LineEdit" parent="stage/controls" index="3"] +[node name="place" parent="stage/controls" index="3" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 336.0 margin_right = 1080.0 margin_bottom = 398.0 -placeholder_text = "Local" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/place"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="anesthesia" type="LineEdit" parent="stage/controls" index="4"] +[node name="anesthesia" parent="stage/controls" index="4" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 402.0 margin_right = 1080.0 margin_bottom = 464.0 -placeholder_text = "Anestesia" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/anesthesia"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="first_assistant" type="LineEdit" parent="stage/controls" index="5"] +[node name="first_assistant" parent="stage/controls" index="5" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 468.0 margin_right = 1080.0 margin_bottom = 530.0 -placeholder_text = "1º Ajudante" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/first_assistant"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="type" type="LineEdit" parent="stage/controls" index="6"] +[node name="type" parent="stage/controls" index="6" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 534.0 margin_right = 1080.0 margin_bottom = 596.0 -placeholder_text = "Tipo" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/type"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="sub_type" type="LineEdit" parent="stage/controls" index="7"] +[node name="sub_type" parent="stage/controls" index="7" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 600.0 margin_right = 1080.0 margin_bottom = 662.0 -placeholder_text = "Subtipo" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/sub_type"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="sub_sub_type" type="LineEdit" parent="stage/controls" index="8"] +[node name="sub_sub_type" parent="stage/controls" index="8" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 666.0 margin_right = 1080.0 margin_bottom = 728.0 -placeholder_text = "Sub-Subtipo" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/sub_sub_type"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="pathology" type="LineEdit" parent="stage/controls" index="9"] +[node name="pathology" parent="stage/controls" index="9" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 732.0 margin_right = 1080.0 margin_bottom = 794.0 -placeholder_text = "Patologia" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/pathology"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) -[node name="intervention" type="LineEdit" parent="stage/controls" index="10"] +[node name="intervention" parent="stage/controls" index="10" instance=ExtResource( 7 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 798.0 margin_right = 1080.0 margin_bottom = 860.0 -placeholder_text = "Intervenção" -caret_blink = true -caret_blink_speed = 0.5 - -[node name="option_set" type="Button" parent="stage/controls/intervention"] -anchor_left = 0.88 -anchor_right = 1.0 -anchor_bottom = 1.0 -text = "▽" -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 0, 62 ) [node name="is_urgency" type="CheckBox" parent="stage/controls" index="11"] margin_top = 864.0 diff --git a/option_set/option_set.gd b/option_set/option_set.gd new file mode 100644 index 0000000..e9cac3f --- /dev/null +++ b/option_set/option_set.gd @@ -0,0 +1,15 @@ +extends Control +class_name OptionSet + +var text: String setget set_text, get_text + +func set_text(var value: String): + input.text = value + +func get_text() -> String: + return input.text + + +onready var input := get_node("input") as LineEdit + + diff --git a/option_set/option_set.tscn b/option_set/option_set.tscn new file mode 100644 index 0000000..fc2aff5 --- /dev/null +++ b/option_set/option_set.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://option_set/option_set.gd" type="Script" id=1] + +[node name="option_set" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="input" type="LineEdit" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -100.0 +size_flags_horizontal = 3 +placeholder_text = "option set placeholder" +caret_blink = true +caret_blink_speed = 0.5 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="options" type="Button" parent="."] +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -100.0 +grow_horizontal = 0 +text = "▽" +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/project.godot b/project.godot index 9067744..aed55ea 100644 --- a/project.godot +++ b/project.godot @@ -25,6 +25,11 @@ _global_script_classes=[ { "path": "res://date_picker/date_picker.gd" }, { "base": "Control", +"class": "OptionSet", +"language": "GDScript", +"path": "res://option_set/option_set.gd" +}, { +"base": "Control", "class": "PointerInputSensor", "language": "GDScript", "path": "res://pointer_input_sensor.gd" @@ -53,6 +58,7 @@ _global_script_class_icons={ "Database": "", "DatabaseEntry": "", "DatePicker": "", +"OptionSet": "", "PointerInputSensor": "", "Stage": "", "TouchItemList": "", diff --git a/touch_vertical_container/touch_vertical_container.gd b/touch_vertical_container/touch_vertical_container.gd index f9c43e9..7c2ba84 100644 --- a/touch_vertical_container/touch_vertical_container.gd +++ b/touch_vertical_container/touch_vertical_container.gd @@ -27,8 +27,8 @@ func _ready(): sensor.connect("on_end_drag", self, "pointer_input_on_end_drag_handler") sensor.connect("on_click", self, "pointer_input_on_click_handler") - it.connect("focus_entered", sensor, "set_visible", [false]) - it.connect("focus_exited", sensor, "set_visible", [true]) +# it.connect("focus_entered", sensor, "set_visible", [false]) +# it.connect("focus_exited", sensor, "set_visible", [true]) func _process(delta: float): @@ -54,6 +54,33 @@ func pointer_input_on_end_drag_handler(pointer: PointerInputSensor.PointerInputD func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): - pointer.target.get_parent().grab_focus() - + propagate_click(pointer.target.get_parent(), pointer) + + +# @DAM Maybe replace this with a stack of next items to process approach. +func propagate_click(control: Control, pointer: PointerInputSensor.PointerInputData) -> bool: + if control is PointerInputSensor || control.mouse_filter == MOUSE_FILTER_IGNORE || control.visible == false: + return false + var click_processed := false + if control.get_global_rect().has_point(pointer.current_position): + var children = control.get_children() + children.invert() # @DAM Use inverted index for loop to avoid invert() operation. + for child in children: + if child is Control: + click_processed = click_processed || propagate_click(child, pointer) + if click_processed == true: + break + + if click_processed == false: + if control is CheckBox || control is CheckButton: + control.pressed = !control.pressed + control.grab_focus() + control.emit_signal("button_down") + control.emit_signal("pressed") + control.emit_signal("button_up") + click_processed = true + pointer.target.visible = false + control.connect("focus_exited", pointer.target, "set_visible", [true]) + + return click_processed -- cgit v1.2.3 From 283c0f2d84420bd02550dd4404b306d427fd58af Mon Sep 17 00:00:00 2001 From: dam Date: Fri, 18 Feb 2022 01:34:43 +0000 Subject: Implemented custom option set control. Fixed option sets text input zone being hidden below the button. --- logic/popup_list.gd | 1 + logic/stage.gd | 31 ++-------- main.tscn | 3 + option_set/option_set.gd | 23 ++++++- option_set/option_set.tscn | 3 +- project.godot | 6 ++ readme.md | 5 +- test_input.gd | 42 ------------- test_input.tscn | 58 ------------------ .../touch_vertical_container.gd | 71 ++++++++++++---------- 10 files changed, 82 insertions(+), 161 deletions(-) delete mode 100644 test_input.gd delete mode 100644 test_input.tscn (limited to 'project.godot') diff --git a/logic/popup_list.gd b/logic/popup_list.gd index 43bf2a1..7e049fb 100644 --- a/logic/popup_list.gd +++ b/logic/popup_list.gd @@ -1,4 +1,5 @@ extends Popup +class_name PopupList signal item_selected diff --git a/logic/stage.gd b/logic/stage.gd index 3cc5943..892dee4 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -49,11 +49,9 @@ func _ready(): save_button.connect("pressed", self, "save_action") discard_button.connect("pressed", self, "discard_action") - # @DAM Not working because we changed the stage/controls/.. estructure with the new option_sets. - # @DAM We could try to do a recursive approach or, build a stack of next items to process. for it in get_node("controls").get_children(): if it is LineEdit: - it.connect("focus_entered", it, "set_cursor_position", [99999999]) # @DAM Use MAX_INT + it.connect("focus_entered", it, "set", ["caret_position", it.max_length]) it.connect("focus_exited", it, "deselect") # Map option sets buttons. @@ -68,16 +66,12 @@ func _ready(): "intervention": intervention } for key in option_sets_map: -# var button := option_sets_map[key].get_node("option_set") as Button -# button.connect("pressed", self, "show_option_sets", [key]) - -# if key != "place": # @DAM DEBUG -# continue - var button := option_sets_map[key].get_node("options") as Button - button.connect("pressed", self, "show_option_sets", [key]) + var button := option_sets_map[key].get_node("options") as Button # @DAM Maybe rename "options". Also requires rename on option_set. + button.connect("pressed", self, "show_options", [key]) -func get_option_sets(field: String): +func show_options(field: String): + var option_set_field := self[field] as OptionSet var options: Array match field: @@ -92,20 +86,7 @@ func get_option_sets(field: String): options.append(OPTION_SETS_NOT_AVAILABLE) options.sort() - return options - - -# @DAM WIP I suspect that these should go inside the option_set class... -func show_option_sets(field: String): - var stage_options = get_node("/root/main/popup_list") as Popup - stage_options.connect("item_selected", self, "option_set_selected", [field], CONNECT_ONESHOT) - stage_options.popup_options(get_option_sets(field)) - - -func option_set_selected(index: int, field: String): - var field_input: LineEdit = self[field].get_node("input") - field_input.text = get_option_sets(field)[index] - field_input.caret_position = field_input.text.length() + option_set_field.show_options(options) func save_action(): diff --git a/main.tscn b/main.tscn index db7c7f7..5122f4c 100644 --- a/main.tscn +++ b/main.tscn @@ -97,6 +97,7 @@ script = ExtResource( 9 ) [node name="process_id" type="LineEdit" parent="stage/controls" index="0"] margin_right = 1080.0 margin_bottom = 62.0 +max_length = 32 placeholder_text = "Nº Processo" caret_blink = true caret_blink_speed = 0.5 @@ -105,6 +106,7 @@ caret_blink_speed = 0.5 margin_top = 66.0 margin_right = 1080.0 margin_bottom = 128.0 +max_length = 32 placeholder_text = "Nº Cirurgia" caret_blink = true caret_blink_speed = 0.5 @@ -193,6 +195,7 @@ text = "Urgência" margin_top = 928.0 margin_right = 1080.0 margin_bottom = 990.0 +max_length = 4096 placeholder_text = "Notas" caret_blink = true caret_blink_speed = 0.5 diff --git a/option_set/option_set.gd b/option_set/option_set.gd index e9cac3f..62d10d0 100644 --- a/option_set/option_set.gd +++ b/option_set/option_set.gd @@ -1,6 +1,7 @@ extends Control class_name OptionSet +var options: Array var text: String setget set_text, get_text func set_text(var value: String): @@ -9,7 +10,27 @@ func set_text(var value: String): func get_text() -> String: return input.text +onready var input := get_node("input") as LineEdit +onready var button := get_node("options") as Button # @DAM Maybe rename this. Also requires renaming on stage. +onready var popup := get_node("/root/main/popup_list") as PopupList -onready var input := get_node("input") as LineEdit +func _ready(): + assert(popup != null, "OptionSet failed to get 'popup' node.") + + input.connect("focus_entered", input, "set", ["caret_position", input.max_length]) + input.connect("focus_exited", input, "deselect") + + +func show_options(options_array: Array): + options = options_array + popup.connect("item_selected", self, "option_selected", [], CONNECT_ONESHOT) + popup.popup_options(options) + + +func option_selected(index: int): + if index >= 0 && index < options.size(): + input.text = options[index] + input.caret_position = input.max_length + button.release_focus() diff --git a/option_set/option_set.tscn b/option_set/option_set.tscn index fc2aff5..bf15806 100644 --- a/option_set/option_set.tscn +++ b/option_set/option_set.tscn @@ -15,7 +15,8 @@ anchor_right = 1.0 anchor_bottom = 1.0 margin_right = -100.0 size_flags_horizontal = 3 -placeholder_text = "option set placeholder" +text = "placeholder" +max_length = 4096 caret_blink = true caret_blink_speed = 0.5 __meta__ = { diff --git a/project.godot b/project.godot index aed55ea..b414dff 100644 --- a/project.godot +++ b/project.godot @@ -34,6 +34,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://pointer_input_sensor.gd" }, { +"base": "Popup", +"class": "PopupList", +"language": "GDScript", +"path": "res://logic/popup_list.gd" +}, { "base": "TouchVerticalContainer", "class": "Stage", "language": "GDScript", @@ -60,6 +65,7 @@ _global_script_class_icons={ "DatePicker": "", "OptionSet": "", "PointerInputSensor": "", +"PopupList": "", "Stage": "", "TouchItemList": "", "TouchVerticalContainer": "", diff --git a/readme.md b/readme.md index 795d37c..2437056 100644 --- a/readme.md +++ b/readme.md @@ -42,9 +42,9 @@ Surgery Log else: has_permissions = true ``` -- [ ] Fix the show option sets buttons; they are drawn over the input fields and hide inserted text; +- [x] Fix the show option sets buttons; they are drawn over the input fields and hide inserted text; +- [ ] Allow to parse option sets from database file; - [ ] Database menu and action buttons are not nice; Improve appearance; -- [ ] Show title of database (Log/Historico) and stage (New entry/Novo registo); - [ ] check if import_option_sets, store_option_sets, store_database require the parameter save_changes; this requires changes on databse, stage and menu scripts; - [ ] fix back button: - on stage screen should show pop-up asking it changes are to be discarded; @@ -52,7 +52,6 @@ Surgery Log - on about screen should close it; - on auto-fill pop-up, should close it; - on database screen, should deselect selected item, otherwise should quit the app; -- [ ] Add title to current window (on top, left of the menu); - [ ] Improve menu appearance; - [ ] Setup two themes: - [ ] theme_light diff --git a/test_input.gd b/test_input.gd deleted file mode 100644 index bae409d..0000000 --- a/test_input.gd +++ /dev/null @@ -1,42 +0,0 @@ -extends ColorRect - -onready var debug: RichTextLabel = get_node("/root/main/debug") - - -func _gui_input(event): -# if name == "a": -# accept_event() -# if name == "b" : #&& (event is InputEventScreenTouch): -# if name == "b": -# get_tree().set_input_as_handled() -# accept_event() -# if name == "b" && event is InputEventScreenTouch && event.is_pressed() == false: -# simulate_click() -# call_deferred("simulate_click") - - if event is InputEventScreenTouch || event is InputEventMouseButton: - debug.text += "%s> %-24s\t:\t%s\n" % [name, event.get_class(), event.is_pressed()] - else: - debug.text += "%s> %s\n" % [name, event.get_class()] - - -func simulate_click(): - var event_touch = InputEventScreenTouch.new() - event_touch.index = 0 - event_touch.position = self.get_global_mouse_position() - - var event_mouse = InputEventMouseButton.new() - event_mouse.button_index = BUTTON_LEFT - event_mouse.button_mask = BUTTON_MASK_LEFT - event_mouse.position = self.get_global_mouse_position() - - self.mouse_filter = Control.MOUSE_FILTER_IGNORE - event_mouse.pressed = true - event_touch.pressed = true -# Input.parse_input_event(event_mouse) - Input.parse_input_event(event_touch) - event_mouse.pressed = false - event_touch.pressed = false -# Input.parse_input_event(event_mouse) - Input.parse_input_event(event_touch) - self.mouse_filter = Control.MOUSE_FILTER_STOP diff --git a/test_input.tscn b/test_input.tscn deleted file mode 100644 index 4b507fe..0000000 --- a/test_input.tscn +++ /dev/null @@ -1,58 +0,0 @@ -[gd_scene load_steps=3 format=2] - -[ext_resource path="res://test_input.gd" type="Script" id=1] -[ext_resource path="res://fonts/font_regular.tres" type="DynamicFont" id=2] - -[node name="main" type="Control"] -anchor_right = 1.0 -anchor_bottom = 1.0 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="debug" type="RichTextLabel" parent="."] -anchor_right = 1.0 -anchor_bottom = 1.0 -mouse_filter = 2 -custom_fonts/normal_font = ExtResource( 2 ) -scroll_following = true -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="a" type="ColorRect" parent="."] -anchor_right = 0.66 -anchor_bottom = 0.66 -color = Color( 1, 0, 0, 0.196078 ) -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="b" type="ColorRect" parent="a"] -anchor_left = 0.5 -anchor_right = 1.502 -anchor_bottom = 1.0 -mouse_filter = 1 -color = Color( 0, 1, 0, 0.196078 ) -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="c" type="ColorRect" parent="."] -anchor_top = 0.333 -anchor_right = 0.666 -anchor_bottom = 1.0 -color = Color( 0, 0, 1, 0.196078 ) -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="d" type="ColorRect" parent="c"] -anchor_left = 0.5 -anchor_right = 1.502 -anchor_bottom = 1.0 -color = Color( 1, 1, 1, 0.196078 ) -script = ExtResource( 1 ) diff --git a/touch_vertical_container/touch_vertical_container.gd b/touch_vertical_container/touch_vertical_container.gd index 7c2ba84..1a7236c 100644 --- a/touch_vertical_container/touch_vertical_container.gd +++ b/touch_vertical_container/touch_vertical_container.gd @@ -26,9 +26,6 @@ func _ready(): sensor.connect("on_drag", self, "pointer_input_on_drag_handler") sensor.connect("on_end_drag", self, "pointer_input_on_end_drag_handler") sensor.connect("on_click", self, "pointer_input_on_click_handler") - -# it.connect("focus_entered", sensor, "set_visible", [false]) -# it.connect("focus_exited", sensor, "set_visible", [true]) func _process(delta: float): @@ -54,33 +51,45 @@ func pointer_input_on_end_drag_handler(pointer: PointerInputSensor.PointerInputD func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): - propagate_click(pointer.target.get_parent(), pointer) - - -# @DAM Maybe replace this with a stack of next items to process approach. -func propagate_click(control: Control, pointer: PointerInputSensor.PointerInputData) -> bool: - if control is PointerInputSensor || control.mouse_filter == MOUSE_FILTER_IGNORE || control.visible == false: - return false - var click_processed := false - if control.get_global_rect().has_point(pointer.current_position): - var children = control.get_children() - children.invert() # @DAM Use inverted index for loop to avoid invert() operation. - for child in children: - if child is Control: - click_processed = click_processed || propagate_click(child, pointer) - if click_processed == true: - break - - if click_processed == false: - if control is CheckBox || control is CheckButton: - control.pressed = !control.pressed - control.grab_focus() - control.emit_signal("button_down") - control.emit_signal("pressed") - control.emit_signal("button_up") - click_processed = true - pointer.target.visible = false - control.connect("focus_exited", pointer.target, "set_visible", [true]) + # Get last leaf node. + var root := pointer.target.get_parent() as Control + var leaf := root as Node + while leaf.get_child_count() > 0: + leaf = leaf.get_child(leaf.get_child_count() - 1) - return click_processed + # Navigate backwards from leaf to root until we find a node accepting the input. + var tried_leaf_as_root := false + while leaf != root || tried_leaf_as_root == false: + tried_leaf_as_root = leaf == root # Allow a final iteration cycle when leaf reaches root. + var node := leaf + + if node is PointerInputSensor \ + || node is Control == false \ + || node.mouse_filter == MOUSE_FILTER_IGNORE \ + || node.visible == false \ + || node.get_global_rect().has_point(pointer.current_position) == false: + # Get next node to be processed. + var leaf_index_in_parent := leaf.get_position_in_parent() + var parent := leaf.get_parent() + if leaf_index_in_parent == 0: + leaf = parent + else: + leaf = parent.get_child(leaf_index_in_parent - 1) + # Drill down into the new tree branch. + while leaf.get_child_count() > 0: + leaf = leaf.get_child(leaf.get_child_count() - 1) + continue + + var control: Control = node + if control is CheckBox || control is CheckButton: + control.pressed = !control.pressed + + control.grab_focus() + control.emit_signal("button_down") + control.emit_signal("pressed") + control.emit_signal("button_up") + control.connect("focus_exited", pointer.target, "set_visible", [true], CONNECT_ONESHOT) + pointer.target.visible = false + break + -- cgit v1.2.3 From f6369eaee39abe3d360ba42278a5a2a1d166f5af Mon Sep 17 00:00:00 2001 From: dam Date: Sun, 27 Mar 2022 16:57:14 +0000 Subject: Implemented prototype of option set list component. --- date_picker/date_picker.tscn | 3 - logic/database.gd | 2 +- logic/popup.gd | 36 +++++ logic/popup_list.gd | 28 ---- main.gd | 6 + main.tscn | 28 ++-- option_set/option_set.gd | 39 +++-- option_set/option_set.tscn | 3 - option_set/option_set_list.gd | 293 ++++++++++++++++++++++------------- option_set/option_set_list.tscn | 1 + project.godot | 18 ++- touch_item_list/touch_item_list.gd | 1 + touch_item_list/touch_item_list.tscn | 3 - 13 files changed, 290 insertions(+), 171 deletions(-) create mode 100644 logic/popup.gd delete mode 100644 logic/popup_list.gd (limited to 'project.godot') diff --git a/date_picker/date_picker.tscn b/date_picker/date_picker.tscn index 54b2b82..8b082f2 100644 --- a/date_picker/date_picker.tscn +++ b/date_picker/date_picker.tscn @@ -7,9 +7,6 @@ anchor_right = 1.0 anchor_bottom = 1.0 script = ExtResource( 2 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="year" type="Control" parent="."] anchor_right = 0.333 diff --git a/logic/database.gd b/logic/database.gd index c4482f4..370a679 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -118,7 +118,7 @@ func save_stage(entry: Dictionary): next_selected_idx = staged_idx else: db.append(entry) - add_item(get_entry_view(entry)) + self.add_item(get_entry_view(entry)) next_selected_idx = db.size() - 1 select(next_selected_idx) diff --git a/logic/popup.gd b/logic/popup.gd new file mode 100644 index 0000000..1b1813a --- /dev/null +++ b/logic/popup.gd @@ -0,0 +1,36 @@ +extends Control +class_name ModalPopup + +var control : Control + + +func _init(): + anchor_right = 1.0 + anchor_bottom = 1.0 + +func popup_control(item: Control): + control = item + control.connect("visibility_changed", self, "closed") + var background = $background + control.anchor_left = background.anchor_left + control.anchor_top = background.anchor_top + control.anchor_right = background.anchor_right + control.anchor_bottom = background.anchor_bottom + control.margin_left = 20 + control.margin_top = 20 + control.margin_right = -20 + control.margin_bottom = -20 + add_child(control) + show() + control.show() +# self.visible = true + + +func closed(): + if control.visible == true: + return + control.disconnect("visibility_changed", self, "closed") + remove_child(control) + self.hide() + + diff --git a/logic/popup_list.gd b/logic/popup_list.gd deleted file mode 100644 index 7e049fb..0000000 --- a/logic/popup_list.gd +++ /dev/null @@ -1,28 +0,0 @@ -extends Popup -class_name PopupList - -signal item_selected - -onready var item_list := get_node("list") as TouchItemList -onready var blur := get_node("blur") as ColorRect - - -func _ready(): - item_list.connect("item_selected", self, "selected") - - -func popup_options(options: Array): - item_list.v_scroll_bar.value = 0.0 - item_list.clear() - for it in options: - item_list.add_item(it) - self.popup_centered_ratio(0.9) - blur.rect_global_position = Vector2.ZERO - blur.rect_size = get_viewport_rect().size - - -func selected(index: int): - self.hide() - emit_signal("item_selected", index) - - diff --git a/main.gd b/main.gd index 5a78ede..7962d52 100644 --- a/main.gd +++ b/main.gd @@ -34,6 +34,12 @@ func _process(delta: float): for it in controls_sensible_to_keyboard: it.margin_bottom = -keyboard_height + # ~1650 fps with database using ItemList + Engine.target_fps = 0 + OS.vsync_enabled = false + OS.set_window_title("%03d" % [Engine.get_frames_per_second()]) + return + if power_throttle_timeout > 0.0: power_throttle_timeout -= delta else: diff --git a/main.tscn b/main.tscn index ed59082..8e750d4 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=2] +[gd_scene load_steps=13 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] @@ -7,8 +7,9 @@ [ext_resource path="res://logic/database.gd" type="Script" id=5] [ext_resource path="res://fonts/font_icons.tres" type="DynamicFont" id=6] [ext_resource path="res://option_set/option_set.tscn" type="PackedScene" id=7] +[ext_resource path="res://option_set/option_set_list.gd" type="Script" id=8] [ext_resource path="res://logic/stage.gd" type="Script" id=9] -[ext_resource path="res://logic/popup_list.gd" type="Script" id=10] +[ext_resource path="res://logic/popup.gd" type="Script" id=10] [ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] [ext_resource path="res://touch_vertical_container/touch_vertical_container.tscn" type="PackedScene" id=12] @@ -17,9 +18,6 @@ anchor_right = 1.0 anchor_bottom = 1.0 theme = ExtResource( 3 ) script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="database" parent="." instance=ExtResource( 11 )] script = ExtResource( 5 ) @@ -246,19 +244,23 @@ window_title = "CONFIRM ACTION" dialog_text = "Do you confirm this action?" dialog_autowrap = true -[node name="popup_list" type="Popup" parent="."] +[node name="popup" type="ColorRect" parent="."] +visible = false anchor_right = 1.0 anchor_bottom = 1.0 -popup_exclusive = true +color = Color( 0, 0, 0, 0.501961 ) script = ExtResource( 10 ) -[node name="blur" type="ColorRect" parent="popup_list"] -show_behind_parent = true -anchor_right = 1.0 -anchor_bottom = 1.0 -color = Color( 0, 0, 0, 0.75 ) +[node name="background" type="Panel" parent="popup"] +anchor_left = 0.05 +anchor_top = 0.025 +anchor_right = 0.95 +anchor_bottom = 0.975 -[node name="list" parent="popup_list" instance=ExtResource( 11 )] +[node name="option_set_list" type="Control" parent="."] +visible = false +rect_clip_content = true +script = ExtResource( 8 ) [node name="debug" type="Label" parent="."] visible = false diff --git a/option_set/option_set.gd b/option_set/option_set.gd index 62d10d0..040566a 100644 --- a/option_set/option_set.gd +++ b/option_set/option_set.gd @@ -1,7 +1,6 @@ extends Control class_name OptionSet -var options: Array var text: String setget set_text, get_text func set_text(var value: String): @@ -10,9 +9,12 @@ func set_text(var value: String): func get_text() -> String: return input.text +var selected_idx: int + onready var input := get_node("input") as LineEdit onready var button := get_node("options") as Button # @DAM Maybe rename this. Also requires renaming on stage. -onready var popup := get_node("/root/main/popup_list") as PopupList +onready var popup := get_node("/root/main/popup") as ModalPopup +onready var options := get_node("/root/main/option_set_list") as OptionSetList func _ready(): @@ -23,14 +25,31 @@ func _ready(): func show_options(options_array: Array): - options = options_array - popup.connect("item_selected", self, "option_selected", [], CONNECT_ONESHOT) - popup.popup_options(options) + options.clear_items() + var main = get_node("/root/main") + main.remove_child(options) + options.add_items(options_array) + if options_array[selected_idx] == input.text: + options.select(selected_idx) + else: + options.unselect() + options.connect("item_selected", self, "option_selected", [], CONNECT_ONESHOT) + popup.popup_control(options) +# popup.connect("item_selected", self, "option_selected", [], CONNECT_ONESHOT) +# popup.clear_items() +# popup_opt.visible = true +# get_node("/root/main/popup/blur") +# popup.add_items(options) + + +func option_selected(index: int, text: String): + selected_idx = index + input.text = text + input.caret_position = input.max_length + button.release_focus() + options.visible = false + var main = get_node("/root/main") + main.add_child(options) -func option_selected(index: int): - if index >= 0 && index < options.size(): - input.text = options[index] - input.caret_position = input.max_length - button.release_focus() diff --git a/option_set/option_set.tscn b/option_set/option_set.tscn index bf15806..8864e45 100644 --- a/option_set/option_set.tscn +++ b/option_set/option_set.tscn @@ -6,9 +6,6 @@ anchor_right = 1.0 anchor_bottom = 1.0 script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="input" type="LineEdit" parent="."] anchor_right = 1.0 diff --git a/option_set/option_set_list.gd b/option_set/option_set_list.gd index 3cff78d..cad9e9c 100644 --- a/option_set/option_set_list.gd +++ b/option_set/option_set_list.gd @@ -1,93 +1,115 @@ extends Control +class_name OptionSetList + +signal item_selected # (idx: int, text: String) +signal nothing_selected # () + +export var autowrap := true + +var vscrollbar : VScrollBar +var labels : Control +var labels_end_positions: Array +var labels_sizes : Array + +var items : Array +var selected_idx := -1 +var is_dirty := true + +var normal_style : StyleBoxFlat +var selected_style : StyleBoxFlat +var border_size := 5 + +onready var font : Font = get_font("font") -var vscrollbar: VScrollBar -var labels: Control -var labels_positions: Array -var labels_sizes: Array -var font: Font - -var items: Array = [ - "item 1", - "item 22", - "item 333", - "item 4444", - "item 55555", - "item 666666", - "item 7777777", - "item 88888888", - "item 999999999", - "This is the longest item of all, but eventually stops.", - "item 1", - "item 22", - "item 333", - "item 4444", - "item 55555", - "item 666666", - "item 7777777", - "item 88888888", - "item 999999999", - "This is the longest item of all, but eventually stops.", - "item 1", - "item 22", - "item 333", - "item 4444", - "item 55555", - "item 666666", - "item 7777777", - "item 88888888", - "item 999999999", - "This is the longest item of all, but eventually stops.", -] - -# @DAM List of ideas to implement on this element: -# - Allow to toggle word-wrap on or off; -# - Allow to change items; -# - Only build and process labels when needed; func _init(): + self.anchor_right = 1.0 + self.anchor_bottom = 1.0 + self.rect_clip_content = true + labels = Control.new() - labels.anchor_right = 1.0 - labels.anchor_bottom = 1.0 + labels.anchor_right = 1.0 + labels.anchor_bottom = 1.0 + labels.mouse_filter = Control.MOUSE_FILTER_IGNORE + labels.name = "labels" add_child(labels) vscrollbar = VScrollBar.new() vscrollbar.anchor_left = 1.0 vscrollbar.anchor_bottom = 1.0 - vscrollbar.grow_horizontal = Control.GROW_DIRECTION_BEGIN - vscrollbar.name = "vscrollbar" + vscrollbar.grow_horizontal = Control.GROW_DIRECTION_BEGIN + vscrollbar.name = "vscrollbar" add_child(vscrollbar) - font = get_font("font") - connect("resized", self, "build_labels") + normal_style = StyleBoxFlat.new() + normal_style.border_width_bottom = border_size + normal_style.border_color = Color.white * 0.333 + normal_style.bg_color = Color.transparent + + selected_style = StyleBoxFlat.new() + selected_style.border_width_bottom = border_size + selected_style.border_color = Color.white * 0.333 + selected_style.bg_color = Color.dimgray + + connect("resized", self, "mark_as_dirty") -# @DAM We connect build_labels to resized during init. This calls build_labels immediately and the -# labels.rect_size is still not properly set thus, making the max_required_labels to return an -# incorrect value. To patch this, we are calling build_labels again on the _ready. Maybe we can sort -# this out in a cleaner way? -func _ready(): - build_labels() +func mark_as_dirty(): + is_dirty = true +func add_item(text: String): + items.append(text) + is_dirty = true -# @DAM This is only used once so, why not inline it? -func max_required_labels() -> int: - var max_labels := ceil(labels.rect_size.y / get_line_height()) + 1 - return int(min(items.size(), max_labels)) +func add_items(texts: Array): + items.append_array(texts) + is_dirty = true -func get_line_height() -> float: - return font.get_height() + font.get_descent() +func set_item(index: int, text: String): + items[index] = text + is_dirty = true + + +func set_items(indices: Array, texts: Array): + for idx in indices.size(): + items[indices[idx]] = texts[idx] + is_dirty = true + + +func remove_item(index: int): + items.remove(index) + is_dirty = true -func build_labels(): - var new_max_required_labels := max_required_labels() - var delta := new_max_required_labels - labels.get_child_count() +func remove_items(indices: Array): + indices.sort() + var idx := indices.size()-1 + while idx >= 0: + items.remove(indices[idx]) + idx -= 1 + is_dirty = true + + +func clear_items(): + items.clear() + is_dirty = true + + +func build_labels(): + + var num_of_labels := int(min( + items.size(), + ceil(labels.rect_size.y / (font.get_height() + border_size)) + 1 + )) + + var delta := num_of_labels - labels.get_child_count() + while delta > 0: var label := Label.new() - label.autowrap = true - label.anchor_left = 0.0 + label.autowrap = autowrap label.anchor_right = 1.0 label.valign = Label.VALIGN_TOP labels.add_child(label) @@ -98,61 +120,124 @@ func build_labels(): labels.remove_child(label) label.free() delta += 1 - - -func process_labels(): - labels_positions.clear() + + labels_end_positions.clear() labels_sizes.clear() - var position := 0.0 - var limit := labels.rect_size.x + + if num_of_labels == 0: + return + + var position := 0.0 + var proto_label := labels.get_child(0) as Label + var line_spacing := proto_label.get_constant("line_spacing") + var line_height := proto_label.get_line_height() for it in items: - var size := font.get_wordwrap_string_size(it, limit).y + proto_label.text = it + var line_count := proto_label.get_line_count() + var height := line_count * line_height + (line_count - 1) * line_spacing + border_size - # The get_wordwrap_string_size does not include the vertical spacing for the last line, thus - # we need to include it manually. - # Method 1 -# var lines = size / font.get_height() -# var height = size + font.get_descent() * lines - # Method 2 - var height = get_line_height() * ceil(size / get_line_height()) - # Method 3 - not correct -# var height = size + font.get_descent() - position += height - labels_positions.append(position) + labels_end_positions.append(position) labels_sizes.append(height) func _process(delta): - # @DAM We are recalculating the labels size and position on every update. - # This only has to be done on resize or when items change. - process_labels() + if is_dirty: + build_labels() + is_dirty = false + + var ratio := 1.0 + + if items.size() > 0: + ratio = vscrollbar.max_value / float(labels_end_positions.back()) vscrollbar.min_value = 0 - vscrollbar.max_value = rect_size.y - var ratio := rect_size.y / float(labels_positions[labels_positions.size()-1]) + vscrollbar.max_value = labels.rect_size.y vscrollbar.visible = ratio < 1.0 vscrollbar.page = ratio * (vscrollbar.max_value - vscrollbar.min_value) - var offset := vscrollbar.value - var bs_value := offset / ratio - var offset_idx := labels_positions.bsearch(bs_value) - - var wasted := 0 # @DAM To be removed. - var idx := 0 + var scrollbar_offset := vscrollbar.value + var labels_offset := scrollbar_offset / ratio + var idx_offset := labels_end_positions.bsearch(labels_offset) + + var idx := idx_offset for label in labels.get_children(): - if idx + offset_idx >= items.size(): - label.text = "" - wasted += 1 + + if idx >= items.size(): + label.visible = false continue -# break # @DAM Or should we use continue? - label.text = items[idx + offset_idx] - label.rect_position.y = labels_positions[idx + offset_idx] - labels_sizes[idx + offset_idx] - bs_value + + label.visible = true + label.text = items[idx] + label.rect_size.y = labels_sizes[idx] + label.rect_position.y = labels_end_positions[idx] - labels_sizes[idx] - labels_offset + + if idx == selected_idx: + label.add_stylebox_override("normal", selected_style) + else: + label.add_stylebox_override("normal", normal_style) + idx += 1 - if Engine.get_idle_frames() % 30 == 1: - print_debug("Wasted: %s" % wasted) - labels.margin_right = -vscrollbar.rect_size.x if vscrollbar.visible else 0.0 + +func get_item_at_position(mouse_position: Vector2) -> int: + if items.size() == 0: + return -1 + + var ratio := 1.0 + + if items.size() > 0: + ratio = vscrollbar.max_value / float(labels_end_positions.back()) + + var scrollbar_offset := vscrollbar.value + var labels_offset := scrollbar_offset / ratio + var position := mouse_position.y + labels_offset + var item_idx := labels_end_positions.bsearch(position) + + return int(min(item_idx, items.size()-1)) # Return last item when position is below it. + + +func select(index: int): + selected_idx = index + emit_signal("item_selected", selected_idx, items[selected_idx]) + + +func unselect(): + selected_idx = -1 + emit_signal("nothing_selected") + + +#func _input(event: InputEvent): +## @DAM Test and debug code. Delete when ready. +# if event is InputEventKey: +# if event.pressed && event.scancode == KEY_C: +# clear_items() +# if event.pressed && event.scancode == KEY_F: +# for idx in range(1, 26): +# if idx % 10 == 0: +# add_item("-- item %06d : This is the longest item of all, but eventually stops. --" % idx) +# else: +# add_item("-- item %06d --" % idx) + + +func _gui_input(event: InputEvent): + + # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. + if event is InputEventScreenTouch || event is InputEventScreenDrag: + if event.index != 0: + return + + if event is InputEventMouseButton == false: + return + + if event is InputEventScreenTouch && event.pressed == false: + return + + var item_idx := get_item_at_position(get_local_mouse_position()) + if item_idx >= 0 && item_idx < items.size(): + select(item_idx) + + diff --git a/option_set/option_set_list.tscn b/option_set/option_set_list.tscn index f8361fa..d336961 100644 --- a/option_set/option_set_list.tscn +++ b/option_set/option_set_list.tscn @@ -5,4 +5,5 @@ [node name="option_set_list" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 +rect_clip_content = true script = ExtResource( 1 ) diff --git a/project.godot b/project.godot index b414dff..4a59943 100644 --- a/project.godot +++ b/project.godot @@ -25,19 +25,24 @@ _global_script_classes=[ { "path": "res://date_picker/date_picker.gd" }, { "base": "Control", +"class": "ModalPopup", +"language": "GDScript", +"path": "res://logic/popup.gd" +}, { +"base": "Control", "class": "OptionSet", "language": "GDScript", "path": "res://option_set/option_set.gd" }, { "base": "Control", -"class": "PointerInputSensor", +"class": "OptionSetList", "language": "GDScript", -"path": "res://pointer_input_sensor.gd" +"path": "res://option_set/option_set_list.gd" }, { -"base": "Popup", -"class": "PopupList", +"base": "Control", +"class": "PointerInputSensor", "language": "GDScript", -"path": "res://logic/popup_list.gd" +"path": "res://pointer_input_sensor.gd" }, { "base": "TouchVerticalContainer", "class": "Stage", @@ -63,9 +68,10 @@ _global_script_class_icons={ "Database": "", "DatabaseEntry": "", "DatePicker": "", +"ModalPopup": "", "OptionSet": "", +"OptionSetList": "", "PointerInputSensor": "", -"PopupList": "", "Stage": "", "TouchItemList": "", "TouchVerticalContainer": "", diff --git a/touch_item_list/touch_item_list.gd b/touch_item_list/touch_item_list.gd index 67f88d7..82f94f2 100644 --- a/touch_item_list/touch_item_list.gd +++ b/touch_item_list/touch_item_list.gd @@ -1,4 +1,5 @@ extends ItemList +#extends OptionSetList class_name TouchItemList const POINTER_VELOCITY_DECAYING_FACTOR: float = PI diff --git a/touch_item_list/touch_item_list.tscn b/touch_item_list/touch_item_list.tscn index 072f5b8..31fed01 100644 --- a/touch_item_list/touch_item_list.tscn +++ b/touch_item_list/touch_item_list.tscn @@ -8,9 +8,6 @@ anchor_right = 1.0 anchor_bottom = 1.0 mouse_filter = 2 script = ExtResource( 2 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="sensor" type="Control" parent="."] anchor_right = 1.0 -- cgit v1.2.3 From 9b619b8c5f117e53b121c2d868b024c7c7d08f4c Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 31 Mar 2022 16:05:54 +0000 Subject: Fixed signals on popup and modal_dialog to make those usable. --- dialog/dialog.gd | 77 +++++++++++++++++++++++++++++++++++++++++++ file_picker.gd | 18 ++++++++++ logic/database.gd | 10 +++--- logic/popup.gd | 36 ++++++++++++++------ logic/stage.gd | 11 ++++--- main.gd | 10 ------ main.tscn | 25 +++++++------- menu/menu.gd | 33 ++++++++++--------- option_set/option_set.gd | 4 --- option_set/option_set_list.gd | 26 +++++++++++---- project.godot | 6 ++++ readme.md | 7 ++-- theme_dark.tres | 6 ++++ theme_white.tres | 6 ---- 14 files changed, 200 insertions(+), 75 deletions(-) create mode 100644 dialog/dialog.gd create mode 100644 file_picker.gd create mode 100644 theme_dark.tres delete mode 100644 theme_white.tres (limited to 'project.godot') diff --git a/dialog/dialog.gd b/dialog/dialog.gd new file mode 100644 index 0000000..bfdbab5 --- /dev/null +++ b/dialog/dialog.gd @@ -0,0 +1,77 @@ +extends Control +class_name Dialog + +signal answered # (accepted: bool) +signal accepted # () +signal rejected # () + +export var clear_signals_on_hide := true + +var message : Label +var accept : Button +var reject : Button + + +func _init(): + self.anchor_right = 1.0 + self.anchor_bottom = 1.0 + self.rect_clip_content = true + self.connect("hide", self, "_clear_signals") + + reject = Button.new() + reject.text = "reject" + reject.anchor_top = 1.0 + reject.anchor_left = 0.0 + reject.anchor_right = 0.5 + reject.grow_vertical = Control.GROW_DIRECTION_BEGIN + reject.name = "reject" + reject.connect("pressed", self, "_signal_rejected") + add_child(reject) + + accept = Button.new() + accept.text = "accept" + accept.anchor_top = 1.0 + accept.anchor_left = 0.5 + accept.anchor_right = 1.0 + accept.grow_vertical = Control.GROW_DIRECTION_BEGIN + accept.name = "accept" + accept.connect("pressed", self, "_signal_accepted") + add_child(accept) + + message = Label.new() + message.autowrap = true + message.align = Label.ALIGN_CENTER + message.anchor_right = 1.0 + message.anchor_bottom = 1.0 + add_child(message) + + +func _clear_signals(): + if clear_signals_on_hide == false: + return + + for signal_name in ["answered", "accepted", "rejected"]: + for it in get_signal_connection_list(signal_name): + disconnect(it.signal, it.target, it.method) + + +func _signal_rejected(): + emit_signal("rejected") + emit_signal("answered", false) + hide() + + +func _signal_accepted(): + emit_signal("accepted") + emit_signal("answered", true) + hide() + + +func setup(message: String, accept_label: String = "Accept", reject_label: String = "Reject"): + self.message.text = message + accept.visible = accept_label != "" + accept.text = accept_label + reject.visible = reject_label != "" + reject.text = reject_label + + diff --git a/file_picker.gd b/file_picker.gd new file mode 100644 index 0000000..9715d0d --- /dev/null +++ b/file_picker.gd @@ -0,0 +1,18 @@ +extends FileDialog + +export var clear_signals_on_hide := true + + +func _init(): + self.connect("hide", self, "_clear_signals") + + +func _clear_signals(): + if clear_signals_on_hide == false: + return + + for signal_name in ["file_selected"]: + for it in get_signal_connection_list(signal_name): + disconnect(it.signal, it.target, it.method) + + diff --git a/logic/database.gd b/logic/database.gd index 5694dcc..b952356 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -8,12 +8,12 @@ var db: Array var selected_idx: int var staged_idx: int -onready var confirm_action := get_node("/root/main/confirm_action") as ConfirmationDialog onready var stage := get_node("/root/main/stage") as Stage onready var delete_button := get_node("actions/delete") as Button onready var edit_button := get_node("actions/edit") as Button onready var add_button := get_node("actions/add") as Button - +onready var popup := get_node("/root/main/popup") as ModalPopup +onready var dialog := get_node("/root/main/dialog") as Dialog func _init(): selected_idx = -1 @@ -75,9 +75,9 @@ func delete_action(): if selected_idx < 0: return - confirm_action.dialog_text = "Do you want to delete entry with process ID '%s' from the database?" % db[selected_idx].process_id - confirm_action.connect("confirmed", self, "delete_action_confirmed", [], CONNECT_ONESHOT) - confirm_action.show_modal(true) + dialog.setup("Do you want to delete entry with process ID '%s' from the database?" % db[selected_idx].process_id, "Yes, delete", "No") + dialog.connect("accepted", self, "delete_action_confirmed") + popup.open_popup("Delete entry?", dialog) func delete_action_confirmed(): diff --git a/logic/popup.gd b/logic/popup.gd index 2ff91fe..31897c7 100644 --- a/logic/popup.gd +++ b/logic/popup.gd @@ -3,20 +3,39 @@ class_name ModalPopup signal dismissed # () +export var clear_signals_on_hide := true + var control : Control var control_parent : Node onready var title := get_node("title") as Label onready var background := get_node("background") as Panel +onready var dismiss := get_node("dismiss") as Button func _init(): - anchor_right = 1.0 - anchor_bottom = 1.0 + self.anchor_right = 1.0 + self.anchor_bottom = 1.0 + self.rect_clip_content = true + self.connect("hide", self, "_clear_signals") func _ready(): - get_node("dismiss").connect("pressed", self, "dismiss") + dismiss.connect("pressed", self, "_dismiss") + + +func _clear_signals(): + if clear_signals_on_hide == false: + return + + for signal_name in ["dismissed"]: + for it in get_signal_connection_list(signal_name): + disconnect(it.signal, it.target, it.method) + + +func _dismiss(): + emit_signal("dismissed") + close_popup() func open_popup(title: String, item: Control): @@ -26,6 +45,7 @@ func open_popup(title: String, item: Control): self.title.text = title control = item + control.connect("hide", self, "close_popup") control_parent = control.get_parent() control_parent.remove_child(control) self.add_child(control) @@ -38,23 +58,19 @@ func open_popup(title: String, item: Control): control.margin_top = 20 control.margin_right = -20 control.margin_bottom = -20 - add_child(control) self.show() control.show() -func dismiss(): - emit_signal("dismissed") - - func close_popup(): if visible == false: return - self.hide() + + control.disconnect("hide", self, "close_popup") control.hide() + self.hide() remove_child(control) control_parent.add_child(control) control_parent = null - diff --git a/logic/stage.gd b/logic/stage.gd index bf311b9..fde67d3 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -23,7 +23,7 @@ const OPTION_SETS_TREE_STRUCTURE := { var staged_entry_hash: int var option_sets: Dictionary -onready var confirm_action := get_node("/root/main/confirm_action") as ConfirmationDialog + onready var process_id := get_node("controls/process_id") as LineEdit onready var surgery_id := get_node("controls/surgery_id") as LineEdit onready var date := get_node("controls/date_picker") as DatePicker @@ -40,7 +40,8 @@ onready var notes := get_node("controls/notes") as LineEdit onready var save_button := get_node("controls/save") as Button onready var discard_button := get_node("controls/discard") as Button onready var scrollbar := get_v_scrollbar() - +onready var popup := get_node("/root/main/popup") as ModalPopup +onready var dialog := get_node("/root/main/dialog") as Dialog func _init(): exclude_controls = ["date_picker", "save", "discard"] @@ -110,9 +111,9 @@ func save_action(): func discard_action(): if get_stage().hash() != staged_entry_hash: - confirm_action.dialog_text = "Do you want to discard the changes made?" - confirm_action.connect("confirmed", self, "discard_action_confirmed", [], CONNECT_ONESHOT) - confirm_action.show_modal(true) + dialog.setup("Do you want to discard the changes made?", "Yes, discard", "No") + dialog.connect("accepted", self, "discard_action_confirmed") + popup.open_popup("Discard changes?", dialog) else: discard_action_confirmed() diff --git a/main.gd b/main.gd index 6171409..5612e01 100644 --- a/main.gd +++ b/main.gd @@ -3,11 +3,9 @@ extends Control var power_throttle_timeout: float onready var file_picker := get_node("/root/main/file_picker") as FileDialog -onready var confirm_action := get_node("/root/main/confirm_action") as ConfirmationDialog onready var controls_sensible_to_keyboard := [ self, file_picker, - confirm_action, ] @@ -25,8 +23,6 @@ func _init(): func _ready(): Input.set_use_accumulated_input(false) - confirm_action.get_cancel().connect("pressed", self, "dialog_cancelled", ["confirmed"]) - file_picker.get_cancel().connect("pressed", self, "dialog_cancelled", ["file_selected"]) func _process(delta: float): @@ -50,9 +46,3 @@ func _unhandled_input(event: InputEvent): power_throttle_timeout = 3.5 -func dialog_cancelled(confirmation_signal_name: String): - var confirmation_handlers = confirm_action.get_signal_connection_list(confirmation_signal_name) - for it in confirmation_handlers: - confirm_action.disconnect(it.signal, it.target, it.method) - - diff --git a/main.tscn b/main.tscn index 83bcaf8..d388cb5 100644 --- a/main.tscn +++ b/main.tscn @@ -1,8 +1,8 @@ -[gd_scene load_steps=14 format=2] +[gd_scene load_steps=16 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] -[ext_resource path="res://theme_white.tres" type="Theme" id=3] +[ext_resource path="res://theme_dark.tres" type="Theme" id=3] [ext_resource path="res://menu/menu.gd" type="Script" id=4] [ext_resource path="res://logic/database.gd" type="Script" id=5] [ext_resource path="res://fonts/font_icons.tres" type="DynamicFont" id=6] @@ -13,6 +13,8 @@ [ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] [ext_resource path="res://touch_vertical_container/touch_vertical_container.tscn" type="PackedScene" id=12] [ext_resource path="res://fonts/font_mono_regular.tres" type="DynamicFont" id=13] +[ext_resource path="res://dialog/dialog.gd" type="Script" id=14] +[ext_resource path="res://file_picker.gd" type="Script" id=15] [node name="main" type="Control"] anchor_right = 1.0 @@ -240,19 +242,11 @@ filters = PoolStringArray( "*.*" ) show_hidden_files = true current_dir = "" current_path = "" +script = ExtResource( 15 ) __meta__ = { "_edit_use_anchors_": false } -[node name="confirm_action" type="ConfirmationDialog" parent="."] -anchor_right = 1.0 -anchor_bottom = 1.0 -size_flags_horizontal = 3 -size_flags_vertical = 3 -window_title = "" -dialog_text = "Do you confirm this action?" -dialog_autowrap = true - [node name="popup" type="ColorRect" parent="."] visible = false anchor_right = 1.0 @@ -290,7 +284,16 @@ flat = true [node name="option_set_list" type="Control" parent="."] visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 rect_clip_content = true script = ExtResource( 8 ) +[node name="dialog" type="Control" parent="."] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_clip_content = true +script = ExtResource( 14 ) + [editable path="stage"] diff --git a/menu/menu.gd b/menu/menu.gd index c963270..021c005 100644 --- a/menu/menu.gd +++ b/menu/menu.gd @@ -12,8 +12,9 @@ const menu_items: Array = [ const license_font_b612: String = "res://licenses/font_b612.txt" const license_godot: String = "res://licenses/godot.txt" -onready var popup := get_popup() as PopupMenu -onready var confirm_action := get_node("/root/main/confirm_action") as ConfirmationDialog +onready var menu := get_popup() as PopupMenu +onready var popup := get_node("/root/main/popup") as ModalPopup +onready var dialog := get_node("/root/main/dialog") as Dialog onready var file_picker := get_node("/root/main/file_picker") as FileDialog onready var database := get_node("/root/main/database") as Database onready var stage := get_node("/root/main/stage") as Stage @@ -21,8 +22,8 @@ onready var stage := get_node("/root/main/stage") as Stage func _ready(): for idx in range(menu_items.size()): - popup.add_item(menu_items[idx].label, idx) - popup.connect("id_pressed", self, "id_pressed") + menu.add_item(menu_items[idx].label, idx) + menu.connect("id_pressed", self, "id_pressed") func id_pressed(id: int): @@ -34,7 +35,7 @@ func import_option_sets_action(): file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) file_picker.filters = ["*.json", "*.csv"] file_picker.current_file = "" - file_picker.connect("file_selected", self, "import_option_sets_action_confirmed", [], CONNECT_ONESHOT) + file_picker.connect("file_selected", self, "import_option_sets_action_confirmed") file_picker.show_modal(true) file_picker.invalidate() @@ -68,9 +69,9 @@ func export_option_sets_action(): func clear_option_sets_action(): - confirm_action.dialog_text = "Do you want to delete all option sets?" - confirm_action.connect("confirmed", stage, "clear_option_sets", [], CONNECT_ONESHOT) - confirm_action.show_modal(true) + dialog.setup("Do you want to delete all option sets?", "Yes, delete.", "No") + dialog.connect("accepted", stage, "clear_option_sets") + popup.open_popup("Clear option sets?", dialog) func export_data_action(): @@ -84,20 +85,20 @@ func export_data_action(): func clear_data_action(): - confirm_action.dialog_text = "Do you want to delete all entries from the database?" - confirm_action.connect("confirmed", database, "clear_database", [], CONNECT_ONESHOT) - confirm_action.show_modal(true) + dialog.setup("Do you want to delete all entries from the database?", "Yes, delete.", "No") + dialog.connect("accepted", database, "clear_database") + popup.open_popup("Clear database?", dialog) func about_action(): - confirm_action.dialog_text = "Surgery Log\nversion 2022-02-27" - confirm_action.show_modal(true) + dialog.setup("Surgery Log\nversion 0.1", "", "") + popup.open_popup("About", dialog) # @DAM Hide this debug method before release. func test_fake_db_action(): - confirm_action.dialog_text = "Do you want to delete all entries from the database and replace by fake entries?" - confirm_action.connect("confirmed", database, "fake_database", [], CONNECT_ONESHOT) - confirm_action.show_modal(true) + dialog.setup("Do you want to delete all entries from the database and replace by fake entries?", "Yes, replace.", "No") + dialog.connect("accepted", database, "fake_database") + popup.open_popup("Fake DB?", dialog) diff --git a/option_set/option_set.gd b/option_set/option_set.gd index 637d033..0e8f90e 100644 --- a/option_set/option_set.gd +++ b/option_set/option_set.gd @@ -35,14 +35,10 @@ func show_options(options_array: Array): options.unselect() options.connect("item_selected", self, "popup_result", []) options.connect("nothing_selected", self, "popup_result", [-1, ""]) - popup.connect("dismissed", self, "popup_result", [selected_idx, input.text]) popup.open_popup(input.placeholder_text, options) func popup_result(index: int, text: String): - options.disconnect("item_selected", self, "popup_result") - options.disconnect("nothing_selected", self, "popup_result") - popup.disconnect("dismissed", self, "popup_result") selected_idx = index input.text = text input.caret_position = input.max_length diff --git a/option_set/option_set_list.gd b/option_set/option_set_list.gd index ea6b2d8..8aad1b1 100644 --- a/option_set/option_set_list.gd +++ b/option_set/option_set_list.gd @@ -5,6 +5,8 @@ const POINTER_VELOCITY_DECAYING_FACTOR: float = PI const POINTER_VELOCITY_BOOST_FACTOR: float = 1.25 const EXACT_SELECTION: bool = false +export var clear_signals_on_hide := true + signal item_selected # (idx: int, text: String) signal nothing_selected # () @@ -17,7 +19,7 @@ var pointer_drag_velocity := 0.0 var when_last_dragged := 0 var labels : Control -var labels_end_positions: Array +var labels_end_positions : Array var labels_sizes : Array var items : Array @@ -35,7 +37,8 @@ func _init(): self.anchor_right = 1.0 self.anchor_bottom = 1.0 self.rect_clip_content = true - + self.connect("hide", self, "_clear_signals") + labels = Control.new() labels.anchor_right = 1.0 labels.anchor_bottom = 1.0 @@ -219,6 +222,7 @@ func get_item_at_position(mouse_position: Vector2) -> int: var position := mouse_position.y + labels_offset var item_idx := labels_end_positions.bsearch(position) + # @DAM Fix this to return -1 if no item was selected. return int(min(item_idx, items.size()-1)) # Return last item when position is below it. @@ -227,6 +231,7 @@ func select(index: int): emit_signal("item_selected", selected_idx, items[selected_idx]) +# @DAM Do we really need this? We should have just one signal to the selection. func unselect(): selected_idx = -1 emit_signal("nothing_selected") @@ -256,10 +261,10 @@ func pointer_input_on_end_drag_handler(pointer: PointerInputSensor.PointerInputD func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): - var selected_idx := get_item_at_position(pointer.current_position - rect_global_position) - if selected_idx >= 0: - select(selected_idx) - emit_signal("item_selected", selected_idx) + var item_idx := get_item_at_position(pointer.current_position - rect_global_position) + if item_idx >= 0: + select(item_idx) + emit_signal("item_selected", item_idx) else: unselect() emit_signal("nothing_selected") @@ -269,3 +274,12 @@ func pointer_input_on_scroll_handler(pointer: PointerInputSensor.PointerInputDat pointer_drag_velocity -= pointer.scroll * POINTER_VELOCITY_BOOST_FACTOR * screen_dpcm +func _clear_signals(): + if clear_signals_on_hide == false: + return + + for signal_name in ["item_selected", "nothing_selected"]: + for it in get_signal_connection_list(signal_name): + disconnect(it.signal, it.target, it.method) + + diff --git a/project.godot b/project.godot index 4a59943..4a3e1ed 100644 --- a/project.godot +++ b/project.godot @@ -25,6 +25,11 @@ _global_script_classes=[ { "path": "res://date_picker/date_picker.gd" }, { "base": "Control", +"class": "Dialog", +"language": "GDScript", +"path": "res://dialog/dialog.gd" +}, { +"base": "Control", "class": "ModalPopup", "language": "GDScript", "path": "res://logic/popup.gd" @@ -68,6 +73,7 @@ _global_script_class_icons={ "Database": "", "DatabaseEntry": "", "DatePicker": "", +"Dialog": "", "ModalPopup": "", "OptionSet": "", "OptionSetList": "", diff --git a/readme.md b/readme.md index c32faf9..5d48eff 100644 --- a/readme.md +++ b/readme.md @@ -55,8 +55,11 @@ Surgery Log - [x] title; - [x] dismiss button; - [x] Hide dialogs title bar (appear in the top with 1 or 2 pixels height); -- [ ] Use popup to display confirmation messages; -- [ ] What to do when the optionset has no options available? +- [x] Fix automation to automatically disconnect acceptance signal handlers when reject is chosen on file_picker/confirm_action; +- [x] Use popup to display confirmation messages; +- [ ] Improve option sets: + - [ ] selecting outside optionset entry should select none + - [ ] if no options are available, show nothing instead of "--" - [ ] Fix back button: - on stage screen should show pop-up asking it changes are to be discarded; - on file-pickers screen should close them; diff --git a/theme_dark.tres b/theme_dark.tres new file mode 100644 index 0000000..832b226 --- /dev/null +++ b/theme_dark.tres @@ -0,0 +1,6 @@ +[gd_resource type="Theme" load_steps=2 format=2] + +[ext_resource path="res://fonts/font_regular.tres" type="DynamicFont" id=1] + +[resource] +default_font = ExtResource( 1 ) diff --git a/theme_white.tres b/theme_white.tres deleted file mode 100644 index 832b226..0000000 --- a/theme_white.tres +++ /dev/null @@ -1,6 +0,0 @@ -[gd_resource type="Theme" load_steps=2 format=2] - -[ext_resource path="res://fonts/font_regular.tres" type="DynamicFont" id=1] - -[resource] -default_font = ExtResource( 1 ) -- cgit v1.2.3 From 2e70e18f24a14f74c00850bfc88071d23ec66da9 Mon Sep 17 00:00:00 2001 From: dam Date: Tue, 5 Apr 2022 05:33:23 +0000 Subject: WIP creating theme and improving UI/UX. --- dialog/dialog.gd | 2 + fonts/entypo-fontello.ttf | Bin 6832 -> 6560 bytes fonts/font_icons.tres | 2 +- logic/database.gd | 14 ++--- logic/stage.gd | 5 +- main.tscn | 136 ++++++++++++++++++++++++--------------------- option_set/option_set.tscn | 2 +- project.godot | 1 + themes/dark.tres | 61 +++++++++++++++++++- 9 files changed, 147 insertions(+), 76 deletions(-) (limited to 'project.godot') diff --git a/dialog/dialog.gd b/dialog/dialog.gd index 1cf0e66..71981c7 100644 --- a/dialog/dialog.gd +++ b/dialog/dialog.gd @@ -22,6 +22,7 @@ func _init(): reject.anchor_top = 1.0 reject.anchor_left = 0.0 reject.anchor_right = 0.5 + reject.margin_right = -5.0 reject.grow_vertical = Control.GROW_DIRECTION_BEGIN reject.name = "reject" reject.connect("pressed", self, "_signal_rejected") @@ -31,6 +32,7 @@ func _init(): accept.anchor_top = 1.0 accept.anchor_left = 0.5 accept.anchor_right = 1.0 + accept.margin_left = 5.0 accept.grow_vertical = Control.GROW_DIRECTION_BEGIN accept.name = "accept" accept.connect("pressed", self, "_signal_accepted") diff --git a/fonts/entypo-fontello.ttf b/fonts/entypo-fontello.ttf index 0e95ba4..345bd55 100644 Binary files a/fonts/entypo-fontello.ttf and b/fonts/entypo-fontello.ttf differ diff --git a/fonts/font_icons.tres b/fonts/font_icons.tres index cc86d17..6bc9f3d 100644 --- a/fonts/font_icons.tres +++ b/fonts/font_icons.tres @@ -3,6 +3,6 @@ [ext_resource path="res://fonts/entypo-fontello.ttf" type="DynamicFontData" id=1] [resource] -size = 64 +size = 55 use_filter = true font_data = ExtResource( 1 ) diff --git a/logic/database.gd b/logic/database.gd index ea27ef2..262a18a 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -44,18 +44,18 @@ func get_entry_view(database_entry: Dictionary) -> String: func item_selected(index: int): selected_idx = index - fade_action_buttons(1.0) + set_buttons_active(true) func clear_selection(): selected_idx = -1 unselect_all() - fade_action_buttons(0.25) + set_buttons_active(false) -func fade_action_buttons(target_alpha: float): - get_node("actions/delete").modulate.a = target_alpha - get_node("actions/edit").modulate.a = target_alpha +func set_buttons_active(active: bool): + (get_node("actions/delete") as Button).disabled = !active + (get_node("actions/edit") as Button).disabled = !active func delete_action(): @@ -83,14 +83,14 @@ func edit_action(): self.visible = false stage.visible = true var staged := (db[staged_idx] as Dictionary).duplicate(true) - stage.set_stage(staged) + stage.set_stage(staged, "Entry #%d" % (staged_idx+1)) func add_action(): self.visible = false stage.visible = true var staged := DatabaseEntry.instance_entry() - stage.set_stage(staged) + stage.set_stage(staged, "New entry") func save_stage(entry: Dictionary): diff --git a/logic/stage.gd b/logic/stage.gd index 104e888..e2248fa 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -23,7 +23,7 @@ const OPTION_SETS_TREE_STRUCTURE := { var staged_entry_hash: int var option_sets: Dictionary - +onready var title := get_node("controls/title") as Label onready var process_id := get_node("controls/process_id") as LineEdit onready var surgery_id := get_node("controls/surgery_id") as LineEdit onready var date := get_node("controls/date_picker") as DatePicker @@ -124,7 +124,8 @@ func discard_action_confirmed(): emit_signal("discard") -func set_stage(entry: Dictionary): +func set_stage(entry: Dictionary, title: String): + self.title.text = title staged_entry_hash = entry.hash() process_id.text = entry.process_id surgery_id.text = entry.surgery_id diff --git a/main.tscn b/main.tscn index 644d393..157f171 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=2] +[gd_scene load_steps=16 format=2] [ext_resource path="res://main.gd" type="Script" id=1] [ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] @@ -12,7 +12,6 @@ [ext_resource path="res://logic/popup.gd" type="Script" id=10] [ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] [ext_resource path="res://touch_vertical_container/touch_vertical_container.tscn" type="PackedScene" id=12] -[ext_resource path="res://fonts/font_mono_regular.tres" type="DynamicFont" id=13] [ext_resource path="res://dialog/dialog.gd" type="Script" id=14] [ext_resource path="res://file_picker.gd" type="Script" id=15] @@ -37,7 +36,6 @@ theme = ExtResource( 3 ) script = ExtResource( 1 ) [node name="database" parent="." instance=ExtResource( 11 )] -custom_fonts/font = ExtResource( 13 ) script = ExtResource( 5 ) [node name="menu" type="MenuButton" parent="database"] @@ -63,11 +61,12 @@ grow_horizontal = 0 grow_vertical = 0 [node name="delete" type="Button" parent="database/actions"] -margin_right = 80.0 -margin_bottom = 95.0 +margin_right = 73.0 +margin_bottom = 86.0 focus_mode = 0 custom_fonts/font = ExtResource( 6 ) custom_styles/normal = SubResource( 1 ) +shortcut_in_tooltip = false enabled_focus_mode = 0 text = "" __meta__ = { @@ -75,12 +74,13 @@ __meta__ = { } [node name="edit" type="Button" parent="database/actions"] -margin_top = 99.0 -margin_right = 80.0 -margin_bottom = 194.0 +margin_top = 90.0 +margin_right = 73.0 +margin_bottom = 176.0 focus_mode = 0 custom_fonts/font = ExtResource( 6 ) custom_styles/normal = SubResource( 1 ) +shortcut_in_tooltip = false enabled_focus_mode = 0 text = "" __meta__ = { @@ -88,12 +88,13 @@ __meta__ = { } [node name="add" type="Button" parent="database/actions"] -margin_top = 198.0 -margin_right = 80.0 -margin_bottom = 293.0 +margin_top = 180.0 +margin_right = 73.0 +margin_bottom = 266.0 focus_mode = 0 custom_fonts/font = ExtResource( 6 ) custom_styles/normal = SubResource( 1 ) +shortcut_in_tooltip = false enabled_focus_mode = 0 text = "" __meta__ = { @@ -104,133 +105,140 @@ __meta__ = { visible = false script = ExtResource( 9 ) -[node name="process_id" type="LineEdit" parent="stage/controls" index="0"] +[node name="title" type="Label" parent="stage/controls" index="0"] margin_right = 1080.0 -margin_bottom = 62.0 +margin_bottom = 52.0 +align = 1 + +[node name="process_id" type="LineEdit" parent="stage/controls" index="1"] +margin_top = 56.0 +margin_right = 1080.0 +margin_bottom = 118.0 max_length = 32 -placeholder_text = "Nº Processo" +placeholder_text = "Process #" caret_blink = true caret_blink_speed = 0.5 -[node name="surgery_id" type="LineEdit" parent="stage/controls" index="1"] -margin_top = 66.0 +[node name="surgery_id" type="LineEdit" parent="stage/controls" index="2"] +margin_top = 122.0 margin_right = 1080.0 -margin_bottom = 128.0 +margin_bottom = 184.0 max_length = 32 -placeholder_text = "Nº Cirurgia" +placeholder_text = "Surgery #" caret_blink = true caret_blink_speed = 0.5 -[node name="date_picker" parent="stage/controls" index="2" instance=ExtResource( 2 )] +[node name="date_picker" parent="stage/controls" index="3" instance=ExtResource( 2 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 340.0 -margin_top = 132.0 +margin_top = 188.0 margin_right = 740.0 -margin_bottom = 332.0 +margin_bottom = 388.0 rect_min_size = Vector2( 400, 200 ) size_flags_horizontal = 4 -[node name="place" parent="stage/controls" index="3" instance=ExtResource( 7 )] +[node name="place" parent="stage/controls" index="4" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 336.0 +margin_top = 392.0 margin_right = 1080.0 -margin_bottom = 398.0 +margin_bottom = 454.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Local" +placeholder = "Place" -[node name="anesthesia" parent="stage/controls" index="4" instance=ExtResource( 7 )] +[node name="anesthesia" parent="stage/controls" index="5" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 402.0 +margin_top = 458.0 margin_right = 1080.0 -margin_bottom = 464.0 +margin_bottom = 520.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Anestesia" +placeholder = "Anesthesia" -[node name="first_assistant" parent="stage/controls" index="5" instance=ExtResource( 7 )] +[node name="first_assistant" parent="stage/controls" index="6" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 468.0 +margin_top = 524.0 margin_right = 1080.0 -margin_bottom = 530.0 +margin_bottom = 586.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "1º Ajudante" +placeholder = "First assistant" -[node name="type" parent="stage/controls" index="6" instance=ExtResource( 7 )] +[node name="type" parent="stage/controls" index="7" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 534.0 +margin_top = 590.0 margin_right = 1080.0 -margin_bottom = 596.0 +margin_bottom = 652.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Tipo" +placeholder = "Type" -[node name="sub_type" parent="stage/controls" index="7" instance=ExtResource( 7 )] +[node name="sub_type" parent="stage/controls" index="8" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 600.0 +margin_top = 656.0 margin_right = 1080.0 -margin_bottom = 662.0 +margin_bottom = 718.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Sub-tipo" +placeholder = "Sub-type" -[node name="sub_sub_type" parent="stage/controls" index="8" instance=ExtResource( 7 )] +[node name="sub_sub_type" parent="stage/controls" index="9" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 666.0 +margin_top = 722.0 margin_right = 1080.0 -margin_bottom = 728.0 +margin_bottom = 784.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Sub-sub-tipo" +placeholder = "Sub-sub-type" -[node name="pathology" parent="stage/controls" index="9" instance=ExtResource( 7 )] +[node name="pathology" parent="stage/controls" index="10" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 732.0 +margin_top = 788.0 margin_right = 1080.0 -margin_bottom = 794.0 +margin_bottom = 850.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Patologia" +placeholder = "Pathology" -[node name="intervention" parent="stage/controls" index="10" instance=ExtResource( 7 )] +[node name="intervention" parent="stage/controls" index="11" instance=ExtResource( 7 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 798.0 +margin_top = 854.0 margin_right = 1080.0 -margin_bottom = 860.0 +margin_bottom = 916.0 rect_min_size = Vector2( 0, 62 ) -placeholder = "Intervenção" +placeholder = "Intervention" -[node name="is_urgency" type="CheckBox" parent="stage/controls" index="11"] -margin_top = 864.0 +[node name="is_urgency" type="CheckBox" parent="stage/controls" index="12"] +margin_top = 920.0 margin_right = 1080.0 -margin_bottom = 924.0 +margin_bottom = 972.0 text = "Urgência" -[node name="notes" type="LineEdit" parent="stage/controls" index="12"] -margin_top = 928.0 +[node name="notes" type="LineEdit" parent="stage/controls" index="13"] +margin_top = 976.0 margin_right = 1080.0 -margin_bottom = 990.0 +margin_bottom = 1038.0 max_length = 4096 -placeholder_text = "Notas" +placeholder_text = "Notes" caret_blink = true caret_blink_speed = 0.5 -[node name="buttons" type="Control" parent="stage/controls" index="13"] -margin_top = 994.0 +[node name="buttons" type="Control" parent="stage/controls" index="14"] +margin_top = 1042.0 margin_right = 1080.0 -margin_bottom = 994.0 +margin_bottom = 1042.0 [node name="discard" type="Button" parent="stage/controls/buttons"] anchor_right = 0.5 +margin_right = -5.0 text = "Discard" [node name="save" type="Button" parent="stage/controls/buttons"] anchor_left = 0.5 anchor_right = 1.0 -margin_bottom = 58.0 +margin_left = 5.0 grow_horizontal = 0 text = "Save" diff --git a/option_set/option_set.tscn b/option_set/option_set.tscn index 5499361..3d09674 100644 --- a/option_set/option_set.tscn +++ b/option_set/option_set.tscn @@ -28,7 +28,7 @@ anchor_bottom = 1.0 margin_left = -100.0 grow_horizontal = 0 custom_fonts/font = ExtResource( 2 ) -text = "" +text = "" __meta__ = { "_edit_use_anchors_": false } diff --git a/project.godot b/project.godot index 4a3e1ed..36429fc 100644 --- a/project.godot +++ b/project.godot @@ -115,4 +115,5 @@ common/enable_pause_aware_picking=true [rendering] vram_compression/import_etc=true +environment/default_clear_color=Color( 0, 0, 0, 1 ) environment/default_environment="res://default_env.tres" diff --git a/themes/dark.tres b/themes/dark.tres index 832b226..717b9c2 100644 --- a/themes/dark.tres +++ b/themes/dark.tres @@ -1,6 +1,65 @@ -[gd_resource type="Theme" load_steps=2 format=2] +[gd_resource type="Theme" load_steps=9 format=2] [ext_resource path="res://fonts/font_regular.tres" type="DynamicFont" id=1] +[ext_resource path="res://fonts/font_mono_regular.tres" type="DynamicFont" id=2] + +[sub_resource type="StyleBoxFlat" id=2] +bg_color = Color( 0.11, 0.11, 0.11, 1 ) +corner_radius_top_left = 8 +corner_radius_top_right = 8 +corner_radius_bottom_right = 8 +corner_radius_bottom_left = 8 + +[sub_resource type="StyleBoxFlat" id=8] +bg_color = Color( 0.109804, 0.109804, 0.109804, 1 ) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +border_color = Color( 0.223529, 0.352941, 0.501961, 1 ) +corner_radius_top_left = 8 +corner_radius_top_right = 8 +corner_radius_bottom_right = 8 +corner_radius_bottom_left = 8 + +[sub_resource type="StyleBoxFlat" id=4] +bg_color = Color( 0.223529, 0.352941, 0.501961, 1 ) +corner_radius_top_left = 8 +corner_radius_top_right = 8 +corner_radius_bottom_right = 8 +corner_radius_bottom_left = 8 + +[sub_resource type="StyleBoxEmpty" id=5] + +[sub_resource type="StyleBoxFlat" id=9] +content_margin_left = 10.0 +content_margin_right = 10.0 +content_margin_top = 5.0 +content_margin_bottom = 5.0 +bg_color = Color( 0, 0, 0, 0 ) +draw_center = false +border_width_bottom = 3 +border_color = Color( 0.223529, 0.352941, 0.501961, 1 ) + +[sub_resource type="StyleBoxFlat" id=7] +content_margin_left = 10.0 +content_margin_right = 10.0 +content_margin_top = 5.0 +content_margin_bottom = 5.0 +bg_color = Color( 0, 0, 0, 0 ) +draw_center = false +border_width_bottom = 3 +border_color = Color( 0.33, 0.33, 0.33, 1 ) [resource] default_font = ExtResource( 1 ) +Button/styles/disabled = null +Button/styles/focus = SubResource( 2 ) +Button/styles/hover = SubResource( 8 ) +Button/styles/normal = SubResource( 2 ) +Button/styles/pressed = SubResource( 4 ) +ItemList/fonts/font = ExtResource( 2 ) +ItemList/styles/bg = SubResource( 5 ) +LineEdit/styles/focus = SubResource( 9 ) +LineEdit/styles/normal = SubResource( 7 ) +LineEdit/styles/read_only = null -- cgit v1.2.3 From 2d7da6bbc23fb917dfe931eaeb5566da0a102ac3 Mon Sep 17 00:00:00 2001 From: dam Date: Sun, 10 Apr 2022 08:32:49 +0000 Subject: Code cleanup. --- date_picker/date_picker.gd | 64 --- date_picker/date_picker.tscn | 189 --------- date_picker/value_picker.gd | 132 ------- dialog/dialog.gd | 79 ---- file_picker.gd | 18 - logic/file_picker.gd | 18 + logic/menu.gd | 121 ++++++ logic/popup.gd | 76 ---- main.tscn | 54 +-- menu/font_b612.txt | 93 ----- menu/godot.txt | 20 - menu/menu.gd | 121 ------ old_native_project/AndroidManifest.xml | 30 -- .../gen/net/redroid/medlog/BuildConfig.java | 6 - old_native_project/gen/net/redroid/medlog/R.java | 145 ------- old_native_project/ic_launcher-web.png | Bin 118840 -> 0 bytes old_native_project/ic_launcher-web.png.import | 35 -- old_native_project/libs/android-support-v4.jar | Bin 627582 -> 0 bytes old_native_project/libs/javacsv.jar | Bin 13582 -> 0 bytes old_native_project/lint.xml | 3 - old_native_project/proguard-project.txt | 20 - old_native_project/project.properties | 14 - .../res/drawable-hdpi/ic_launcher.png | Bin 6369 -> 0 bytes .../res/drawable-hdpi/ic_launcher.png.import | 35 -- .../res/drawable-mdpi/ic_launcher.png | Bin 3108 -> 0 bytes .../res/drawable-mdpi/ic_launcher.png.import | 35 -- .../res/drawable-xhdpi/ic_launcher.png | Bin 9945 -> 0 bytes .../res/drawable-xhdpi/ic_launcher.png.import | 35 -- .../res/drawable-xxhdpi/ic_launcher.png | Bin 18410 -> 0 bytes .../res/drawable-xxhdpi/ic_launcher.png.import | 35 -- old_native_project/res/layout/activity_main.xml | 23 -- .../res/layout/fragment_file_operations.xml | 31 -- .../res/layout/fragment_main_dummy.xml | 16 - .../res/layout/fragment_new_entry.xml | 216 ---------- .../res/layout/fragment_view_data.xml | 24 -- .../res/layout/multiline_spinner_dropdown_item.xml | 28 -- .../res/layout/override_new_entry.xml | 95 ----- old_native_project/res/menu/main.xml | 9 - old_native_project/res/values-sw600dp/dimens.xml | 8 - .../res/values-sw720dp-land/dimens.xml | 9 - old_native_project/res/values-v11/styles.xml | 11 - old_native_project/res/values-v14/styles.xml | 12 - old_native_project/res/values/dimens.xml | 7 - old_native_project/res/values/strings.xml | 38 -- old_native_project/res/values/styles.xml | 20 - .../example/surgerylog/FileOperationsFragment.java | 185 --------- .../com/example/surgerylog/ISpinnerRefresh.java | 9 - .../src/com/example/surgerylog/MainActivity.java | 330 ---------------- .../src/com/example/surgerylog/MedLogInfo.java | 51 --- .../src/com/example/surgerylog/MedLogRoot.java | 142 ------- .../src/com/example/surgerylog/MedLogSubType.java | 87 ---- .../src/com/example/surgerylog/MedLogType.java | 52 --- .../com/example/surgerylog/NewEntryFragment.java | 437 --------------------- .../com/example/surgerylog/ViewDataFragment.java | 173 -------- option_set/option_set.gd | 44 --- option_set/option_set.tscn | 34 -- option_set/option_set_list.gd | 294 -------------- option_set/option_set_list.tscn | 9 - pointer_input_sensor.gd | 117 ------ project.godot | 18 +- readme.md | 8 +- touch_item_list/touch_item_list.gd | 68 ---- touch_item_list/touch_item_list.tscn | 19 - .../touch_vertical_container.gd | 118 ------ .../touch_vertical_container.tscn | 19 - ui/date_picker/date_picker.gd | 64 +++ ui/date_picker/date_picker.tscn | 189 +++++++++ ui/date_picker/value_picker.gd | 132 +++++++ ui/dialog/dialog.gd | 79 ++++ ui/modal_popup/modal_popup.gd | 76 ++++ ui/modal_popup/modal_popup.tscn | 40 ++ ui/option_set/option_set.gd | 44 +++ ui/option_set/option_set.tscn | 34 ++ ui/option_set/option_set_list.gd | 294 ++++++++++++++ ui/option_set/option_set_list.tscn | 9 + ui/pointer_input_sensor.gd | 117 ++++++ ui/touch_item_list/touch_item_list.gd | 68 ++++ ui/touch_item_list/touch_item_list.tscn | 19 + .../touch_vertical_container.gd | 118 ++++++ .../touch_vertical_container.tscn | 19 + 80 files changed, 1464 insertions(+), 3977 deletions(-) delete mode 100644 date_picker/date_picker.gd delete mode 100644 date_picker/date_picker.tscn delete mode 100644 date_picker/value_picker.gd delete mode 100644 dialog/dialog.gd delete mode 100644 file_picker.gd create mode 100644 logic/file_picker.gd create mode 100644 logic/menu.gd delete mode 100644 logic/popup.gd delete mode 100644 menu/font_b612.txt delete mode 100644 menu/godot.txt delete mode 100644 menu/menu.gd delete mode 100755 old_native_project/AndroidManifest.xml delete mode 100755 old_native_project/gen/net/redroid/medlog/BuildConfig.java delete mode 100755 old_native_project/gen/net/redroid/medlog/R.java delete mode 100755 old_native_project/ic_launcher-web.png delete mode 100644 old_native_project/ic_launcher-web.png.import delete mode 100755 old_native_project/libs/android-support-v4.jar delete mode 100755 old_native_project/libs/javacsv.jar delete mode 100755 old_native_project/lint.xml delete mode 100755 old_native_project/proguard-project.txt delete mode 100755 old_native_project/project.properties delete mode 100755 old_native_project/res/drawable-hdpi/ic_launcher.png delete mode 100644 old_native_project/res/drawable-hdpi/ic_launcher.png.import delete mode 100755 old_native_project/res/drawable-mdpi/ic_launcher.png delete mode 100644 old_native_project/res/drawable-mdpi/ic_launcher.png.import delete mode 100755 old_native_project/res/drawable-xhdpi/ic_launcher.png delete mode 100644 old_native_project/res/drawable-xhdpi/ic_launcher.png.import delete mode 100755 old_native_project/res/drawable-xxhdpi/ic_launcher.png delete mode 100644 old_native_project/res/drawable-xxhdpi/ic_launcher.png.import delete mode 100755 old_native_project/res/layout/activity_main.xml delete mode 100755 old_native_project/res/layout/fragment_file_operations.xml delete mode 100755 old_native_project/res/layout/fragment_main_dummy.xml delete mode 100755 old_native_project/res/layout/fragment_new_entry.xml delete mode 100755 old_native_project/res/layout/fragment_view_data.xml delete mode 100755 old_native_project/res/layout/multiline_spinner_dropdown_item.xml delete mode 100755 old_native_project/res/layout/override_new_entry.xml delete mode 100755 old_native_project/res/menu/main.xml delete mode 100755 old_native_project/res/values-sw600dp/dimens.xml delete mode 100755 old_native_project/res/values-sw720dp-land/dimens.xml delete mode 100755 old_native_project/res/values-v11/styles.xml delete mode 100755 old_native_project/res/values-v14/styles.xml delete mode 100755 old_native_project/res/values/dimens.xml delete mode 100755 old_native_project/res/values/strings.xml delete mode 100755 old_native_project/res/values/styles.xml delete mode 100755 old_native_project/src/com/example/surgerylog/FileOperationsFragment.java delete mode 100755 old_native_project/src/com/example/surgerylog/ISpinnerRefresh.java delete mode 100755 old_native_project/src/com/example/surgerylog/MainActivity.java delete mode 100755 old_native_project/src/com/example/surgerylog/MedLogInfo.java delete mode 100755 old_native_project/src/com/example/surgerylog/MedLogRoot.java delete mode 100755 old_native_project/src/com/example/surgerylog/MedLogSubType.java delete mode 100755 old_native_project/src/com/example/surgerylog/MedLogType.java delete mode 100755 old_native_project/src/com/example/surgerylog/NewEntryFragment.java delete mode 100755 old_native_project/src/com/example/surgerylog/ViewDataFragment.java delete mode 100644 option_set/option_set.gd delete mode 100644 option_set/option_set.tscn delete mode 100644 option_set/option_set_list.gd delete mode 100644 option_set/option_set_list.tscn delete mode 100644 pointer_input_sensor.gd delete mode 100644 touch_item_list/touch_item_list.gd delete mode 100644 touch_item_list/touch_item_list.tscn delete mode 100644 touch_vertical_container/touch_vertical_container.gd delete mode 100644 touch_vertical_container/touch_vertical_container.tscn create mode 100644 ui/date_picker/date_picker.gd create mode 100644 ui/date_picker/date_picker.tscn create mode 100644 ui/date_picker/value_picker.gd create mode 100644 ui/dialog/dialog.gd create mode 100644 ui/modal_popup/modal_popup.gd create mode 100644 ui/modal_popup/modal_popup.tscn create mode 100644 ui/option_set/option_set.gd create mode 100644 ui/option_set/option_set.tscn create mode 100644 ui/option_set/option_set_list.gd create mode 100644 ui/option_set/option_set_list.tscn create mode 100644 ui/pointer_input_sensor.gd create mode 100644 ui/touch_item_list/touch_item_list.gd create mode 100644 ui/touch_item_list/touch_item_list.tscn create mode 100644 ui/touch_vertical_container/touch_vertical_container.gd create mode 100644 ui/touch_vertical_container/touch_vertical_container.tscn (limited to 'project.godot') diff --git a/date_picker/date_picker.gd b/date_picker/date_picker.gd deleted file mode 100644 index e2a793f..0000000 --- a/date_picker/date_picker.gd +++ /dev/null @@ -1,64 +0,0 @@ -extends Control -class_name DatePicker - -const days_per_month: Dictionary = { - 1: 31, - 2: 28, - 3: 31, - 4: 30, - 5: 31, - 6: 30, - 7: 31, - 8: 31, - 9: 30, - 10: 31, - 11: 30, - 12: 31, -} - -onready var year_picker := get_node("year") as ValuePicker -onready var month_picker := get_node("month") as ValuePicker -onready var day_picker := get_node("day") as ValuePicker - - -func _process(delta: float): - var year := year_picker.value - var month := month_picker.value - var day := day_picker.value - var days_on_month: int = days_per_month[month] - - var is_leap_year := (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 - if is_leap_year && month == 2: - days_on_month = 29 - - if day > days_on_month: - day_picker.value = days_on_month - day_picker.max_value = days_on_month - - -func get_day() -> int: - return day_picker.value - - -func get_month() -> int: - return month_picker.value - - -func get_year() -> int: - return year_picker.value - - -func get_date() -> Dictionary: - return { - year = year_picker.value, - month = month_picker.value, - day = day_picker.value, - } - - -func set_date(new_year: int, new_month: int, new_day: int): - year_picker.value = new_year - month_picker.value = new_month - day_picker.value = new_day - - diff --git a/date_picker/date_picker.tscn b/date_picker/date_picker.tscn deleted file mode 100644 index 8b082f2..0000000 --- a/date_picker/date_picker.tscn +++ /dev/null @@ -1,189 +0,0 @@ -[gd_scene load_steps=3 format=2] - -[ext_resource path="res://date_picker/value_picker.gd" type="Script" id=1] -[ext_resource path="res://date_picker/date_picker.gd" type="Script" id=2] - -[node name="date_picker" type="Control"] -anchor_right = 1.0 -anchor_bottom = 1.0 -script = ExtResource( 2 ) - -[node name="year" type="Control" parent="."] -anchor_right = 0.333 -anchor_bottom = 1.0 -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} -min_value = 1 -max_value = 9999 - -[node name="previous" type="Label" parent="year"] -anchor_right = 1.0 -anchor_bottom = 0.333 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="current" type="Label" parent="year"] -anchor_top = 0.333 -anchor_right = 1.0 -anchor_bottom = 0.666 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="input" type="LineEdit" parent="year/current"] -visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -focus_next = NodePath("../../../month/current/input") -custom_constants/minimum_spaces = 0 -align = 1 -max_length = 4 -caret_blink = true - -[node name="next" type="Label" parent="year"] -anchor_top = 0.666 -anchor_right = 1.0 -anchor_bottom = 1.0 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="month" type="Control" parent="."] -anchor_left = 0.333 -anchor_right = 0.666 -anchor_bottom = 1.0 -script = ExtResource( 1 ) -min_value = 1 -max_value = 12 - -[node name="previous" type="Label" parent="month"] -anchor_right = 1.0 -anchor_bottom = 0.333 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="current" type="Label" parent="month"] -anchor_top = 0.333 -anchor_right = 1.0 -anchor_bottom = 0.666 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="input" type="LineEdit" parent="month/current"] -visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -focus_next = NodePath("../../../day/current/input") -focus_previous = NodePath("../../../year/current/input") -custom_constants/minimum_spaces = 0 -align = 1 -max_length = 2 -caret_blink = true - -[node name="next" type="Label" parent="month"] -anchor_top = 0.666 -anchor_right = 1.0 -anchor_bottom = 1.0 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="day" type="Control" parent="."] -anchor_left = 0.666 -anchor_right = 1.0 -anchor_bottom = 1.0 -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} -min_value = 1 -max_value = 31 - -[node name="previous" type="Label" parent="day"] -anchor_right = 1.0 -anchor_bottom = 0.333 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="current" type="Label" parent="day"] -anchor_top = 0.333 -anchor_right = 1.0 -anchor_bottom = 0.666 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="input" type="LineEdit" parent="day/current"] -visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -focus_previous = NodePath("../../../month/current/input") -custom_constants/minimum_spaces = 0 -align = 1 -max_length = 2 -caret_blink = true - -[node name="next" type="Label" parent="day"] -anchor_top = 0.666 -anchor_right = 1.0 -anchor_bottom = 1.0 -mouse_filter = 1 -align = 1 -valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="split_upper" type="ColorRect" parent="."] -anchor_top = 0.333 -anchor_right = 1.0 -anchor_bottom = 0.343 -color = Color( 1, 1, 1, 0.25 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="split_lower" type="ColorRect" parent="."] -anchor_top = 0.666 -anchor_right = 1.0 -anchor_bottom = 0.676 -color = Color( 1, 1, 1, 0.25 ) -__meta__ = { -"_edit_use_anchors_": false -} diff --git a/date_picker/value_picker.gd b/date_picker/value_picker.gd deleted file mode 100644 index b70f1aa..0000000 --- a/date_picker/value_picker.gd +++ /dev/null @@ -1,132 +0,0 @@ -extends Control - -class_name ValuePicker - -const VELOCITY_DECAYING_FACTOR: float = 5.5 -const BINNING_THRESHOLD: float = 0.75 -const BINNING_ADJUST_P: float = 5.0 -const DRAG_THRESHOLD_CM: float = 0.250 - -export var min_value: int -export var max_value: int - -var pointer: Dictionary -var anchor: float -var value: int -var offset: float - -var scroll_unit_height: float -var label_previous_base_position: float -var label_current_base_position: float -var label_next_base_position: float - -onready var input := get_node("current/input") as LineEdit -onready var label_previous := get_node("previous") as Label -onready var label_current := get_node("current") as Label -onready var label_next := get_node("next") as Label -onready var screen_dpcm := float(OS.get_screen_dpi()) / 2.54 - - -func _ready(): - pointer = { - index = -1, - initial_position = Vector2.ZERO, - current_position = Vector2.ZERO, - velocity = Vector2.ZERO, - was_dragged = false, - is_active = false, - } - - input.connect("text_entered", self, "input_text_entered") - input.connect("focus_entered", self, "input_focus_entered") - input.connect("focus_exited", self, "input_focus_exited") - - scroll_unit_height = label_current.rect_size.y - label_previous_base_position = label_previous.rect_position.y - label_current_base_position = label_current.rect_position.y - label_next_base_position = label_next.rect_position.y - - value = min_value - offset = 0.0 - - -func _process(delta: float): - - if pointer.is_active: - var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y) - offset = anchor + (dragged_distance / scroll_unit_height) - value = int(offset) - offset -= value - else: - pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) - offset -= pointer.velocity.y * delta / scroll_unit_height - if abs(pointer.velocity.y) < BINNING_THRESHOLD * scroll_unit_height: - offset -= offset * BINNING_ADJUST_P * delta - - # Using 'offset * 2.0' (equivalent to 'offset / 0.5') rounds the value based on 0.5 units. - var cummulative_displacement := int(offset * 2.0) - value = wrapi(value + cummulative_displacement, min_value, max_value + 1) - offset -= cummulative_displacement - - label_current.text = "%d" % value - label_next.text = "%d" % wrapi(value + 1, min_value, max_value + 1) - label_previous.text = "%d" % wrapi(value - 1, min_value, max_value + 1) - - var offset_position := offset * scroll_unit_height - label_current.rect_position.y = label_current_base_position - offset_position - label_previous.rect_position.y = label_previous_base_position - offset_position - label_next.rect_position.y = label_next_base_position - offset_position - - label_previous.modulate.a = 0.5 - offset - label_next.modulate.a = offset + 0.5 - - -func _gui_input(event: InputEvent): - - # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. - if event is InputEventScreenTouch || event is InputEventScreenDrag: - if event.index != 0: - return - - if event is InputEventScreenTouch && (pointer.is_active == false || pointer.index == event.index): - var touch := event as InputEventScreenTouch - pointer.is_active = event.pressed - pointer.current_position = touch.position - if pointer.is_active: - input.release_focus() - pointer.index = touch.index - pointer.initial_position = touch.position - anchor = value + offset - else: - if pointer.was_dragged == false: # Click detected. - input.grab_focus() - pointer.index = -1 - pointer.was_dragged = false - - if event is InputEventScreenDrag && event.index == pointer.index: - var drag := event as InputEventScreenDrag - pointer.current_position = drag.position - pointer.velocity = drag.speed - if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM: - pointer.was_dragged = true - - -func input_text_entered(new_text: String): - input.release_focus() - - -func input_focus_entered(): - pointer.velocity = Vector2.ZERO # Avoid changing to other value once entering input. - input.text = "%d" % value - input.visible = true - input.select_all() - label_current.self_modulate.a = 0.0 - - -func input_focus_exited(): - if input.text.is_valid_integer(): - value = wrapi(int(input.text), min_value, max_value + 1) - input.visible = false - label_current.self_modulate.a = 1.0 - - diff --git a/dialog/dialog.gd b/dialog/dialog.gd deleted file mode 100644 index 89fee5c..0000000 --- a/dialog/dialog.gd +++ /dev/null @@ -1,79 +0,0 @@ -extends Control -class_name Dialog - -signal answered # (accepted: bool) -signal accepted # () -signal rejected # () - -export var clear_signals_on_hide := true - -var message : Label -var accept_button : Button -var reject_button : Button - - -func _init(): - self.anchor_right = 1.0 - self.anchor_bottom = 1.0 - self.rect_clip_content = true - self.connect("hide", self, "_clear_signals") - - reject_button = Button.new() - reject_button.anchor_top = 1.0 - reject_button.anchor_left = 0.0 - reject_button.anchor_right = 0.5 - reject_button.margin_right = -5.0 - reject_button.rect_min_size.y = 62.0 - reject_button.grow_vertical = Control.GROW_DIRECTION_BEGIN - reject_button.name = "reject" - reject_button.connect("pressed", self, "_signal_rejected") - add_child(reject_button) - - accept_button = Button.new() - accept_button.anchor_top = 1.0 - accept_button.anchor_left = 0.5 - accept_button.anchor_right = 1.0 - accept_button.margin_left = 5.0 - accept_button.rect_min_size.y = 62.0 - accept_button.grow_vertical = Control.GROW_DIRECTION_BEGIN - accept_button.name = "accept" - accept_button.connect("pressed", self, "_signal_accepted") - add_child(accept_button) - - message = Label.new() - message.autowrap = true - message.align = Label.ALIGN_CENTER - message.anchor_right = 1.0 - message.anchor_bottom = 1.0 - add_child(message) - - -func _clear_signals(): - if clear_signals_on_hide == false: - return - - for signal_name in ["answered", "accepted", "rejected"]: - for it in get_signal_connection_list(signal_name): - disconnect(it.signal, it.target, it.method) - - -func _signal_rejected(): - emit_signal("rejected") - emit_signal("answered", false) - hide() - - -func _signal_accepted(): - emit_signal("accepted") - emit_signal("answered", true) - hide() - - -func setup(message: String, accept_label: String = "Accept", reject_label: String = "Reject"): - self.message.text = message - accept_button.visible = accept_label != "" - accept_button.text = accept_label - reject_button.visible = reject_label != "" - reject_button.text = reject_label - - diff --git a/file_picker.gd b/file_picker.gd deleted file mode 100644 index 9715d0d..0000000 --- a/file_picker.gd +++ /dev/null @@ -1,18 +0,0 @@ -extends FileDialog - -export var clear_signals_on_hide := true - - -func _init(): - self.connect("hide", self, "_clear_signals") - - -func _clear_signals(): - if clear_signals_on_hide == false: - return - - for signal_name in ["file_selected"]: - for it in get_signal_connection_list(signal_name): - disconnect(it.signal, it.target, it.method) - - diff --git a/logic/file_picker.gd b/logic/file_picker.gd new file mode 100644 index 0000000..9715d0d --- /dev/null +++ b/logic/file_picker.gd @@ -0,0 +1,18 @@ +extends FileDialog + +export var clear_signals_on_hide := true + + +func _init(): + self.connect("hide", self, "_clear_signals") + + +func _clear_signals(): + if clear_signals_on_hide == false: + return + + for signal_name in ["file_selected"]: + for it in get_signal_connection_list(signal_name): + disconnect(it.signal, it.target, it.method) + + diff --git a/logic/menu.gd b/logic/menu.gd new file mode 100644 index 0000000..d6e1501 --- /dev/null +++ b/logic/menu.gd @@ -0,0 +1,121 @@ +extends MenuButton + +const menu_items: Array = [ + { label = "Import Option Sets", action = "import_option_sets_action" }, + { label = "Export Option Sets", action = "export_option_sets_action" }, + { label = "Clear Option Sets", action = "clear_option_sets_action" }, + { label = "Import Database", action = "import_database_action" }, + { label = "Export Database", action = "export_database_action" }, + { label = "Clear Database", action = "clear_database_action" }, + { label = "About", action = "about_action" }, +] +const license_font_b612: String = "res://licenses/font_b612.txt" +const license_godot: String = "res://licenses/godot.txt" + +onready var menu := get_popup() as PopupMenu +onready var popup := get_node("/root/main/popup") as ModalPopup +onready var dialog := get_node("/root/main/dialog") as Dialog +onready var file_picker := get_node("/root/main/file_picker") as FileDialog +onready var database := get_node("/root/main/database") as Database +onready var stage := get_node("/root/main/stage") as Stage + + +func _ready(): + for idx in range(menu_items.size()): + menu.add_item(menu_items[idx].label, idx) + menu.connect("id_pressed", self, "id_pressed") + + +func id_pressed(id: int): + self.call_deferred(menu_items[id].action) + + +func import_option_sets_action(): + dialog.setup("All option sets from the dropdown menus will be replaced.", "Continue", "No") + dialog.connect("accepted", self, "import_option_sets_action_accepted") + popup.open_popup("Replace option sets?", dialog) + + +func import_option_sets_action_accepted(): + file_picker.mode = FileDialog.MODE_OPEN_FILE + file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters = ["*.json", "*.csv"] + file_picker.current_file = "" + file_picker.connect("file_selected", self, "import_option_sets") + file_picker.show_modal(true) + file_picker.invalidate() + + +func import_option_sets(file_path: String): + stage.load_option_sets(file_path) + stage.save_option_sets() + + +func export_option_sets_action(): + file_picker.mode = FileDialog.MODE_SAVE_FILE + file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters = ["*.json"] + file_picker.current_file = "" + file_picker.connect("file_selected", stage, "save_option_sets") + file_picker.show_modal(true) + file_picker.invalidate() + + +func clear_option_sets_action(): + dialog.setup("All option sets from the dropdown menus will be deleted.", "Delete all", "No") + dialog.connect("accepted", self, "clear_option_sets") + popup.open_popup("Clear option sets?", dialog) + + +func clear_option_sets(): + stage.clear_option_sets() + stage.save_option_sets() + + +func import_database_action(): + dialog.setup("All entries from the database will be replaced.", "Continue", "No") + dialog.connect("accepted", self, "import_database_action_accepted") + popup.open_popup("Replace database?", dialog) + + +func import_database_action_accepted(): + file_picker.mode = FileDialog.MODE_OPEN_FILE + file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters = ["*.json", "*.csv"] + file_picker.current_file = "" + file_picker.connect("file_selected", self, "import_database") + file_picker.show_modal(true) + file_picker.invalidate() + + +func import_database(file_path: String): + database.load_database(file_path) + database.save_database() + + +func export_database_action(): + file_picker.mode = FileDialog.MODE_SAVE_FILE + file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters = ["*.csv"] + file_picker.current_file = "" + file_picker.connect("file_selected", database, "save_database") + file_picker.show_modal(true) + file_picker.invalidate() + + +func clear_database_action(): + dialog.setup("All entries from the database will be deleted.", "Delete all", "No") + dialog.connect("accepted", self, "clear_database") + popup.open_popup("Clear database?", dialog) + + +func clear_database(): + database.clear_database() + database.save_database() + + +func about_action(): + dialog.setup("Surgery Log\nversion 0.1", "", "") + popup.open_popup("About", dialog) + + diff --git a/logic/popup.gd b/logic/popup.gd deleted file mode 100644 index 95fc2c3..0000000 --- a/logic/popup.gd +++ /dev/null @@ -1,76 +0,0 @@ -extends Control -class_name ModalPopup - -signal dismissed # () - -export var clear_signals_on_hide := true - -var control : Control -var control_parent : Node - -onready var title := get_node("title") as Label -onready var background := get_node("background") as Panel -onready var dismiss_button := get_node("dismiss") as Button - - -func _init(): - self.anchor_right = 1.0 - self.anchor_bottom = 1.0 - self.rect_clip_content = true - self.connect("hide", self, "_clear_signals") - - -func _ready(): - dismiss_button.connect("pressed", self, "dismiss") - - -func _clear_signals(): - if clear_signals_on_hide == false: - return - - for signal_name in ["dismissed"]: - for it in get_signal_connection_list(signal_name): - disconnect(it.signal, it.target, it.method) - - -func dismiss(): - emit_signal("dismissed") - close_popup() - - -func open_popup(title: String, item: Control): - if visible == true: - return - - self.title.text = title - - control = item - control.connect("hide", self, "close_popup") - control_parent = control.get_parent() - control_parent.remove_child(control) - self.add_child(control) - - control.anchor_left = background.anchor_left - control.anchor_top = background.anchor_top - control.anchor_right = background.anchor_right - control.anchor_bottom = background.anchor_bottom - control.margin_left = 20 - control.margin_top = 20 - control.margin_right = -20 - control.margin_bottom = -20 - - self.show() - control.show() - - -func close_popup(): - if visible == false: - return - - control.disconnect("hide", self, "close_popup") - control.hide() - self.hide() - remove_child(control) - control_parent.add_child(control) - control_parent = null - diff --git a/main.tscn b/main.tscn index 4a99142..9fce789 100644 --- a/main.tscn +++ b/main.tscn @@ -1,19 +1,19 @@ [gd_scene load_steps=15 format=2] [ext_resource path="res://main.gd" type="Script" id=1] -[ext_resource path="res://date_picker/date_picker.tscn" type="PackedScene" id=2] +[ext_resource path="res://ui/date_picker/date_picker.tscn" type="PackedScene" id=2] [ext_resource path="res://themes/dark.tres" type="Theme" id=3] -[ext_resource path="res://menu/menu.gd" type="Script" id=4] +[ext_resource path="res://logic/menu.gd" type="Script" id=4] [ext_resource path="res://logic/database.gd" type="Script" id=5] [ext_resource path="res://fonts/font_icons.tres" type="DynamicFont" id=6] -[ext_resource path="res://option_set/option_set.tscn" type="PackedScene" id=7] -[ext_resource path="res://option_set/option_set_list.gd" type="Script" id=8] +[ext_resource path="res://ui/option_set/option_set.tscn" type="PackedScene" id=7] +[ext_resource path="res://ui/option_set/option_set_list.gd" type="Script" id=8] [ext_resource path="res://logic/stage.gd" type="Script" id=9] -[ext_resource path="res://logic/popup.gd" type="Script" id=10] -[ext_resource path="res://touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] -[ext_resource path="res://touch_vertical_container/touch_vertical_container.tscn" type="PackedScene" id=12] -[ext_resource path="res://dialog/dialog.gd" type="Script" id=14] -[ext_resource path="res://file_picker.gd" type="Script" id=15] +[ext_resource path="res://ui/modal_popup/modal_popup.tscn" type="PackedScene" id=10] +[ext_resource path="res://ui/touch_item_list/touch_item_list.tscn" type="PackedScene" id=11] +[ext_resource path="res://ui/touch_vertical_container/touch_vertical_container.tscn" type="PackedScene" id=12] +[ext_resource path="res://ui/dialog/dialog.gd" type="Script" id=14] +[ext_resource path="res://logic/file_picker.gd" type="Script" id=15] [node name="main" type="Control"] anchor_right = 1.0 @@ -258,41 +258,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="popup" type="ColorRect" parent="."] -visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 -color = Color( 0, 0, 0, 0.870588 ) -script = ExtResource( 10 ) - -[node name="background" type="Panel" parent="popup"] -anchor_left = 0.05 -anchor_top = 0.1 -anchor_right = 0.95 -anchor_bottom = 0.975 - -[node name="title" type="Label" parent="popup"] -anchor_left = 0.124 -anchor_top = 0.025 -anchor_right = 0.95 -anchor_bottom = 0.1 -margin_left = 0.0799866 -margin_right = -80.0 -margin_bottom = -20.0 -align = 1 -valign = 1 -autowrap = true - -[node name="dismiss" type="Button" parent="popup"] -anchor_left = 0.05 -anchor_top = 0.025 -anchor_right = 0.124 -anchor_bottom = 0.1 -margin_right = 0.0799866 -margin_bottom = -20.0 -custom_fonts/font = ExtResource( 6 ) -text = "" -flat = true +[node name="popup" parent="." instance=ExtResource( 10 )] [node name="option_set_list" type="Control" parent="."] visible = false diff --git a/menu/font_b612.txt b/menu/font_b612.txt deleted file mode 100644 index 2826948..0000000 --- a/menu/font_b612.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2012 The B612 Project Authors (https://github.com/polarsys/b612) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/menu/godot.txt b/menu/godot.txt deleted file mode 100644 index bee83fb..0000000 --- a/menu/godot.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. -Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/menu/menu.gd b/menu/menu.gd deleted file mode 100644 index d6e1501..0000000 --- a/menu/menu.gd +++ /dev/null @@ -1,121 +0,0 @@ -extends MenuButton - -const menu_items: Array = [ - { label = "Import Option Sets", action = "import_option_sets_action" }, - { label = "Export Option Sets", action = "export_option_sets_action" }, - { label = "Clear Option Sets", action = "clear_option_sets_action" }, - { label = "Import Database", action = "import_database_action" }, - { label = "Export Database", action = "export_database_action" }, - { label = "Clear Database", action = "clear_database_action" }, - { label = "About", action = "about_action" }, -] -const license_font_b612: String = "res://licenses/font_b612.txt" -const license_godot: String = "res://licenses/godot.txt" - -onready var menu := get_popup() as PopupMenu -onready var popup := get_node("/root/main/popup") as ModalPopup -onready var dialog := get_node("/root/main/dialog") as Dialog -onready var file_picker := get_node("/root/main/file_picker") as FileDialog -onready var database := get_node("/root/main/database") as Database -onready var stage := get_node("/root/main/stage") as Stage - - -func _ready(): - for idx in range(menu_items.size()): - menu.add_item(menu_items[idx].label, idx) - menu.connect("id_pressed", self, "id_pressed") - - -func id_pressed(id: int): - self.call_deferred(menu_items[id].action) - - -func import_option_sets_action(): - dialog.setup("All option sets from the dropdown menus will be replaced.", "Continue", "No") - dialog.connect("accepted", self, "import_option_sets_action_accepted") - popup.open_popup("Replace option sets?", dialog) - - -func import_option_sets_action_accepted(): - file_picker.mode = FileDialog.MODE_OPEN_FILE - file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) - file_picker.filters = ["*.json", "*.csv"] - file_picker.current_file = "" - file_picker.connect("file_selected", self, "import_option_sets") - file_picker.show_modal(true) - file_picker.invalidate() - - -func import_option_sets(file_path: String): - stage.load_option_sets(file_path) - stage.save_option_sets() - - -func export_option_sets_action(): - file_picker.mode = FileDialog.MODE_SAVE_FILE - file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) - file_picker.filters = ["*.json"] - file_picker.current_file = "" - file_picker.connect("file_selected", stage, "save_option_sets") - file_picker.show_modal(true) - file_picker.invalidate() - - -func clear_option_sets_action(): - dialog.setup("All option sets from the dropdown menus will be deleted.", "Delete all", "No") - dialog.connect("accepted", self, "clear_option_sets") - popup.open_popup("Clear option sets?", dialog) - - -func clear_option_sets(): - stage.clear_option_sets() - stage.save_option_sets() - - -func import_database_action(): - dialog.setup("All entries from the database will be replaced.", "Continue", "No") - dialog.connect("accepted", self, "import_database_action_accepted") - popup.open_popup("Replace database?", dialog) - - -func import_database_action_accepted(): - file_picker.mode = FileDialog.MODE_OPEN_FILE - file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) - file_picker.filters = ["*.json", "*.csv"] - file_picker.current_file = "" - file_picker.connect("file_selected", self, "import_database") - file_picker.show_modal(true) - file_picker.invalidate() - - -func import_database(file_path: String): - database.load_database(file_path) - database.save_database() - - -func export_database_action(): - file_picker.mode = FileDialog.MODE_SAVE_FILE - file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) - file_picker.filters = ["*.csv"] - file_picker.current_file = "" - file_picker.connect("file_selected", database, "save_database") - file_picker.show_modal(true) - file_picker.invalidate() - - -func clear_database_action(): - dialog.setup("All entries from the database will be deleted.", "Delete all", "No") - dialog.connect("accepted", self, "clear_database") - popup.open_popup("Clear database?", dialog) - - -func clear_database(): - database.clear_database() - database.save_database() - - -func about_action(): - dialog.setup("Surgery Log\nversion 0.1", "", "") - popup.open_popup("About", dialog) - - diff --git a/old_native_project/AndroidManifest.xml b/old_native_project/AndroidManifest.xml deleted file mode 100755 index fd4ec79..0000000 --- a/old_native_project/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/old_native_project/gen/net/redroid/medlog/BuildConfig.java b/old_native_project/gen/net/redroid/medlog/BuildConfig.java deleted file mode 100755 index c27f499..0000000 --- a/old_native_project/gen/net/redroid/medlog/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -/** Automatically generated file. DO NOT MODIFY */ -package net.redroid.medlog; - -public final class BuildConfig { - public final static boolean DEBUG = true; -} \ No newline at end of file diff --git a/old_native_project/gen/net/redroid/medlog/R.java b/old_native_project/gen/net/redroid/medlog/R.java deleted file mode 100755 index 59722b1..0000000 --- a/old_native_project/gen/net/redroid/medlog/R.java +++ /dev/null @@ -1,145 +0,0 @@ -/* AUTO-GENERATED FILE. DO NOT MODIFY. - * - * This class was automatically generated by the - * aapt tool from the resource data it found. It - * should not be modified by hand. - */ - -package net.redroid.medlog; - -public final class R { - public static final class attr { - } - public static final class dimen { - /** Default screen margins, per the Android Design guidelines. - - Customize dimensions originally defined in res/values/dimens.xml (such as - screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here. - - */ - public static final int activity_horizontal_margin=0x7f040000; - public static final int activity_vertical_margin=0x7f040001; - } - public static final class drawable { - public static final int ic_launcher=0x7f020000; - } - public static final class id { - public static final int FileOperationsView=0x7f080002; - public static final int NewEntryView=0x7f080006; - public static final int OverrideNewEntry=0x7f080022; - public static final int RelativeLayout1=0x7f08001f; - public static final int action_settings=0x7f08002b; - public static final int anesthesiaOverride=0x7f08000d; - public static final int anesthesiaSpinner=0x7f08000c; - public static final int dataBaseListView=0x7f080021; - public static final int datePicker=0x7f080008; - public static final int exportDataBase=0x7f080004; - public static final int fillOverrideButton=0x7f08001d; - public static final int firstAiderOverride=0x7f08000f; - public static final int firstAiderSpinner=0x7f08000e; - public static final int importButton=0x7f080003; - public static final int interventionOverride=0x7f080019; - public static final int interventionSpinner=0x7f080018; - public static final int medSubSubTypeOverride=0x7f080015; - public static final int medSubSubTypeSpinner=0x7f080014; - public static final int medSubTypeOverride=0x7f080013; - public static final int medSubTypeSpinner=0x7f080012; - public static final int medTypeOverride=0x7f080011; - public static final int medTypeSpinner=0x7f080010; - public static final int nProcess=0x7f080007; - public static final int nSurgery=0x7f080009; - public static final int notesText=0x7f08001b; - public static final int overrideAnesthesia=0x7f08002a; - public static final int overrideCheckBox=0x7f08001c; - public static final int overrideFirstAider=0x7f080028; - public static final int overrideIntervention=0x7f080027; - public static final int overridePatholoty=0x7f080026; - public static final int overridePlace=0x7f080029; - public static final int overrideSubSubType=0x7f080025; - public static final int overrideSubType=0x7f080024; - public static final int overrideType=0x7f080023; - public static final int pager=0x7f080000; - public static final int pager_title_strip=0x7f080001; - public static final int pathologyOverride=0x7f080017; - public static final int pathologySpinner=0x7f080016; - public static final int placeOverride=0x7f08000b; - public static final int placeSpinner=0x7f08000a; - public static final int refreshBtn=0x7f080020; - public static final int saveButton=0x7f08001e; - public static final int section_label=0x7f080005; - public static final int urgencyCheckBox=0x7f08001a; - } - public static final class layout { - public static final int activity_main=0x7f030000; - public static final int fragment_file_operations=0x7f030001; - public static final int fragment_main_dummy=0x7f030002; - public static final int fragment_new_entry=0x7f030003; - public static final int fragment_view_data=0x7f030004; - public static final int multiline_spinner_dropdown_item=0x7f030005; - public static final int override_new_entry=0x7f030006; - } - public static final class menu { - public static final int main=0x7f070000; - } - public static final class string { - public static final int action_settings=0x7f050001; - public static final int anesthesia_str=0x7f05001c; - public static final int app_name=0x7f050000; - public static final int delete_str=0x7f05000c; - public static final int errorMissingProcessNumber_str=0x7f050010; - public static final int exportDataBase_str=0x7f050009; - public static final int exportMessageError_str=0x7f05000f; - public static final int exportMessage_str=0x7f05000e; - public static final int filloverride_str=0x7f050015; - public static final int firstaider_str=0x7f05001b; - public static final int importConfigs_str=0x7f050008; - public static final int intervention_str=0x7f05001a; - public static final int nProcess_str=0x7f050005; - public static final int nSurgery_str=0x7f050006; - public static final int no_str=0x7f050013; - public static final int notes_str=0x7f05001e; - public static final int ok_str=0x7f05000b; - public static final int override_str=0x7f050014; - public static final int pathology_str=0x7f050019; - public static final int place_str=0x7f05001d; - public static final int refresh_str=0x7f05000d; - public static final int save_str=0x7f05000a; - public static final int subsubtype_str=0x7f050018; - public static final int subtype_str=0x7f050017; - public static final int successSavingEntry_str=0x7f050011; - public static final int title_section1=0x7f050002; - public static final int title_section2=0x7f050003; - public static final int title_section3=0x7f050004; - public static final int type_str=0x7f050016; - public static final int urgency_str=0x7f050007; - public static final int yes_str=0x7f050012; - } - public static final class style { - /** - Base application theme, dependent on API level. This theme is replaced - by AppBaseTheme from res/values-vXX/styles.xml on newer devices. - - - Theme customizations available in newer API levels can go in - res/values-vXX/styles.xml, while customizations related to - backward-compatibility can go here. - - - Base application theme for API 11+. This theme completely replaces - AppBaseTheme from res/values/styles.xml on API 11+ devices. - - API 11 theme customizations can go here. - - Base application theme for API 14+. This theme completely replaces - AppBaseTheme from BOTH res/values/styles.xml and - res/values-v11/styles.xml on API 14+ devices. - - API 14 theme customizations can go here. - */ - public static final int AppBaseTheme=0x7f060000; - /** Application theme. - All customizations that are NOT specific to a particular API-level can go here. - */ - public static final int AppTheme=0x7f060001; - } -} diff --git a/old_native_project/ic_launcher-web.png b/old_native_project/ic_launcher-web.png deleted file mode 100755 index e4d20ec..0000000 Binary files a/old_native_project/ic_launcher-web.png and /dev/null differ diff --git a/old_native_project/ic_launcher-web.png.import b/old_native_project/ic_launcher-web.png.import deleted file mode 100644 index f462da2..0000000 --- a/old_native_project/ic_launcher-web.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture" -path="res://.import/ic_launcher-web.png-244ffa8897e9eebe71336a23a9033c01.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://old_native_project/ic_launcher-web.png" -dest_files=[ "res://.import/ic_launcher-web.png-244ffa8897e9eebe71336a23a9033c01.stex" ] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 -compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 -process/fix_alpha_border=true -process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -process/normal_map_invert_y=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 diff --git a/old_native_project/libs/android-support-v4.jar b/old_native_project/libs/android-support-v4.jar deleted file mode 100755 index 96644ed..0000000 Binary files a/old_native_project/libs/android-support-v4.jar and /dev/null differ diff --git a/old_native_project/libs/javacsv.jar b/old_native_project/libs/javacsv.jar deleted file mode 100755 index ceb59eb..0000000 Binary files a/old_native_project/libs/javacsv.jar and /dev/null differ diff --git a/old_native_project/lint.xml b/old_native_project/lint.xml deleted file mode 100755 index ee0eead..0000000 --- a/old_native_project/lint.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/old_native_project/proguard-project.txt b/old_native_project/proguard-project.txt deleted file mode 100755 index f2fe155..0000000 --- a/old_native_project/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/old_native_project/project.properties b/old_native_project/project.properties deleted file mode 100755 index 4ab1256..0000000 --- a/old_native_project/project.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-19 diff --git a/old_native_project/res/drawable-hdpi/ic_launcher.png b/old_native_project/res/drawable-hdpi/ic_launcher.png deleted file mode 100755 index 9ef6cfb..0000000 Binary files a/old_native_project/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/old_native_project/res/drawable-hdpi/ic_launcher.png.import b/old_native_project/res/drawable-hdpi/ic_launcher.png.import deleted file mode 100644 index fb44ccd..0000000 --- a/old_native_project/res/drawable-hdpi/ic_launcher.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture" -path="res://.import/ic_launcher.png-7b75c07f16537d4d1276f02b2da8f046.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://old_native_project/res/drawable-hdpi/ic_launcher.png" -dest_files=[ "res://.import/ic_launcher.png-7b75c07f16537d4d1276f02b2da8f046.stex" ] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 -compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 -process/fix_alpha_border=true -process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -process/normal_map_invert_y=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 diff --git a/old_native_project/res/drawable-mdpi/ic_launcher.png b/old_native_project/res/drawable-mdpi/ic_launcher.png deleted file mode 100755 index 330d0a4..0000000 Binary files a/old_native_project/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/old_native_project/res/drawable-mdpi/ic_launcher.png.import b/old_native_project/res/drawable-mdpi/ic_launcher.png.import deleted file mode 100644 index 3e22a92..0000000 --- a/old_native_project/res/drawable-mdpi/ic_launcher.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture" -path="res://.import/ic_launcher.png-60911ba4a7bacee1ef18c90549959e99.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://old_native_project/res/drawable-mdpi/ic_launcher.png" -dest_files=[ "res://.import/ic_launcher.png-60911ba4a7bacee1ef18c90549959e99.stex" ] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 -compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 -process/fix_alpha_border=true -process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -process/normal_map_invert_y=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 diff --git a/old_native_project/res/drawable-xhdpi/ic_launcher.png b/old_native_project/res/drawable-xhdpi/ic_launcher.png deleted file mode 100755 index e6341a6..0000000 Binary files a/old_native_project/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/old_native_project/res/drawable-xhdpi/ic_launcher.png.import b/old_native_project/res/drawable-xhdpi/ic_launcher.png.import deleted file mode 100644 index 03ba604..0000000 --- a/old_native_project/res/drawable-xhdpi/ic_launcher.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture" -path="res://.import/ic_launcher.png-392be394da50ded53954d6a34405ccd0.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://old_native_project/res/drawable-xhdpi/ic_launcher.png" -dest_files=[ "res://.import/ic_launcher.png-392be394da50ded53954d6a34405ccd0.stex" ] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 -compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 -process/fix_alpha_border=true -process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -process/normal_map_invert_y=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 diff --git a/old_native_project/res/drawable-xxhdpi/ic_launcher.png b/old_native_project/res/drawable-xxhdpi/ic_launcher.png deleted file mode 100755 index 590a40f..0000000 Binary files a/old_native_project/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/old_native_project/res/drawable-xxhdpi/ic_launcher.png.import b/old_native_project/res/drawable-xxhdpi/ic_launcher.png.import deleted file mode 100644 index 562f414..0000000 --- a/old_native_project/res/drawable-xxhdpi/ic_launcher.png.import +++ /dev/null @@ -1,35 +0,0 @@ -[remap] - -importer="texture" -type="StreamTexture" -path="res://.import/ic_launcher.png-d4038f1f519c934c855a1e1587c8d21b.stex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://old_native_project/res/drawable-xxhdpi/ic_launcher.png" -dest_files=[ "res://.import/ic_launcher.png-d4038f1f519c934c855a1e1587c8d21b.stex" ] - -[params] - -compress/mode=0 -compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 -compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 -process/fix_alpha_border=true -process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -process/normal_map_invert_y=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 diff --git a/old_native_project/res/layout/activity_main.xml b/old_native_project/res/layout/activity_main.xml deleted file mode 100755 index 6cfef6f..0000000 --- a/old_native_project/res/layout/activity_main.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - diff --git a/old_native_project/res/layout/fragment_file_operations.xml b/old_native_project/res/layout/fragment_file_operations.xml deleted file mode 100755 index 2703afb..0000000 --- a/old_native_project/res/layout/fragment_file_operations.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - -