Files
starruler-linux/scripts/toolkit/elements/GuiFileChooser.as
T
2018-07-17 14:15:37 +02:00

367 lines
8.9 KiB
ActionScript

import elements.BaseGuiElement;
import elements.GuiListbox;
import elements.GuiText;
import elements.GuiTextbox;
import elements.GuiButton;
import dialogs.QuestionDialog;
import dialogs.InputDialog;
export ChooseFileMode, GuiFileChooser;
enum ChooseFileMode {
CFM_Filename,
CFM_Single,
CFM_Multiple,
};
enum FileType {
FT_Other,
FT_Design,
FT_Directory,
FT_Back,
};
class FileChooserElement : GuiListElement {
string path;
string extension;
FileType type;
FileChooserElement() {
path = "../";
type = FT_Back;
}
FileChooserElement(FileList@ flist, uint num) {
path = flist.basename[num];
if(flist.isDirectory[num]) {
type = FT_Directory;
path += "/";
}
else {
extension = flist.extension[num];
if(extension == "design")
type = FT_Design;
else
type = FT_Other;
}
}
void draw(GuiListbox@ ele, uint flags, const recti& absPos) override {
const Font@ font = ele.skin.getFont(ele.TextFont);
int baseLine = font.getBaseline();
vec2i textOffset(ele.horizPadding + 24, (ele.lineHeight - baseLine) / 2);
if(ele.itemStyle == SS_NULL)
ele.skin.draw(SS_ListboxItem, flags, absPos);
spritesheet::FileIcons.draw(type, recti_area(absPos.topLeft + vec2i(ele.horizPadding, 2), vec2i(20, 20)));
font.draw(absPos.topLeft + textOffset, path);
}
};
class FileChooserConfirm : QuestionDialogCallback {
GuiFileChooser@ chooser;
FileChooserConfirm(GuiFileChooser@ Chooser) {
@chooser = Chooser;
}
void questionCallback(QuestionDialog@ dialog, int answer) {
if(answer == QA_Yes)
chooser.emitConfirmed();
}
};
class FileChooserConfirmDelete : QuestionDialogCallback {
GuiFileChooser@ chooser;
FileChooserConfirmDelete(GuiFileChooser@ Chooser) {
@chooser = Chooser;
}
void questionCallback(QuestionDialog@ dialog, int answer) {
if(answer == QA_Yes)
chooser.deleteFiles();
}
};
class FileChooserConfirmMkdir : InputDialogCallback {
GuiFileChooser@ chooser;
FileChooserConfirmMkdir(GuiFileChooser@ Chooser) {
@chooser = Chooser;
}
void inputCallback(InputDialog@ dialog, bool accepted) {
if(!accepted)
return;
makeDirectory(chooser.realPath(dialog.getTextInput(0)));
chooser.updateFiles();
}
};
class GuiFileChooser : BaseGuiElement {
string filter = "*";
string root;
string current;
ChooseFileMode mode;
bool PromptOverwrite = true;
GuiListbox@ list;
FileList flist;
GuiText@ label;
GuiTextbox@ filename;
GuiButton@ confirm;
GuiButton@ deleteButton;
GuiButton@ mkdirButton;
GuiFileChooser(IGuiElement@ Parent, Alignment@ align, const string& Root, const string&in Initial, ChooseFileMode Mode, bool Management = true) {
super(Parent, align);
_GuiFileChooser(Root, Initial, Mode, Management);
}
GuiFileChooser(IGuiElement@ Parent, const recti& pos, const string&in Root, const string&in Initial, ChooseFileMode Mode, bool Management = true) {
super(Parent, pos);
_GuiFileChooser(Root, Initial, Mode, Management);
}
void _GuiFileChooser(const string& Root, const string&in Initial, ChooseFileMode Mode, bool Management) {
root = Root;
current = Initial;
mode = Mode;
if(mode == CFM_Filename) {
@list = GuiListbox(this, Alignment(Left, Top+(Management ? 26 : 0), Right, Bottom-28));
@label = GuiText(this, Alignment(Left+4, Bottom-24, Left+0.25f, Bottom-2), locale::FILENAME_LABEL);
@filename = GuiTextbox(this, Alignment(Left+0.25f+4, Bottom-24, Left+0.75f, Bottom-2));
@confirm = GuiButton(this, Alignment(Left+0.75f+4, Bottom-24, Right, Bottom-2), locale::SAVE);
}
else {
@list = GuiListbox(this, Alignment(Left, Top+(Management ? 26 : 0), Right, Bottom));
if(mode == CFM_Multiple)
list.multiple = true;
}
list.DblClickConfirm = true;
list.autoMultiple = false;
list.itemHeight = 24;
if(Management) {
@deleteButton = GuiButton(this, Alignment(Left, Top, Left+0.2f, Top+22), locale::DELETE);
deleteButton.disabled = true;
@mkdirButton = GuiButton(this, Alignment(Right-0.3f, Top, Right, Top+22), locale::NEW_DIRECTORY);
}
updateFiles();
updateAbsolutePosition();
}
string realPath(string file) {
return path_join(path_join(root, current), file);
}
void deleteFiles() {
uint cnt = list.itemCount;
for(uint i = 0; i < cnt; ++i) {
if(!list.isSelected(i))
continue;
FileChooserElement@ elem = cast<FileChooserElement>(list.getItemElement(i));
if(elem is null || elem.type == FT_Back)
continue;
deleteFile(realPath(elem.path));
}
updateFiles();
}
void updateFiles() {
//Navigate to new directory
string dir = path_join(root, current);
flist.navigate(dir, filter);
//Fill file list
list.clearItems();
if(current.length != 0)
list.addItem(FileChooserElement());
uint cnt = flist.length;
for(uint i = 0; i < cnt; ++i)
if(flist.isDirectory[i])
list.addItem(FileChooserElement(flist, i));
for(uint i = 0; i < cnt; ++i)
if(!flist.isDirectory[i])
list.addItem(FileChooserElement(flist, i));
}
uint get_selectedCount() {
return list.selectedCount;
}
void getSelectedFiles(array<string>@ output, bool fullPath = true) {
uint cnt = list.itemCount;
for(uint i = 0; i < cnt; ++i) {
if(!list.isSelected(i))
continue;
FileChooserElement@ elem = cast<FileChooserElement>(list.getItemElement(i));
if(elem is null)
continue;
if(elem.type == FT_Directory || elem.type == FT_Back)
continue;
if(fullPath)
output.insertLast(path_join(path_join(root, current), elem.path));
else
output.insertLast(path_join(current, elem.path));
}
}
string getSelectedPath(bool fullPath = true) {
string fname;
if(filename !is null) {
fname = filename.text;
if(fname.length == 0)
return fname;
}
else {
if(list.selectedCount == 0)
return "";
fname = cast<FileChooserElement>(list.selectedItem).path;
}
if(fullPath)
return path_join(path_join(root, current), fname);
else
return path_join(current, fname);
}
string get_selectedFilename() {
return filename.text;
}
void set_selectedFilename(string fname) {
filename.text = fname;
}
void clickConfirm() {
if(mode == CFM_Filename && PromptOverwrite) {
string path = getSelectedPath(true);
if(path.length != 0 && fileExists(path)) {
string basepath = getSelectedPath(false);
string text = format(locale::CONFIRM_OVERWRITE, basepath);
question(text, locale::OVERWRITE, locale::CANCEL, FileChooserConfirm(this));
}
else {
emitConfirmed();
}
}
else {
emitConfirmed();
}
}
void promptMkdir() {
InputDialog@ dialog = InputDialog(FileChooserConfirmMkdir(this), this);
dialog.accept.text = locale::CREATE_DIRECTORY;
dialog.addTextInput(locale::DIRECTORY_LABEL, "");
addDialog(dialog);
dialog.focusInput();
}
void promptDelete() {
if(selectedCount == 0)
return;
string text = locale::CONFIRM_DELETE_FILES+"\n";
uint cnt = list.itemCount;
for(uint i = 0; i < cnt; ++i) {
if(!list.isSelected(i))
continue;
FileChooserElement@ elem = cast<FileChooserElement>(list.getItemElement(i));
if(elem is null || elem.type == FT_Back)
continue;
text += "\n"+elem.path;
}
question(text, locale::DELETE, locale::CANCEL, FileChooserConfirmDelete(this));
}
bool onKeyEvent(const KeyboardEvent& event, IGuiElement@ source) {
switch(event.type) {
case KET_Key_Down:
if(event.key == KEY_DEL) {
return true;
}
break;
case KET_Key_Up:
if(event.key == KEY_DEL) {
promptDelete();
return true;
}
break;
}
if(source !is list && !source.isChildOf(list))
return list.onKeyEvent(event, list);
else
return BaseGuiElement::onKeyEvent(event, source);
}
bool onGuiEvent(const GuiEvent& event) {
if(event.caller is list) {
switch(event.type) {
case GUI_Changed:
if(mode == CFM_Filename) {
FileChooserElement@ elem = cast<FileChooserElement>(list.selectedItem);
if(elem is null || elem.type == FT_Directory || elem.type == FT_Back)
return true;
filename.text = elem.path;
}
deleteButton.disabled = list.selectedCount == 0;
emitChanged();
break;
case GUI_Confirmed: {
FileChooserElement@ elem = cast<FileChooserElement>(list.getItemElement(event.value));
if(elem is null)
return true;
if(elem.type == FT_Back) {
if(current.length != 0) {
current = path_up(current);
updateFiles();
}
return true;
}
else if(elem.type == FT_Directory) {
current = path_join(current, elem.path);
updateFiles();
return true;
}
else {
clickConfirm();
return true;
}
}
}
}
else if(event.type == GUI_Clicked) {
if(event.caller is confirm) {
clickConfirm();
return true;
}
else if(event.caller is deleteButton) {
promptDelete();
return true;
}
else if(event.caller is mkdirButton) {
promptMkdir();
return true;
}
}
else if(event.caller is filename) {
if(event.type == GUI_Confirmed) {
clickConfirm();
return true;
}
}
return BaseGuiElement::onGuiEvent(event);
}
};