1 /** 2 Grimoire 3 Copyright (c) 2017 Enalye 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising 7 from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute 11 it freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; 14 you must not claim that you wrote the original software. 15 If you use this software in a product, an acknowledgment 16 in the product documentation would be appreciated but 17 is not required. 18 19 2. Altered source versions must be plainly marked as such, 20 and must not be misrepresented as being the original software. 21 22 3. This notice may not be removed or altered from any source distribution. 23 */ 24 25 module ui.save; 26 27 import std.file; 28 import std.path; 29 import std.conv: to; 30 31 import core.all; 32 import common.all; 33 34 import ui.widget; 35 import ui.modal; 36 import ui.button; 37 import ui.list.vlist; 38 import ui.inputfield; 39 40 private { 41 InStream _loadedStream = null; 42 } 43 44 void setSaveWindow(Widget callbackWidget, string callbackId, OutStream stream, string path, string extension) { 45 path = buildNormalizedPath(absolutePath(path)); 46 if(!extension.length) 47 throw new Exception("Cannot save without a file extension"); 48 auto modal = new SaveWindow(stream, path, extension); 49 modal.setCallback(callbackWidget, callbackId); 50 setModalWindow(modal); 51 } 52 53 void setLoadWindow(Widget callbackWidget, string callbackId, string path, string extension) { 54 InStream stream = new InStream; 55 path = buildNormalizedPath(absolutePath(path)); 56 if(!extension.length) 57 throw new Exception("Cannot save without a file extension"); 58 auto modal = new LoadWindow(stream, path, extension); 59 modal.setCallback(callbackWidget, callbackId); 60 _loadedStream = null; 61 setModalWindow(modal); 62 } 63 64 InStream getLoadedStream() { 65 return _loadedStream; 66 } 67 68 class SaveWindow: ModalWindow { 69 private { 70 OutStream _stream; 71 string _path, _extension; 72 InputField _inputField; 73 } 74 75 this(OutStream stream, string path, string extension) { 76 super("Saving", Vec2f(250f, 25f)); 77 _stream = stream; 78 _path = path; 79 _extension = extension; 80 _inputField = new InputField(layout.size, "Sans Titre", true); 81 layout.addChild(_inputField); 82 } 83 84 override void onEvent(Event event) { 85 super.onEvent(event); 86 if(event.type == EventType.Callback) { 87 if(event.id == "apply") { 88 string fullPath = buildPath(_path, setExtension(_inputField.text, _extension)); 89 if(!isValidPath(fullPath)) 90 throw new Exception("Error saving file: invalid path \'" ~ fullPath ~ "\'"); 91 write(fullPath, _stream.data); 92 triggerCallback(); 93 } 94 } 95 } 96 97 override void update(float deltaTime) { 98 super.update(deltaTime); 99 applyBtn.isLocked = (_inputField.text.length == 0L); 100 } 101 } 102 103 class LoadWindow: ModalWindow { 104 private { 105 InStream _stream; 106 string[] _files; 107 VList _list; 108 } 109 110 this(InStream stream, string path, string extension) { 111 super("Loading", Vec2f(250f, 200f)); 112 _stream = stream; 113 _list = new VList(layout.size); 114 foreach(file; dirEntries(path, "*." ~ extension, SpanMode.depth)) { 115 _files ~= file; 116 string relativeFileName = stripExtension(baseName(file)); 117 auto btn = new TextButton(relativeFileName); 118 _list.addChild(btn); 119 } 120 layout.addChild(_list); 121 } 122 123 override void onEvent(Event event) { 124 super.onEvent(event); 125 126 if(event.type == EventType.Callback) { 127 if(event.id == "apply") { 128 if(_list.selected < _files.length) { 129 string fileName = _files[_list.selected]; 130 if(!exists(fileName)) 131 throw new Exception("Error saving file: invalid path \'" ~ fileName ~ "\'"); 132 _stream.set(cast(ubyte[])(read(fileName))); 133 if(_stream.length) 134 _loadedStream = _stream; 135 else 136 _loadedStream = null; 137 triggerCallback(); 138 } 139 } 140 } 141 } 142 143 override void update(float deltaTime) { 144 super.update(deltaTime); 145 applyBtn.isLocked = (_files.length == 0L); 146 } 147 }