Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiText;
|
||||
import elements.GuiTextbox;
|
||||
import elements.GuiSpinbox;
|
||||
import elements.GuiScrollbar;
|
||||
|
||||
interface ColorDialogCallback {
|
||||
void colorChosen(Color col);
|
||||
};
|
||||
|
||||
class ColorPicker : BaseGuiElement {
|
||||
float hue = 1.f, sat = 1.f, value = 1.f, alpha = 1.f;
|
||||
Color picked;
|
||||
bool pressed = false;
|
||||
|
||||
ColorPicker(IGuiElement@ parent, const recti& pos) {
|
||||
super(parent, pos);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
shader::HSV_VALUE = value;
|
||||
shader::HSV_SAT_START = 0.f;
|
||||
shader::HSV_SAT_END = 1.f;
|
||||
drawRectangle(AbsolutePosition, material::HSVPalette, Color());
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
|
||||
Color get_color() const {
|
||||
Colorf col;
|
||||
col.fromHSV(hue, sat, value);
|
||||
col.a = alpha;
|
||||
return Color(col);
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
||||
if(event.type == MET_Button_Down || (event.type == MET_Moved && pressed)) {
|
||||
pressed = true;
|
||||
hue = float(event.x - AbsolutePosition.topLeft.x);
|
||||
sat = 1.f - float(event.y - AbsolutePosition.topLeft.y) / float(AbsolutePosition.height);
|
||||
|
||||
picked = color;
|
||||
|
||||
GuiEvent evt;
|
||||
@evt.caller = this;
|
||||
evt.type = GUI_Changed;
|
||||
onGuiEvent(evt);
|
||||
return true;
|
||||
}
|
||||
else if(pressed && event.type == MET_Button_Up) {
|
||||
pressed = false;
|
||||
return true;
|
||||
}
|
||||
return BaseGuiElement::onMouseEvent(event, source);
|
||||
}
|
||||
};
|
||||
|
||||
class ColorBox : BaseGuiElement {
|
||||
Color color;
|
||||
|
||||
ColorBox(IGuiElement@ parent, const recti& pos) {
|
||||
super(parent, pos);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
drawRectangle(AbsolutePosition, color);
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
|
||||
class ColorDialog : Dialog {
|
||||
ColorDialogCallback@ callback;
|
||||
ColorPicker@ picker;
|
||||
GuiScrollbar@ value;
|
||||
ColorBox@ display;
|
||||
|
||||
GuiButton@ accept;
|
||||
|
||||
GuiSpinbox@ r, g, b, a;
|
||||
|
||||
ColorDialog(ColorDialogCallback@ CB, IGuiElement@ bind, Color startCol = Color()) {
|
||||
@callback = CB;
|
||||
super(bind);
|
||||
height = 330;
|
||||
width = 480;
|
||||
|
||||
@picker = ColorPicker(window, recti_area(vec2i(6,6), vec2i(360,256)));
|
||||
@accept = GuiButton(window, recti(400, 300, 476, 326), locale::ACCEPT);
|
||||
@value = GuiScrollbar(window, recti(370, 6, 396, 280));
|
||||
value.page = 0;
|
||||
value.scroll = 5.f / 255.f;
|
||||
|
||||
@r = GuiSpinbox(window, recti(400, 6, 450, 32), 0, 0, 255, 5, 0);
|
||||
@b = GuiSpinbox(window, recti(400, 36, 450, 62), 0, 0, 255, 5, 0);
|
||||
@g = GuiSpinbox(window, recti(400, 66, 450, 92), 0, 0, 255, 5, 0);
|
||||
@a = GuiSpinbox(window, recti(400, 96, 450, 122), 0, 0, 255, 5, 0);
|
||||
@display = ColorBox(window, recti(400, 126, 450, 152));
|
||||
|
||||
color = startCol;
|
||||
addDialog(this);
|
||||
}
|
||||
|
||||
void set_color(Color col) {
|
||||
syncBoxColor(col);
|
||||
syncRegionColor(col);
|
||||
}
|
||||
|
||||
void syncBoxColor(Color col) {
|
||||
r.value = col.r;
|
||||
g.value = col.g;
|
||||
b.value = col.b;
|
||||
a.value = col.a;
|
||||
col.a = 255;
|
||||
display.color = col;
|
||||
}
|
||||
|
||||
void syncRegionColor(Color col) {
|
||||
Colorf hsv = Colorf(col);
|
||||
|
||||
value.pos = 1.f - hsv.value;
|
||||
picker.value = 1.f - value.pos;
|
||||
picker.hue = hsv.hue;
|
||||
picker.sat = hsv.saturation;
|
||||
picker.alpha = hsv.a;
|
||||
|
||||
col.a = 255;
|
||||
display.color = col;
|
||||
}
|
||||
|
||||
Color get_color() const {
|
||||
Color col;
|
||||
col.r = min(uint(r.value), 255);
|
||||
col.g = min(uint(g.value), 255);
|
||||
col.b = min(uint(b.value), 255);
|
||||
col.a = min(uint(a.value), 255);
|
||||
return col;
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(Closed)
|
||||
return false;
|
||||
if(event.type == GUI_Clicked) {
|
||||
if(event.caller is accept) {
|
||||
if(callback !is null)
|
||||
callback.colorChosen(color);
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(event.type == GUI_Changed) {
|
||||
if(event.caller is picker) {
|
||||
syncBoxColor(picker.picked);
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is value) {
|
||||
picker.value = 1.f - value.pos;
|
||||
syncBoxColor(picker.color);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
syncRegionColor(color);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) override {
|
||||
if(Closed)
|
||||
return false;
|
||||
if(event.type == MET_Scrolled && source is picker)
|
||||
return value.onMouseEvent(event, value);
|
||||
return Dialog::onMouseEvent(event, source);;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
#section disable menu
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiFileChooser;
|
||||
import util.design_export;
|
||||
|
||||
class DesignExportDialog : Dialog {
|
||||
const Design@ dsg;
|
||||
const DesignClass@ targetClass;
|
||||
GuiFileChooser@ chooser;
|
||||
|
||||
DesignExportDialog(const Design@ Dsg, const DesignClass@ Cls, IGuiElement@ bind) {
|
||||
super(bind);
|
||||
addTitle(locale::EXPORT_DESIGN);
|
||||
|
||||
@dsg = Dsg;
|
||||
@targetClass = Cls;
|
||||
@window.callback = this;
|
||||
|
||||
@chooser = GuiFileChooser(window, Alignment(Left+12, Top+38, Right-12, Bottom-12), modProfile["designs"], "", CFM_Filename);
|
||||
chooser.selectedFilename = dsg.name + ".design";
|
||||
|
||||
height = 500;
|
||||
}
|
||||
|
||||
void focus() {
|
||||
Dialog::focus();
|
||||
chooser.filename.focus(true);
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
void clickConfirm() {
|
||||
write_design(dsg, chooser.getSelectedPath(true), targetClass);
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.caller is chooser && event.type == GUI_Confirmed) {
|
||||
clickConfirm();
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
DesignExportDialog@ exportDesign(const Design@ dsg, const DesignClass@ cls, IGuiElement@ bind = null) {
|
||||
DesignExportDialog dlg(dsg, cls, bind);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
#section disable menu
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiFileChooser;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiText;
|
||||
import elements.GuiDropdown;
|
||||
import dialogs.MessageDialog;
|
||||
import util.design_export;
|
||||
|
||||
class DesignImportDialog : Dialog {
|
||||
GuiFileChooser@ chooser;
|
||||
GuiText@ label;
|
||||
GuiDropdown@ classList;
|
||||
GuiButton@ confirm;
|
||||
|
||||
DesignImportDialog(IGuiElement@ bind) {
|
||||
super(bind);
|
||||
addTitle(locale::IMPORT_DESIGNS);
|
||||
|
||||
@chooser = GuiFileChooser(window, Alignment(Left+12, Top+38, Right-12, Bottom-38),
|
||||
modProfile["designs"], "", CFM_Multiple);
|
||||
chooser.list.autoMultiple = true;
|
||||
|
||||
@label = GuiText(window, Alignment(Left+16, Bottom-34, Left+0.35f, Bottom-12), locale::IMPORT_INTO_CLASS);
|
||||
|
||||
@classList = GuiDropdown(window, Alignment(Left+0.35f+4, Bottom-34, Left+0.8f, Bottom-12));
|
||||
classList.addItem(locale::SAVED_CLASS);
|
||||
|
||||
uint cnt = playerEmpire.designClassCount;
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
classList.addItem(playerEmpire.getDesignClass(i).name);
|
||||
|
||||
@confirm = GuiButton(window, Alignment(Left+0.8f+4, Bottom-34, Right-12, Bottom-12), locale::IMPORT);
|
||||
height = 500;
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
bool showDesign(const Design@ dsg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void clickConfirm() {
|
||||
const DesignClass@ inClass;
|
||||
if(classList.selected > 0)
|
||||
@inClass = playerEmpire.getDesignClass(classList.selected - 1);
|
||||
|
||||
string errors;
|
||||
bool hasErrors = false;
|
||||
const Design@ errDesign;
|
||||
|
||||
array<string> selected;
|
||||
chooser.getSelectedFiles(selected, true);
|
||||
for(uint i = 0, cnt = selected.length; i < cnt; ++i) {
|
||||
DesignDescriptor desc;
|
||||
string fname = getBasename(selected[i]);
|
||||
if(!read_design(selected[i], desc)) {
|
||||
errors += "\n"+fname+":\n - ";
|
||||
errors += locale::ERROR_INVALID_FILE+"\n";
|
||||
hasErrors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Report design renames
|
||||
const Design@ prevDesign = playerEmpire.getDesign(desc.name);
|
||||
if(prevDesign !is null && !prevDesign.obsolete) {
|
||||
errors += "\n"+fname+":\n - ";
|
||||
desc.name = uniqueDesignName(desc.name, playerEmpire);
|
||||
errors += format(locale::ERROR_DUPLICATE_DESIGN, desc.name);
|
||||
errors += "\n";
|
||||
hasErrors = true;
|
||||
@prevDesign = null;
|
||||
}
|
||||
|
||||
//Report all design errors
|
||||
@desc.hull = getBestHull(desc, getHullTypeTag(desc.hull));
|
||||
const Design@ dsg = makeDesign(desc);
|
||||
if(dsg.hasFatalErrors()) {
|
||||
uint errCnt = dsg.errorCount;
|
||||
errors += "\n"+fname+":\n";
|
||||
for(uint j = 0; j < errCnt; ++j)
|
||||
errors += " - "+dsg.errors[j].text+"\n";
|
||||
hasErrors = true;
|
||||
@errDesign = dsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(desc.settings !is null)
|
||||
dsg.setSettings(desc.settings);
|
||||
|
||||
const DesignClass@ cls = inClass;
|
||||
if(cls is null && desc.className.length != 0)
|
||||
@cls = playerEmpire.getDesignClass(desc.className);
|
||||
if(cls is null)
|
||||
@cls = playerEmpire.getDesignClass(locale::DOWNLOAD_DESIGN_CLASS, true);
|
||||
if(prevDesign !is null)
|
||||
playerEmpire.changeDesign(prevDesign, dsg, cls);
|
||||
else
|
||||
playerEmpire.addDesign(cls, dsg);
|
||||
}
|
||||
|
||||
//Report errors
|
||||
if(hasErrors) {
|
||||
if(selected.length == 1 && errDesign !is null) {
|
||||
if(showDesign(errDesign))
|
||||
return;
|
||||
}
|
||||
message(locale::IMPORT_ERRORS + "\n" + errors, null, elem);
|
||||
}
|
||||
}
|
||||
|
||||
void confirmDialog() {
|
||||
clickConfirm();
|
||||
close();
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.caller is chooser && event.type == GUI_Confirmed) {
|
||||
clickConfirm();
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
if(event.caller is confirm && event.type == GUI_Clicked) {
|
||||
clickConfirm();
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
DesignImportDialog@ importDesigns(IGuiElement@ bind = null) {
|
||||
DesignImportDialog dlg(bind);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import elements.BaseGuiElement;
|
||||
import elements.GuiDraggable;
|
||||
import elements.GuiSkinElement;
|
||||
import elements.GuiText;
|
||||
import elements.GuiButton;
|
||||
import dialogs.IDialog;
|
||||
from gui import navigateInto;
|
||||
|
||||
from dialog import addDialog, closeDialog, closeDialogs;
|
||||
|
||||
const int DIALOG_BUTTON_HEIGHT = 32;
|
||||
const int DIALOG_PADDING = 7;
|
||||
const int DIALOG_BUTTON_ROW = DIALOG_BUTTON_HEIGHT + DIALOG_PADDING;
|
||||
const Color DIALOG_TITLE_COLOR(0x00bffeff);
|
||||
|
||||
class Dialog : IDialog, IGuiCallback {
|
||||
bool Closed;
|
||||
IGuiElement@ elem;
|
||||
IGuiElement@ lastFocus;
|
||||
GuiSkinElement@ bg;
|
||||
BaseGuiElement@ window;
|
||||
GuiSkinElement@ titleBox;
|
||||
GuiText@ titleText;
|
||||
GuiButton@ closeBtn;
|
||||
|
||||
int height;
|
||||
int width;
|
||||
|
||||
Dialog(IGuiElement@ bind, bool bindInside = false) {
|
||||
Closed = false;
|
||||
@elem = bind;
|
||||
width = 500;
|
||||
height = 38+DIALOG_PADDING;
|
||||
|
||||
@lastFocus = getGuiFocus();
|
||||
@window = GuiDraggable(bindInside ? bind : null, recti());
|
||||
@window.callback = this;
|
||||
|
||||
@bg = GuiSkinElement(window, Alignment_Fill(), SS_Dialog);
|
||||
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void addTitle(const string& title, FontType font = FT_Bold, bool closeButton = true, const Color& color = Color(0x00bffeff)) {
|
||||
if(titleBox is null)
|
||||
@titleBox = GuiSkinElement(window, recti_area(vec2i(1, 1), vec2i(width-3, 26)), SS_WindowTitle);
|
||||
else
|
||||
titleBox.size = vec2i(width-3, 26);
|
||||
if(titleText is null) {
|
||||
@titleText = GuiText(window, recti_area(vec2i(8, 4), vec2i(width-16, 22)));
|
||||
titleText.font = font;
|
||||
height += 26;
|
||||
}
|
||||
|
||||
titleBox.color = color;
|
||||
titleText.text = title;
|
||||
|
||||
if(closeButton && closeBtn is null) {
|
||||
vec2i size = window.skin.getSize(SS_GameTabClose, SF_Normal);
|
||||
int off = (26 - size.y) / 2 + 1;
|
||||
@closeBtn = GuiButton(window, Alignment(Right-off-size.x, Top+off, Width=size.x, Height=size.y));
|
||||
closeBtn.style = SS_GameTabClose;
|
||||
}
|
||||
}
|
||||
|
||||
void set_titleColor(const Color& color) {
|
||||
if(titleBox !is null)
|
||||
titleBox.color = color;
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onKeyEvent(const KeyboardEvent& event, IGuiElement@ source) {
|
||||
switch(event.type) {
|
||||
case KET_Key_Down:
|
||||
if(event.key == KEY_ESC) {
|
||||
return true;
|
||||
}
|
||||
else if(event.key == KEY_ENTER) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case KET_Key_Up:
|
||||
if(event.key == KEY_ESC) {
|
||||
cancelDialog();
|
||||
return true;
|
||||
}
|
||||
else if(event.key == KEY_ENTER) {
|
||||
confirmDialog();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.caller is closeBtn && event.type == GUI_Clicked) {
|
||||
cancelDialog();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void set_position(const vec2i& pos) {
|
||||
window.position = pos;
|
||||
}
|
||||
|
||||
void updatePosition() {
|
||||
recti pos;
|
||||
if(elem is null)
|
||||
pos = recti(vec2i(), screenSize);
|
||||
else
|
||||
pos = elem.absolutePosition;
|
||||
pos = recti_centered(pos, vec2i(width, height));
|
||||
|
||||
if(titleBox !is null)
|
||||
titleBox.size = vec2i(width-3, 26);
|
||||
window.position = pos.topLeft;
|
||||
window.size = pos.size;
|
||||
window.updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void focus() {
|
||||
window.bringToFront();
|
||||
navigateInto(window);
|
||||
}
|
||||
|
||||
void cancelDialog() {
|
||||
close();
|
||||
}
|
||||
|
||||
void confirmDialog() {
|
||||
window.emitConfirmed();
|
||||
}
|
||||
|
||||
void close() {
|
||||
Closed = true;
|
||||
window.remove();
|
||||
setGuiFocus(lastFocus);
|
||||
}
|
||||
|
||||
bool get_closed() {
|
||||
return Closed;
|
||||
}
|
||||
|
||||
IGuiElement@ get_bound() {
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
|
||||
void alignAcceptButtons(BaseGuiElement@ accept, BaseGuiElement@ cancel) {
|
||||
if(isWindows) {
|
||||
//Legacy OS support
|
||||
@accept.alignment = Alignment(Left+0.2f+12, Bottom-0.0f-DIALOG_BUTTON_ROW, Left+0.5f-6, Bottom-0.0f-DIALOG_PADDING);
|
||||
|
||||
@cancel.alignment = Alignment(Right-0.5f+6, Bottom-0.0f-DIALOG_BUTTON_ROW, Right-0.2f-12, Bottom-0.0f-DIALOG_PADDING);
|
||||
}
|
||||
else {
|
||||
@accept.alignment = Alignment(Right-0.3f, Bottom-0.0f-DIALOG_BUTTON_ROW, Right-0.0f-DIALOG_PADDING, Bottom-0.0f-DIALOG_PADDING);
|
||||
|
||||
@cancel.alignment = Alignment(Right-0.6f, Bottom-0.0f-DIALOG_BUTTON_ROW, Right-0.3f-DIALOG_PADDING, Bottom-0.0f-DIALOG_PADDING);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import elements.IGuiElement;
|
||||
|
||||
interface IDialog {
|
||||
void set_position(const vec2i& pos);
|
||||
void updatePosition();
|
||||
void close();
|
||||
void focus();
|
||||
bool get_closed();
|
||||
IGuiElement@ get_bound();
|
||||
};
|
||||
@@ -0,0 +1,292 @@
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiText;
|
||||
import elements.GuiTextbox;
|
||||
import elements.GuiCheckbox;
|
||||
import elements.GuiDropdown;
|
||||
import elements.GuiSpinbox;
|
||||
|
||||
const int INPUT_LINE_HEIGHT = 26;
|
||||
|
||||
interface IInputDialogCallback {
|
||||
void inputCallback(InputDialog@ dialog, bool accepted);
|
||||
void changeCallback(InputDialog@ dialog);
|
||||
};
|
||||
|
||||
class InputDialogCallback : IInputDialogCallback {
|
||||
void inputCallback(InputDialog@ dialog, bool accepted) {
|
||||
}
|
||||
|
||||
void changeCallback(InputDialog@ dialog) {
|
||||
}
|
||||
};
|
||||
|
||||
class InputDialog : Dialog {
|
||||
IInputDialogCallback@ callback;
|
||||
BaseGuiElement@[] inputs;
|
||||
GuiButton@ accept;
|
||||
GuiButton@ cancel;
|
||||
int curPos;
|
||||
|
||||
InputDialog(IInputDialogCallback@ CB, IGuiElement@ bind) {
|
||||
@callback = CB;
|
||||
curPos = DIALOG_PADDING;
|
||||
super(bind);
|
||||
|
||||
Dialog::addTitle("", FT_Bold);
|
||||
curPos += 26;
|
||||
|
||||
@accept = GuiButton(bg, recti());
|
||||
accept.text = locale::ACCEPT;
|
||||
accept.tabIndex = 100;
|
||||
@accept.callback = this;
|
||||
|
||||
@cancel = GuiButton(bg, recti());
|
||||
cancel.text = locale::CANCEL;
|
||||
cancel.tabIndex = 101;
|
||||
@cancel.callback = this;
|
||||
|
||||
alignAcceptButtons(accept, cancel);
|
||||
}
|
||||
|
||||
uint get_inputCount() {
|
||||
return inputs.length;
|
||||
}
|
||||
|
||||
void focus() {
|
||||
Dialog::focus();
|
||||
focusInput();
|
||||
}
|
||||
|
||||
//**Generic functions for adding lines
|
||||
void addLine(BaseGuiElement& label, int h = INPUT_LINE_HEIGHT) {
|
||||
@label.parent = window;
|
||||
@label.alignment = Alignment(Left+12, Top+curPos, Right-12, Top+curPos + h);
|
||||
|
||||
curPos += h + 6;
|
||||
height += h + 6;
|
||||
}
|
||||
|
||||
int addInput(BaseGuiElement& input, int h = INPUT_LINE_HEIGHT) {
|
||||
@input.parent = window;
|
||||
@input.alignment = Alignment(Left+12, Top+curPos, Right-12, Top+curPos + h);
|
||||
input.tabIndex = inputs.length();
|
||||
|
||||
curPos += h + 6;
|
||||
height += h + 6;
|
||||
inputs.insertLast(input);
|
||||
return inputs.length() - 1;
|
||||
}
|
||||
|
||||
int addInput(BaseGuiElement@ label, BaseGuiElement& input, int h = INPUT_LINE_HEIGHT) {
|
||||
if(label !is null) {
|
||||
@label.parent = window;
|
||||
@label.alignment = Alignment(Left+12, Top+curPos, Left+0.3f-6, Top+curPos + h);
|
||||
}
|
||||
|
||||
@input.parent = window;
|
||||
@input.alignment = Alignment(Left+0.3f+6, Top+curPos, Right-12, Top+curPos + h);
|
||||
input.tabIndex = inputs.length;
|
||||
|
||||
curPos += h + 6;
|
||||
height += h + 6;
|
||||
inputs.insertLast(input);
|
||||
return inputs.length - 1;
|
||||
}
|
||||
|
||||
BaseGuiElement@ getInput(int num) {
|
||||
return inputs[num];
|
||||
}
|
||||
|
||||
void focusInput(uint num = 0) {
|
||||
if(num < inputs.length) {
|
||||
setGuiFocus(inputs[num]);
|
||||
}
|
||||
else {
|
||||
setGuiFocus(null);
|
||||
}
|
||||
}
|
||||
|
||||
//**Text label lines
|
||||
void addTitle(const string& title, FontType font = FT_Bold, bool closeButton = true, const Color& color = DIALOG_TITLE_COLOR) {
|
||||
titleText.text = title;
|
||||
titleText.font = font;
|
||||
titleBox.color = color;
|
||||
}
|
||||
|
||||
int addLabel(const string& label, FontType font = FT_Normal, double align = 0.0, bool register = false) {
|
||||
GuiText@ txt = GuiText(null, recti(), label);
|
||||
@txt.parent = window;
|
||||
@txt.alignment = Alignment(Left+12, Top+curPos, Right-12, Top+curPos + INPUT_LINE_HEIGHT);
|
||||
txt.font = font;
|
||||
txt.horizAlign = align;
|
||||
txt.wordWrap = true;
|
||||
|
||||
int h = txt.getTextDimension().height;
|
||||
h += (INPUT_LINE_HEIGHT - txt.skin.getFont(txt.font).getLineHeight());
|
||||
if(h != INPUT_LINE_HEIGHT) {
|
||||
@txt.alignment = Alignment(Left+12, Top+curPos, Right-12, Top+curPos + h);
|
||||
}
|
||||
|
||||
curPos += h + 6;
|
||||
height += h + 6;
|
||||
|
||||
if(register) {
|
||||
inputs.insertLast(txt);
|
||||
return inputs.length - 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void setLabel(int num, const string& label) {
|
||||
GuiText@ txt = cast<GuiText>(getInput(num));
|
||||
if(txt !is null)
|
||||
txt.text = label;
|
||||
}
|
||||
|
||||
//**Textbox input lines
|
||||
int addTextInput(const string& label, const string& defaultText, int height = INPUT_LINE_HEIGHT) {
|
||||
GuiText@ lbl = GuiText(null, recti(), label);
|
||||
|
||||
GuiTextbox@ box = GuiTextbox(null, recti(), defaultText);
|
||||
@box.callback = this;
|
||||
|
||||
int i = addInput(lbl, box, height);
|
||||
|
||||
if(height > INPUT_LINE_HEIGHT) {
|
||||
box.multiLine = true;
|
||||
lbl.vertAlign = 0.0;
|
||||
}
|
||||
|
||||
box.updateTextPosition();
|
||||
return i;
|
||||
}
|
||||
|
||||
string getTextInput(int num) {
|
||||
GuiTextbox@ box = cast<GuiTextbox@>(getInput(num));
|
||||
return box.text;
|
||||
}
|
||||
|
||||
void focusTextInput(int num, bool selectAll = false) {
|
||||
GuiTextbox@ box = cast<GuiTextbox@>(getInput(num));
|
||||
box.focus(selectAll);
|
||||
}
|
||||
|
||||
//**Spinbox input lines
|
||||
int addSpinboxInput(const string& label, double defaultValue = 0.0, double step = 1.0,
|
||||
double minValue = -INFINITY, double maxValue = INFINITY, int decimals = 0) {
|
||||
GuiText@ lbl = GuiText(null, recti(), label);
|
||||
|
||||
GuiSpinbox@ box = GuiSpinbox(null, recti(), defaultValue);
|
||||
@box.callback = this;
|
||||
box.step = step;
|
||||
box.decimals = decimals;
|
||||
box.min = minValue;
|
||||
box.max = maxValue;
|
||||
box.value = defaultValue;
|
||||
|
||||
return addInput(lbl, box);
|
||||
}
|
||||
|
||||
double getSpinboxInput(int num) {
|
||||
GuiSpinbox@ box = cast<GuiSpinbox@>(getInput(num));
|
||||
return box.value;
|
||||
}
|
||||
|
||||
//**Checkbox input lines
|
||||
int addToggle(const string& label, bool defaultValue) {
|
||||
GuiCheckbox@ box = GuiCheckbox(null, recti(), label, defaultValue);
|
||||
@box.callback = this;
|
||||
|
||||
return addInput(null, box);
|
||||
}
|
||||
|
||||
bool getToggle(int num) {
|
||||
GuiCheckbox@ box = cast<GuiCheckbox@>(getInput(num));
|
||||
return box.checked;
|
||||
}
|
||||
|
||||
//** Dropdown lines
|
||||
int addSelection(const string& label) {
|
||||
GuiText@ lbl = GuiText(null, recti(), label);
|
||||
lbl.vertAlign = 0.0;
|
||||
|
||||
GuiDropdown@ box = GuiDropdown(null, recti());
|
||||
|
||||
return addInput(lbl, box);
|
||||
}
|
||||
|
||||
void addItem(const string& value, bool select = false) {
|
||||
addItem(inputs.length() - 1, value, select);
|
||||
}
|
||||
|
||||
void addItem(int num, const string& value, bool select = false) {
|
||||
GuiDropdown@ box = cast<GuiDropdown@>(getInput(num));
|
||||
box.addItem(value);
|
||||
|
||||
if(select)
|
||||
box.selected = box.itemCount - 1;
|
||||
}
|
||||
|
||||
int getSelection(int num) {
|
||||
GuiDropdown@ box = cast<GuiDropdown@>(getInput(num));
|
||||
return box.selected;
|
||||
}
|
||||
|
||||
string getSelectionValue(int num) {
|
||||
GuiDropdown@ box = cast<GuiDropdown@>(getInput(num));
|
||||
int sel = box.selected;
|
||||
if(sel >= 0)
|
||||
return box.getItem(sel);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
//Close callback
|
||||
void close() {
|
||||
close(false);
|
||||
}
|
||||
|
||||
void close(bool accepted) {
|
||||
if(callback !is null)
|
||||
callback.inputCallback(this, accepted);
|
||||
Dialog::close();
|
||||
}
|
||||
|
||||
void confirmDialog() {
|
||||
close(true);
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(Closed)
|
||||
return false;
|
||||
if(event.type == GUI_Clicked && (event.caller is accept || event.caller is cancel)) {
|
||||
close(event.caller is accept);
|
||||
return true;
|
||||
}
|
||||
else if(event.type == GUI_Confirmed) {
|
||||
int ind = -1;
|
||||
for(uint i = 0, cnt = inputs.length(); i < cnt; ++i) {
|
||||
if(inputs[i] is cast<BaseGuiElement@>(event.caller)) {
|
||||
ind = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ind < 0)
|
||||
return false;
|
||||
if(uint(ind) == inputs.length() - 1)
|
||||
close(true);
|
||||
else
|
||||
setGuiFocus(inputs[ind + 1]);
|
||||
return true;
|
||||
}
|
||||
else if(event.type == GUI_Changed) {
|
||||
if(callback !is null)
|
||||
callback.changeCallback(this);
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiFileChooser;
|
||||
|
||||
class LoadDialog : Dialog {
|
||||
GuiFileChooser@ chooser;
|
||||
GuiButton@ confirm;
|
||||
|
||||
LoadDialog(IGuiElement@ bind, const string& folder) {
|
||||
super(bind);
|
||||
addTitle(locale::LOAD);
|
||||
@window.callback = this;
|
||||
|
||||
@chooser = GuiFileChooser(window, Alignment(Left+12, Top+38, Right-12, Bottom-12), folder, "", CFM_Single);
|
||||
@confirm = GuiButton(window, Alignment(Left+0.8f+4, Bottom-42, Right-12, Bottom-12), locale::LOAD);
|
||||
confirm.disabled = true;
|
||||
|
||||
height = 500;
|
||||
addDialog(this);
|
||||
}
|
||||
|
||||
void focus() {
|
||||
Dialog::focus();
|
||||
}
|
||||
|
||||
string get_path() {
|
||||
return chooser.getSelectedPath(true);
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
void clickConfirm() {
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if((event.caller is chooser && event.type == GUI_Confirmed)
|
||||
|| (event.caller is confirm && event.type == GUI_Clicked)) {
|
||||
if(chooser.selectedCount != 0)
|
||||
clickConfirm();
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
if(event.caller is chooser && event.type == GUI_Changed)
|
||||
confirm.disabled = chooser.selectedCount == 0;
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,226 @@
|
||||
import dialogs.Dialog;
|
||||
|
||||
enum MaterialChooserMode {
|
||||
MCM_All,
|
||||
MCM_Materials,
|
||||
MCM_Spritesheets,
|
||||
};
|
||||
|
||||
MaterialChooser@ openMaterialChooser(MaterialChoiceCallback@ callback, MaterialChooserMode mode = MCM_All) {
|
||||
MaterialChooser@ matDialog = MaterialChooser(callback, null, mode);
|
||||
addDialog(matDialog);
|
||||
return matDialog;
|
||||
}
|
||||
|
||||
interface MaterialChoiceCallback {
|
||||
void onMaterialChosen(const Material@ material, const string& id);
|
||||
void onSpriteSheetChosen(const SpriteSheet@ spritebank, uint spriteIndex, const string& id);
|
||||
};
|
||||
|
||||
class MaterialChooser : Dialog {
|
||||
MaterialList@ materials;
|
||||
MaterialChoiceCallback@ matCallback;
|
||||
|
||||
MaterialChooser(MaterialChoiceCallback@ userCallback, IGuiElement@ bind, MaterialChooserMode mode) {
|
||||
super(bind);
|
||||
width = 1024;
|
||||
height = 768;
|
||||
|
||||
@materials = MaterialList(window, recti(4,4,1020,764), mode);
|
||||
@matCallback = userCallback;
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onKeyEvent(const KeyboardEvent& event, IGuiElement@ source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.type == GUI_Clicked && event.caller is materials) {
|
||||
if(materials.material !is null)
|
||||
matCallback.onMaterialChosen(materials.material, materials.identifier);
|
||||
else if(materials.spriteSheet !is null)
|
||||
matCallback.onSpriteSheetChosen(materials.spriteSheet, materials.spriteIndex, materials.identifier);
|
||||
closeDialog(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class MaterialList : BaseGuiElement {
|
||||
const Material@ material;
|
||||
const SpriteSheet@ spriteSheet;
|
||||
string identifier;
|
||||
uint spriteIndex;
|
||||
MaterialChooserMode mode;
|
||||
|
||||
int scroll;
|
||||
int iconSize, margin;
|
||||
uint rowIconCount;
|
||||
|
||||
vec2i hoverPos, clickPos;
|
||||
|
||||
MaterialList(IGuiElement@ parent, const recti& position, MaterialChooserMode Mode) {
|
||||
super(parent, position);
|
||||
hoverPos = vec2i(-1,-1);
|
||||
|
||||
iconSize = 96;
|
||||
margin = 2;
|
||||
mode = Mode;
|
||||
rowIconCount = (AbsolutePosition.width - (2 * margin) / (iconSize + margin));
|
||||
}
|
||||
|
||||
vec2i absoluteToMatPos(int x, int y) const {
|
||||
return vec2i((x - (AbsolutePosition.topLeft.x + 4)) / (iconSize + margin),
|
||||
(y - (AbsolutePosition.topLeft.y + 4) + scroll) / (iconSize + margin));
|
||||
}
|
||||
|
||||
void draw() {
|
||||
@material = null;
|
||||
@spriteSheet = null;
|
||||
vec2i at;
|
||||
|
||||
int x = margin, y = margin - scroll;
|
||||
int height = AbsolutePosition.height;
|
||||
int row = 0, col = 0;
|
||||
|
||||
//Draw each material
|
||||
uint count = getMaterialCount();
|
||||
if(mode == MCM_All || mode == MCM_Materials) {
|
||||
for(uint i = 0; i < count; ++i) {
|
||||
if(y + iconSize >= 0 && y - iconSize < height) {
|
||||
const Material@ mat = getMaterial(i);
|
||||
|
||||
if(hoverPos.x == col && hoverPos.y == row) {
|
||||
@material = mat;
|
||||
identifier = getMaterialName(i);
|
||||
at = vec2i(x-iconSize/2,y-iconSize/2);
|
||||
}
|
||||
else {
|
||||
mat.draw(recti(x,y,x+iconSize,y+iconSize) + AbsolutePosition.topLeft, Color(0xffffffff), shader::BaseTexture);
|
||||
}
|
||||
}
|
||||
|
||||
x += iconSize + margin;
|
||||
col += 1;
|
||||
if(x+iconSize > AbsolutePosition.width - margin) {
|
||||
x = margin;
|
||||
y += iconSize + margin;
|
||||
|
||||
col = 0;
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Start on a new line when we switch to sprite sheets
|
||||
if(col != 0) {
|
||||
x = margin;
|
||||
y += iconSize + margin;
|
||||
|
||||
col = 0;
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw each sprite in each sprite sheet
|
||||
if(mode == MCM_All || mode == MCM_Spritesheets) {
|
||||
count = getSpriteSheetCount();
|
||||
for(uint i = 0; i < count; ++i) {
|
||||
const SpriteSheet@ sheet = getSpriteSheet(i);
|
||||
uint spriteCount = sheet.count;
|
||||
for(uint j = 0; j < spriteCount; ++j) {
|
||||
if(y + iconSize >= 0 && y - iconSize < height) {
|
||||
if(hoverPos.x == col && hoverPos.y == row) {
|
||||
at = vec2i(x-iconSize/2,y-iconSize/2);
|
||||
|
||||
@spriteSheet = sheet;
|
||||
spriteIndex = j;
|
||||
identifier = getSpriteSheetName(i);
|
||||
}
|
||||
else {
|
||||
sheet.draw(j, recti_area(vec2i(x,y),vec2i(iconSize)) + AbsolutePosition.topLeft, shader::BaseTexture);
|
||||
}
|
||||
}
|
||||
|
||||
x += iconSize + margin;
|
||||
col += 1;
|
||||
if(x+iconSize > AbsolutePosition.width - margin) {
|
||||
x = margin;
|
||||
y += iconSize + margin;
|
||||
|
||||
col = 0;
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(material !is null || spriteSheet !is null) {
|
||||
if(at.x < margin)
|
||||
at.x = margin;
|
||||
else if(at.x + (iconSize*2) > AbsolutePosition.width - margin)
|
||||
at.x = AbsolutePosition.width - margin - (iconSize*2);
|
||||
|
||||
if(at.y < margin)
|
||||
at.y = margin;
|
||||
else if(at.y + (iconSize*2) > AbsolutePosition.height - margin)
|
||||
at.y = AbsolutePosition.height - margin - (iconSize*2);
|
||||
|
||||
recti bgRect = recti(at.x - margin, at.y - margin, at.x + (iconSize*2) + margin, at.y + (iconSize*2) + margin) + AbsolutePosition.topLeft;
|
||||
|
||||
if(material !is null) {
|
||||
drawRectangle(bgRect, Color(0x70a070ff));
|
||||
|
||||
vec2i size = material.size;
|
||||
if(size.x > iconSize * 2 || size.y > iconSize * 2) {
|
||||
double factor = max(double(size.x), double(size.y)) / double(iconSize * 2);
|
||||
size /= factor;
|
||||
}
|
||||
|
||||
material.draw(recti_area(at + vec2i(iconSize) - size * 0.5,size) + AbsolutePosition.topLeft, Color(0xffffffff), shader::BaseTexture);
|
||||
skin.getFont(FT_Normal).draw(bgRect, identifier, Color(0x000000ff), vertAlign = 0.0);
|
||||
}
|
||||
else if(spriteSheet !is null) {
|
||||
drawRectangle(bgRect, Color(0x70a070ff));
|
||||
|
||||
vec2i size = spriteSheet.size;
|
||||
if(size.x > iconSize * 2 || size.y > iconSize * 2) {
|
||||
double factor = max(double(size.x), double(size.y)) / double(iconSize * 2);
|
||||
size /= factor;
|
||||
}
|
||||
|
||||
spriteSheet.draw(spriteIndex, recti_area(at + vec2i(iconSize) - size * 0.5,size) + AbsolutePosition.topLeft, shader::BaseTexture);
|
||||
skin.getFont(FT_Normal).draw(bgRect, identifier, Color(0x000000ff), vertAlign = 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
||||
if(event.type == MET_Button_Up) {
|
||||
vec2i pos = absoluteToMatPos(event.x, event.y);
|
||||
if(pos == clickPos) {
|
||||
emitClicked();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(event.type == MET_Button_Down) {
|
||||
clickPos = absoluteToMatPos(event.x, event.y);
|
||||
return true;
|
||||
}
|
||||
else if(event.type == MET_Moved) {
|
||||
hoverPos = absoluteToMatPos(event.x, event.y);
|
||||
}
|
||||
else if(event.type == MET_Scrolled) {
|
||||
scroll -= int(event.y * 32.0);
|
||||
if(scroll < 0)
|
||||
scroll = 0;
|
||||
}
|
||||
return BaseGuiElement::onMouseEvent(event, source);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiMarkupText;
|
||||
import elements.GuiTextbox;
|
||||
|
||||
interface MessageDialogCallback {
|
||||
void messageCallback(MessageDialog@ dialog);
|
||||
};
|
||||
|
||||
class MessageDialog : Dialog {
|
||||
MessageDialogCallback@ callback;
|
||||
GuiMarkupText@ txt;
|
||||
GuiButton@ ok;
|
||||
|
||||
MessageDialog(const string& text, MessageDialogCallback@ CB, IGuiElement@ bind) {
|
||||
@callback = CB;
|
||||
super(bind);
|
||||
addTitle(locale::NOTICE);
|
||||
|
||||
@ok = GuiButton(bg, recti());
|
||||
ok.text = locale::OK;
|
||||
|
||||
if(isWindows) {
|
||||
//Legacy OS support
|
||||
@ok.alignment = Alignment(Left+0.4f+DIALOG_PADDING, Bottom-DIALOG_BUTTON_ROW, Right-0.4f-DIALOG_PADDING, Bottom-DIALOG_PADDING);
|
||||
}
|
||||
else {
|
||||
@ok.alignment = Alignment(Right-0.2f-DIALOG_PADDING, Bottom-DIALOG_BUTTON_ROW, Right-0.0f-DIALOG_PADDING, Bottom-DIALOG_PADDING);
|
||||
}
|
||||
|
||||
@txt = GuiMarkupText(window, recti(DIALOG_PADDING, DIALOG_PADDING+22, width - DIALOG_PADDING, 50), text);
|
||||
height = txt.size.height+22;
|
||||
height += 56;
|
||||
}
|
||||
|
||||
//Close callback
|
||||
void close() {
|
||||
if(callback !is null)
|
||||
callback.messageCallback(this);
|
||||
Dialog::close();
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.type == GUI_Clicked && event.caller is ok && !Closed) {
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
MessageDialog@ message(const string& msg, MessageDialogCallback@ cb = null, IGuiElement@ bind = null) {
|
||||
MessageDialog@ dlg = MessageDialog(msg, cb, bind);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiMarkupText;
|
||||
import elements.GuiTextbox;
|
||||
import elements.GuiText;
|
||||
|
||||
interface QuestionDialogCallback {
|
||||
void questionCallback(QuestionDialog@ dialog, int answer);
|
||||
};
|
||||
|
||||
class QuestionDialog : Dialog {
|
||||
QuestionDialogCallback@ callback;
|
||||
GuiText@ txt;
|
||||
GuiButton@[] buttons;
|
||||
|
||||
QuestionDialog(const string& title, const string& text, QuestionDialogCallback@ CB, IGuiElement@ bind) {
|
||||
@callback = CB;
|
||||
super(bind);
|
||||
|
||||
int y = 0;
|
||||
if(title.length != 0) {
|
||||
addTitle(title);
|
||||
y += 26;
|
||||
}
|
||||
|
||||
GuiMarkupText@ txt = GuiMarkupText(window, recti(DIALOG_PADDING, DIALOG_PADDING+y, width - DIALOG_PADDING, 50+y), text);
|
||||
height = txt.size.height+y;
|
||||
height += 50+DIALOG_PADDING;
|
||||
}
|
||||
|
||||
string get_text() {
|
||||
return txt.text;
|
||||
}
|
||||
|
||||
//Button management
|
||||
void addButton(const string& str, const Color& color = colors::White) {
|
||||
if(isWindows) {
|
||||
//Legacy OS support
|
||||
GuiButton@ btn = GuiButton(window, recti(vec2i(), vec2i(130, DIALOG_BUTTON_HEIGHT)), str);
|
||||
buttons.insertLast(btn);
|
||||
btn.color = color;
|
||||
|
||||
int start = buttons.length() * (130 + DIALOG_PADDING) - DIALOG_PADDING;
|
||||
start = (width - start) / 2;
|
||||
|
||||
for(uint i = 0, cnt = buttons.length(); i < cnt; ++i) {
|
||||
buttons[i].position = vec2i(start, height - DIALOG_BUTTON_ROW);
|
||||
start += 152;
|
||||
}
|
||||
}
|
||||
else {
|
||||
recti pos = recti_area(
|
||||
vec2i(width - (buttons.length() + 1) * (130 + DIALOG_PADDING), height - DIALOG_BUTTON_ROW),
|
||||
vec2i(130, DIALOG_BUTTON_HEIGHT));
|
||||
|
||||
GuiButton@ btn = GuiButton(window, pos, str);
|
||||
btn.color = color;
|
||||
buttons.insertLast(btn);
|
||||
}
|
||||
}
|
||||
|
||||
//Close callback
|
||||
void close() {
|
||||
close(-1);
|
||||
}
|
||||
|
||||
void close(int answer) {
|
||||
if(callback !is null)
|
||||
callback.questionCallback(this, answer);
|
||||
Dialog::close();
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(Closed)
|
||||
return false;
|
||||
if(event.type == GUI_Clicked) {
|
||||
for(uint i = 0, cnt = buttons.length(); i < cnt; ++i) {
|
||||
if(buttons[i] is cast<GuiButton@>(event.caller)) {
|
||||
close(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event.type == GUI_Confirmed) {
|
||||
close(0);
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
enum QuestionAnswer {
|
||||
QA_Yes,
|
||||
QA_No,
|
||||
};
|
||||
|
||||
QuestionDialog@ question(const string& msg, QuestionDialogCallback@ cb = null, IGuiElement@ bind = null) {
|
||||
QuestionDialog@ dlg = QuestionDialog(" ", msg, cb, bind);
|
||||
dlg.addButton(locale::YES, colors::Green);
|
||||
dlg.addButton(locale::NO, colors::Red);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
|
||||
QuestionDialog@ question(const string& msg, const string& yes, const string& no, QuestionDialogCallback@ cb = null, IGuiElement@ bind = null) {
|
||||
QuestionDialog@ dlg = QuestionDialog(" ", msg, cb, bind);
|
||||
dlg.addButton(yes, colors::Green);
|
||||
dlg.addButton(no, colors::Red);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
|
||||
QuestionDialog@ question(const string& title, const string& msg, QuestionDialogCallback@ cb = null, IGuiElement@ bind = null) {
|
||||
QuestionDialog@ dlg = QuestionDialog(title, msg, cb, bind);
|
||||
dlg.addButton(locale::YES, colors::Green);
|
||||
dlg.addButton(locale::NO, colors::Red);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
|
||||
QuestionDialog@ question(const string& title, const string& msg, const string& yes, const string& no, QuestionDialogCallback@ cb = null, IGuiElement@ bind = null) {
|
||||
QuestionDialog@ dlg = QuestionDialog(title, msg, cb, bind);
|
||||
dlg.addButton(yes, colors::Green);
|
||||
dlg.addButton(no, colors::Red);
|
||||
addDialog(dlg);
|
||||
return dlg;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import dialogs.Dialog;
|
||||
import elements.GuiFileChooser;
|
||||
|
||||
class SaveDialog : Dialog {
|
||||
const Design@ dsg;
|
||||
const DesignClass@ targetClass;
|
||||
GuiFileChooser@ chooser;
|
||||
|
||||
SaveDialog(IGuiElement@ bind, const string& folder, const string& defaultName) {
|
||||
super(bind);
|
||||
addTitle(locale::EXPORT_DESIGN);
|
||||
@window.callback = this;
|
||||
|
||||
@chooser = GuiFileChooser(window, Alignment(Left+12, Top+38, Right-12, Bottom-12), folder, "", CFM_Filename);
|
||||
chooser.selectedFilename = defaultName;
|
||||
|
||||
height = 500;
|
||||
addDialog(this);
|
||||
}
|
||||
|
||||
void focus() {
|
||||
Dialog::focus();
|
||||
chooser.filename.focus(true);
|
||||
}
|
||||
|
||||
string get_path() {
|
||||
return chooser.getSelectedPath(true);
|
||||
}
|
||||
|
||||
//Event callbacks
|
||||
void clickConfirm() {
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.caller is chooser && event.type == GUI_Confirmed) {
|
||||
if(chooser.selectedFilename.length != 0)
|
||||
clickConfirm();
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
return Dialog::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
//Dialogs can be given a unique id on
|
||||
//a per-module basis, so duplicate dialogs
|
||||
//are not allowed.
|
||||
|
||||
Dialog@[] uniqueDialogs;
|
||||
|
||||
void addDialog(uint num, Dialog@ dlg) {
|
||||
if(num >= uniqueDialogs.length)
|
||||
uniqueDialogs.length = num + 1;
|
||||
if(uniqueDialogs[num] !is null)
|
||||
closeDialog(uniqueDialogs[num]);
|
||||
@uniqueDialogs[num] = dlg;
|
||||
addDialog(dlg);
|
||||
}
|
||||
|
||||
bool focusDialog(uint num) {
|
||||
if(uniqueDialogs.length <= num)
|
||||
return false;
|
||||
Dialog@ dlg = uniqueDialogs[num];
|
||||
if(dlg is null || dlg.closed)
|
||||
return false;
|
||||
dlg.focus();
|
||||
return true;
|
||||
}
|
||||
|
||||
Dialog@ getUniqueDialog(uint num) {
|
||||
if(uniqueDialogs.length <= num)
|
||||
return null;
|
||||
Dialog@ dlg = uniqueDialogs[num];
|
||||
if(dlg is null || dlg.closed)
|
||||
return null;
|
||||
return dlg;
|
||||
}
|
||||
Reference in New Issue
Block a user