mirror of https://gitlab.com/nakst/essence
ask to save on close
This commit is contained in:
parent
33b7dd9dd1
commit
dc365b12e1
|
@ -84,11 +84,11 @@ const EsStyle styleBitmapSizeTextbox = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const EsStyle styleImageMenuTable = {
|
const EsStyle styleImageMenuTable = {
|
||||||
|
.inherit = ES_STYLE_PANEL_FORM_TABLE,
|
||||||
|
|
||||||
.metrics = {
|
.metrics = {
|
||||||
.mask = ES_THEME_METRICS_GAP_ALL | ES_THEME_METRICS_INSETS,
|
.mask = ES_THEME_METRICS_INSETS,
|
||||||
.insets = ES_RECT_4(20, 20, 5, 8),
|
.insets = ES_RECT_4(20, 20, 5, 8),
|
||||||
.gapMajor = 6,
|
|
||||||
.gapMinor = 6,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -49,14 +49,6 @@ const EsStyle styleButtonsRow = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const EsStyle styleCustomizeTable = {
|
|
||||||
.metrics = {
|
|
||||||
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_GAP_MINOR,
|
|
||||||
.gapMajor = 7,
|
|
||||||
.gapMinor = 7,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
InstallerMetadata *metadata;
|
InstallerMetadata *metadata;
|
||||||
Array<EsMessageDevice> connectedDrives;
|
Array<EsMessageDevice> connectedDrives;
|
||||||
EsListView *drivesList;
|
EsListView *drivesList;
|
||||||
|
@ -1085,7 +1077,7 @@ void _start() {
|
||||||
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
|
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
|
||||||
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING1, INTERFACE_STRING(InstallerCustomizeOptions));
|
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING1, INTERFACE_STRING(InstallerCustomizeOptions));
|
||||||
|
|
||||||
EsPanel *table = EsPanelCreate(panelCustomizeOptions, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL | ES_PANEL_TABLE, &styleCustomizeTable);
|
EsPanel *table = EsPanelCreate(panelCustomizeOptions, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL | ES_PANEL_TABLE, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsPanelSetBands(table, 2 /* columns */);
|
EsPanelSetBands(table, 2 /* columns */);
|
||||||
|
|
||||||
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, ES_STYLE_TEXT_LABEL, INTERFACE_STRING(InstallerUserName));
|
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, ES_STYLE_TEXT_LABEL, INTERFACE_STRING(InstallerUserName));
|
||||||
|
|
|
@ -13,16 +13,6 @@ const EsStyle stylePanelStack = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define the metrics for panelForm.
|
|
||||||
const EsStyle stylePanelForm = {
|
|
||||||
.metrics = {
|
|
||||||
.mask = ES_THEME_METRICS_GAP_MAJOR
|
|
||||||
| ES_THEME_METRICS_GAP_MINOR,
|
|
||||||
.gapMajor = 5, // Spacing between columns.
|
|
||||||
.gapMinor = 8, // Spacing between rows.
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Global variables.
|
// Global variables.
|
||||||
EsTextbox *textboxRate;
|
EsTextbox *textboxRate;
|
||||||
EsTextbox *textboxAmount;
|
EsTextbox *textboxAmount;
|
||||||
|
@ -77,7 +67,7 @@ void _start() {
|
||||||
panelStack, // Add it to panelStack.
|
panelStack, // Add it to panelStack.
|
||||||
ES_PANEL_TABLE // Use table layout.
|
ES_PANEL_TABLE // Use table layout.
|
||||||
| ES_PANEL_HORIZONTAL, // Left to right, then top to bottom.
|
| ES_PANEL_HORIZONTAL, // Left to right, then top to bottom.
|
||||||
&stylePanelForm);
|
ES_STYLE_PANEL_FORM_TABLE); // Use the standard metrics for a form.
|
||||||
|
|
||||||
// Set the number of columns for the panelForm's table layout.
|
// Set the number of columns for the panelForm's table layout.
|
||||||
EsPanelSetBands(panelForm, 2);
|
EsPanelSetBands(panelForm, 2);
|
||||||
|
|
|
@ -151,6 +151,19 @@ void InitialiseInstance(EsInstance *instance) {
|
||||||
|
|
||||||
EsPanel *panel = EsPanelCreate(instance->window, ES_CELL_FILL, &stylePanel);
|
EsPanel *panel = EsPanelCreate(instance->window, ES_CELL_FILL, &stylePanel);
|
||||||
EsButtonCreate(panel, ES_BUTTON_CHECKBOX, 0, "Checkbox");
|
EsButtonCreate(panel, ES_BUTTON_CHECKBOX, 0, "Checkbox");
|
||||||
|
|
||||||
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Alert 1"), [] (EsInstance *, EsElement *element, EsCommand *) {
|
||||||
|
EsDialogShowAlert(element->window, "Title", -1, "Content.", -1, ES_ICON_DIALOG_WARNING, ES_DIALOG_ALERT_OK_BUTTON);
|
||||||
|
});
|
||||||
|
|
||||||
|
EsPanel *table = EsPanelCreate(panel, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_PANEL_TABLE_H_JUSTIFY);
|
||||||
|
EsPanelSetBands(table, 3);
|
||||||
|
|
||||||
|
for (uintptr_t i = 0; i < 8; i++) {
|
||||||
|
EsButtonCreate(table, ES_FLAGS_DEFAULT, 0, "Justified columns");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Crash"), [] (EsInstance *, EsElement *, EsCommand *) { EsAssert(false); });
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Crash"), [] (EsInstance *, EsElement *, EsCommand *) { EsAssert(false); });
|
||||||
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Hang"), [] (EsInstance *, EsElement *, EsCommand *) { while (true); });
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Hang"), [] (EsInstance *, EsElement *, EsCommand *) { while (true); });
|
||||||
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Wait"), [] (EsInstance *, EsElement *, EsCommand *) { EsSleep(8000); });
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Wait"), [] (EsInstance *, EsElement *, EsCommand *) { EsSleep(8000); });
|
||||||
|
@ -176,6 +189,7 @@ void InitialiseInstance(EsInstance *instance) {
|
||||||
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Crash 6"), [] (EsInstance *, EsElement *, EsCommand *) {
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Crash 6"), [] (EsInstance *, EsElement *, EsCommand *) {
|
||||||
EsMemoryCopy(nullptr, nullptr, 1);
|
EsMemoryCopy(nullptr, nullptr, 1);
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Move file"), [] (EsInstance *, EsElement *, EsCommand *) {
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Move file"), [] (EsInstance *, EsElement *, EsCommand *) {
|
||||||
EsPathMove("0:/A Study in Scarlet.txt", -1, "0:/moved.txt", -1, ES_PATH_MOVE_ALLOW_COPY_AND_DELETE);
|
EsPathMove("0:/A Study in Scarlet.txt", -1, "0:/moved.txt", -1, ES_PATH_MOVE_ALLOW_COPY_AND_DELETE);
|
||||||
|
|
131
desktop/api.cpp
131
desktop/api.cpp
|
@ -225,6 +225,9 @@ struct APIInstance {
|
||||||
commandSave,
|
commandSave,
|
||||||
commandShowInFileManager;
|
commandShowInFileManager;
|
||||||
|
|
||||||
|
char *newName;
|
||||||
|
size_t newNameBytes;
|
||||||
|
|
||||||
const char *applicationName;
|
const char *applicationName;
|
||||||
size_t applicationNameBytes;
|
size_t applicationNameBytes;
|
||||||
|
|
||||||
|
@ -235,6 +238,8 @@ struct APIInstance {
|
||||||
|
|
||||||
EsFileStore *fileStore;
|
EsFileStore *fileStore;
|
||||||
|
|
||||||
|
bool closeAfterSaveCompletes;
|
||||||
|
|
||||||
// Do not propagate messages about this instance to the application.
|
// Do not propagate messages about this instance to the application.
|
||||||
// Currently only used for inspectors.
|
// Currently only used for inspectors.
|
||||||
bool internalOnly;
|
bool internalOnly;
|
||||||
|
@ -247,7 +252,7 @@ struct APIInstance {
|
||||||
// For the file menu.
|
// For the file menu.
|
||||||
EsPanel *fileMenuNameSwitcher;
|
EsPanel *fileMenuNameSwitcher;
|
||||||
EsPanel *fileMenuNamePanel;
|
EsPanel *fileMenuNamePanel;
|
||||||
EsTextbox *fileMenuNameTextbox;
|
EsTextbox *fileMenuNameTextbox; // Also used by the file save dialog.
|
||||||
};
|
};
|
||||||
|
|
||||||
MountPoint *NodeAddMountPoint(const char *prefix, size_t prefixBytes, EsHandle base, bool queryInformation) {
|
MountPoint *NodeAddMountPoint(const char *prefix, size_t prefixBytes, EsHandle base, bool queryInformation) {
|
||||||
|
@ -651,6 +656,86 @@ void InstanceSave(EsInstance *_instance) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstanceClose(EsInstance *instance) {
|
||||||
|
if (EsCommandByID(instance, ES_COMMAND_SAVE)->disabled) {
|
||||||
|
EsInstanceDestroy(instance);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The document has unsaved changes.
|
||||||
|
// Ask the user if they want to save.
|
||||||
|
|
||||||
|
// TODO Handling shutdown.
|
||||||
|
|
||||||
|
APIInstance *apiInstance = (APIInstance *) instance->_private;
|
||||||
|
char content[512];
|
||||||
|
size_t contentBytes;
|
||||||
|
const char *cTitle;
|
||||||
|
|
||||||
|
if (apiInstance->startupInformation->filePathBytes) {
|
||||||
|
cTitle = interfaceString_FileCloseWithModificationsTitle;
|
||||||
|
contentBytes = EsStringFormat(content, sizeof(content), interfaceString_FileCloseWithModificationsContent,
|
||||||
|
apiInstance->startupInformation->filePathBytes, apiInstance->startupInformation->filePath);
|
||||||
|
} else {
|
||||||
|
cTitle = interfaceString_FileCloseNewTitle;
|
||||||
|
contentBytes = EsStringFormat(content, sizeof(content), interfaceString_FileCloseNewContent,
|
||||||
|
apiInstance->applicationNameBytes, apiInstance->applicationName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE Duplicated from EsDialogShowAlert.
|
||||||
|
// TODO Is there a good way to make more modular dialogs?
|
||||||
|
EsElement *dialog = EsDialogShow(instance->window);
|
||||||
|
EsPanel *heading = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_DIALOG_HEADING);
|
||||||
|
EsIconDisplayCreate(heading, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
||||||
|
EsTextDisplayCreate(heading, ES_CELL_H_FILL | ES_CELL_V_CENTER, ES_STYLE_TEXT_HEADING2, cTitle);
|
||||||
|
EsPanel *contentArea = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_VERTICAL, ES_STYLE_DIALOG_CONTENT);
|
||||||
|
EsTextDisplayCreate(contentArea, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, content, contentBytes);
|
||||||
|
EsPanel *buttonArea = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE, ES_STYLE_DIALOG_BUTTON_AREA);
|
||||||
|
|
||||||
|
if (!apiInstance->startupInformation->filePathBytes) {
|
||||||
|
EsPanel *row = EsPanelCreate(contentArea, ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
|
EsTextDisplayCreate(row, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL, INTERFACE_STRING(FileCloseNewName));
|
||||||
|
EsTextbox *textbox = EsTextboxCreate(row);
|
||||||
|
EsInstanceClassEditorSettings *editorSettings = &apiInstance->editorSettings;
|
||||||
|
EsTextboxInsert(textbox, editorSettings->newDocumentFileName, editorSettings->newDocumentFileNameBytes);
|
||||||
|
EsElementFocus(textbox);
|
||||||
|
TextboxSelectSectionBeforeFileExtension(textbox, editorSettings->newDocumentFileName, editorSettings->newDocumentFileNameBytes);
|
||||||
|
apiInstance->fileMenuNameTextbox = textbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
EsButton *button;
|
||||||
|
|
||||||
|
button = EsButtonCreate(buttonArea, ES_BUTTON_CANCEL, 0, INTERFACE_STRING(CommonCancel));
|
||||||
|
|
||||||
|
EsButtonOnCommand(button, [] (EsInstance *instance, EsElement *, EsCommand *) {
|
||||||
|
EsDialogClose(instance->window);
|
||||||
|
});
|
||||||
|
|
||||||
|
button = EsButtonCreate(buttonArea, ES_FLAGS_DEFAULT, ES_STYLE_PUSH_BUTTON_DANGEROUS, INTERFACE_STRING(FileCloseWithModificationsDelete));
|
||||||
|
|
||||||
|
EsButtonOnCommand(button, [] (EsInstance *instance, EsElement *, EsCommand *) {
|
||||||
|
EsInstanceDestroy(instance);
|
||||||
|
});
|
||||||
|
|
||||||
|
button = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT, 0, INTERFACE_STRING(FileCloseWithModificationsSave));
|
||||||
|
|
||||||
|
EsButtonOnCommand(button, [] (EsInstance *instance, EsElement *, EsCommand *) {
|
||||||
|
APIInstance *apiInstance = (APIInstance *) instance->_private;
|
||||||
|
|
||||||
|
if (apiInstance->startupInformation->filePathBytes) {
|
||||||
|
InstanceSave(instance);
|
||||||
|
} else {
|
||||||
|
InstanceRenameFromTextbox(instance->window, apiInstance, apiInstance->fileMenuNameTextbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
apiInstance->closeAfterSaveCompletes = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (apiInstance->startupInformation->filePathBytes) {
|
||||||
|
EsElementFocus(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FileStoreCloseHandle(EsFileStore *fileStore) {
|
void FileStoreCloseHandle(EsFileStore *fileStore) {
|
||||||
EsMessageMutexCheck(); // TODO Remove this limitation?
|
EsMessageMutexCheck(); // TODO Remove this limitation?
|
||||||
EsAssert(fileStore->handles < 0x80000000);
|
EsAssert(fileStore->handles < 0x80000000);
|
||||||
|
@ -934,10 +1019,12 @@ EsMessage *EsMessageReceive() {
|
||||||
|
|
||||||
if (instance->startupInformation) {
|
if (instance->startupInformation) {
|
||||||
EsHeapFree((void *) instance->startupInformation->filePath);
|
EsHeapFree((void *) instance->startupInformation->filePath);
|
||||||
|
EsHeapFree((void *) instance->startupInformation->containingFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
EsHeapFree(instance->startupInformation);
|
EsHeapFree(instance->startupInformation);
|
||||||
EsHeapFree(instance->documentPath);
|
EsHeapFree(instance->documentPath);
|
||||||
|
EsHeapFree(instance->newName);
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < instance->commands.Count(); i++) {
|
for (uintptr_t i = 0; i < instance->commands.Count(); i++) {
|
||||||
EsCommand *command = instance->commands[i];
|
EsCommand *command = instance->commands[i];
|
||||||
|
@ -1012,7 +1099,10 @@ EsMessage *EsMessageReceive() {
|
||||||
}
|
}
|
||||||
} else if (type == ES_MSG_TAB_CLOSE_REQUEST) {
|
} else if (type == ES_MSG_TAB_CLOSE_REQUEST) {
|
||||||
EsInstance *instance = InstanceFromWindowID(message.message.tabOperation.id);
|
EsInstance *instance = InstanceFromWindowID(message.message.tabOperation.id);
|
||||||
if (instance) EsInstanceDestroy(instance);
|
|
||||||
|
if (instance) {
|
||||||
|
InstanceClose(instance);
|
||||||
|
}
|
||||||
} else if (type == ES_MSG_INSTANCE_SAVE_RESPONSE) {
|
} else if (type == ES_MSG_INSTANCE_SAVE_RESPONSE) {
|
||||||
EsMessage m = {};
|
EsMessage m = {};
|
||||||
m.type = ES_MSG_INSTANCE_SAVE;
|
m.type = ES_MSG_INSTANCE_SAVE;
|
||||||
|
@ -1046,11 +1136,15 @@ EsMessage *EsMessageReceive() {
|
||||||
EsInstance *instance = InstanceFromWindowID(message.message.tabOperation.id);
|
EsInstance *instance = InstanceFromWindowID(message.message.tabOperation.id);
|
||||||
|
|
||||||
if (instance) {
|
if (instance) {
|
||||||
|
APIInstance *apiInstance = (APIInstance *) instance->_private;
|
||||||
|
|
||||||
if (message.message.tabOperation.error == ES_SUCCESS) {
|
if (message.message.tabOperation.error == ES_SUCCESS) {
|
||||||
EsRectangle bounds = EsElementGetWindowBounds(instance->window->toolbarSwitcher);
|
EsRectangle bounds = EsElementGetWindowBounds(instance->window->toolbarSwitcher);
|
||||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, bounds.b, INTERFACE_STRING(FileRenameSuccess));
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, bounds.b, INTERFACE_STRING(FileRenameSuccess));
|
||||||
} else {
|
} else {
|
||||||
|
char buffer[512];
|
||||||
const char *errorMessage = interfaceString_FileSaveErrorUnknown;
|
const char *errorMessage = interfaceString_FileSaveErrorUnknown;
|
||||||
|
ptrdiff_t errorMessageBytes = -1;
|
||||||
|
|
||||||
switch (message.message.tabOperation.error) {
|
switch (message.message.tabOperation.error) {
|
||||||
case ES_ERROR_FILE_DOES_NOT_EXIST:
|
case ES_ERROR_FILE_DOES_NOT_EXIST:
|
||||||
|
@ -1068,14 +1162,20 @@ EsMessage *EsMessageReceive() {
|
||||||
case ES_ERROR_INSUFFICIENT_RESOURCES:
|
case ES_ERROR_INSUFFICIENT_RESOURCES:
|
||||||
errorMessage = interfaceString_FileSaveErrorResourcesLow;
|
errorMessage = interfaceString_FileSaveErrorResourcesLow;
|
||||||
break;
|
break;
|
||||||
case ES_ERROR_FILE_ALREADY_EXISTS:
|
|
||||||
errorMessage = interfaceString_FileSaveErrorAlreadyExists;
|
case ES_ERROR_FILE_ALREADY_EXISTS: {
|
||||||
break;
|
errorMessage = buffer;
|
||||||
|
errorMessageBytes = EsStringFormat(buffer, sizeof(buffer), interfaceString_FileSaveErrorAlreadyExists,
|
||||||
|
apiInstance->newNameBytes, apiInstance->newName);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EsDialogShowAlert(instance->window, INTERFACE_STRING(FileCannotRename),
|
EsDialogShowAlert(instance->window, INTERFACE_STRING(FileCannotRename),
|
||||||
errorMessage, -1, ES_ICON_DIALOG_ERROR, ES_DIALOG_ALERT_OK_BUTTON);
|
errorMessage, errorMessageBytes, ES_ICON_DIALOG_ERROR, ES_DIALOG_ALERT_OK_BUTTON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EsHeapFree(apiInstance->newName);
|
||||||
|
apiInstance->newName = nullptr;
|
||||||
}
|
}
|
||||||
} else if (type == ES_MSG_INSTANCE_DOCUMENT_RENAMED) {
|
} else if (type == ES_MSG_INSTANCE_DOCUMENT_RENAMED) {
|
||||||
char *buffer = (char *) EsHeapAllocate(message.message.tabOperation.bytes, false);
|
char *buffer = (char *) EsHeapAllocate(message.message.tabOperation.bytes, false);
|
||||||
|
@ -1279,8 +1379,16 @@ void EsInstanceSaveComplete(EsMessage *message, bool success) {
|
||||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, bounds.b, message, messageBytes);
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, bounds.b, message, messageBytes);
|
||||||
EsHeapFree(message);
|
EsHeapFree(message);
|
||||||
EsCommandSetDisabled(&apiInstance->commandShowInFileManager, false);
|
EsCommandSetDisabled(&apiInstance->commandShowInFileManager, false);
|
||||||
|
|
||||||
|
if (apiInstance->closeAfterSaveCompletes) {
|
||||||
|
EsInstanceDestroy(instance);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
apiInstance->closeAfterSaveCompletes = false;
|
||||||
|
|
||||||
|
char buffer[512];
|
||||||
const char *errorMessage = interfaceString_FileSaveErrorUnknown;
|
const char *errorMessage = interfaceString_FileSaveErrorUnknown;
|
||||||
|
ptrdiff_t errorMessageBytes = -1;
|
||||||
|
|
||||||
switch (message->instanceSave.file->error) {
|
switch (message->instanceSave.file->error) {
|
||||||
case ES_ERROR_FILE_DOES_NOT_EXIST:
|
case ES_ERROR_FILE_DOES_NOT_EXIST:
|
||||||
|
@ -1310,16 +1418,19 @@ void EsInstanceSaveComplete(EsMessage *message, bool success) {
|
||||||
case ES_ERROR_INSUFFICIENT_RESOURCES:
|
case ES_ERROR_INSUFFICIENT_RESOURCES:
|
||||||
errorMessage = interfaceString_FileSaveErrorResourcesLow;
|
errorMessage = interfaceString_FileSaveErrorResourcesLow;
|
||||||
break;
|
break;
|
||||||
case ES_ERROR_FILE_ALREADY_EXISTS:
|
|
||||||
errorMessage = interfaceString_FileSaveErrorAlreadyExists;
|
|
||||||
break;
|
|
||||||
case ES_ERROR_TOO_MANY_FILES_WITH_NAME:
|
case ES_ERROR_TOO_MANY_FILES_WITH_NAME:
|
||||||
errorMessage = interfaceString_FileSaveErrorTooManyFiles;
|
errorMessage = interfaceString_FileSaveErrorTooManyFiles;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ES_ERROR_FILE_ALREADY_EXISTS: {
|
||||||
|
errorMessage = buffer;
|
||||||
|
errorMessageBytes = EsStringFormat(buffer, sizeof(buffer), interfaceString_FileSaveErrorAlreadyExists,
|
||||||
|
apiInstance->newNameBytes, apiInstance->newName);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EsDialogShowAlert(instance->window, INTERFACE_STRING(FileCannotSave),
|
EsDialogShowAlert(instance->window, INTERFACE_STRING(FileCannotSave),
|
||||||
errorMessage, -1, ES_ICON_DIALOG_ERROR, ES_DIALOG_ALERT_OK_BUTTON);
|
errorMessage, errorMessageBytes, ES_ICON_DIALOG_ERROR, ES_DIALOG_ALERT_OK_BUTTON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1226,7 +1226,7 @@ void ShutdownModalCreate() {
|
||||||
EsTextDisplayCreate(EsPanelCreate(dialog, ES_PANEL_VERTICAL | ES_CELL_H_FILL, ES_STYLE_DIALOG_CONTENT),
|
EsTextDisplayCreate(EsPanelCreate(dialog, ES_PANEL_VERTICAL | ES_CELL_H_FILL, ES_STYLE_DIALOG_CONTENT),
|
||||||
ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopConfirmShutdown))->cName = "dialog contents";
|
ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopConfirmShutdown))->cName = "dialog contents";
|
||||||
EsPanel *buttonArea = EsPanelCreate(dialog, ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_CELL_H_FILL, ES_STYLE_DIALOG_BUTTON_AREA);
|
EsPanel *buttonArea = EsPanelCreate(dialog, ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE | ES_CELL_H_FILL, ES_STYLE_DIALOG_BUTTON_AREA);
|
||||||
EsButton *cancelButton = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT, 0, INTERFACE_STRING(CommonCancel));
|
EsButton *cancelButton = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT | ES_BUTTON_CANCEL, 0, INTERFACE_STRING(CommonCancel));
|
||||||
EsButton *restartButton = EsButtonCreate(buttonArea, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopRestartAction));
|
EsButton *restartButton = EsButtonCreate(buttonArea, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopRestartAction));
|
||||||
EsButton *shutdownButton = EsButtonCreate(buttonArea, ES_FLAGS_DEFAULT, ES_STYLE_PUSH_BUTTON_DANGEROUS, INTERFACE_STRING(DesktopShutdownAction));
|
EsButton *shutdownButton = EsButtonCreate(buttonArea, ES_FLAGS_DEFAULT, ES_STYLE_PUSH_BUTTON_DANGEROUS, INTERFACE_STRING(DesktopShutdownAction));
|
||||||
EsElementFocus(cancelButton);
|
EsElementFocus(cancelButton);
|
||||||
|
|
126
desktop/gui.cpp
126
desktop/gui.cpp
|
@ -443,14 +443,14 @@ struct EsWindow : EsElement {
|
||||||
EsWindowStyle windowStyle;
|
EsWindowStyle windowStyle;
|
||||||
uint32_t windowWidth, windowHeight;
|
uint32_t windowWidth, windowHeight;
|
||||||
|
|
||||||
bool willUpdate, toolbarFillMode, destroyInstanceAfterClose, hasDialog, doNotPaint;
|
bool willUpdate, toolbarFillMode, destroyInstanceAfterClose, doNotPaint;
|
||||||
bool restoreOnNextMove, resetPositionOnNextMove, receivedFirstResize, isMaximised;
|
bool restoreOnNextMove, resetPositionOnNextMove, receivedFirstResize, isMaximised;
|
||||||
bool hovering, activated, appearActivated;
|
bool hovering, activated, appearActivated;
|
||||||
bool visualizeRepaints, visualizeLayoutBounds, visualizePaintSteps; // Inspector properties.
|
bool visualizeRepaints, visualizeLayoutBounds, visualizePaintSteps; // Inspector properties.
|
||||||
|
|
||||||
EsElement *mainPanel, *toolbar;
|
EsElement *mainPanel, *toolbar;
|
||||||
EsPanel *toolbarSwitcher;
|
EsPanel *toolbarSwitcher;
|
||||||
EsElement *dialogWrapper;
|
Array<EsElement *> dialogs;
|
||||||
|
|
||||||
EsPoint mousePosition;
|
EsPoint mousePosition;
|
||||||
|
|
||||||
|
@ -728,6 +728,7 @@ void UIWindowDestroy(EsWindow *window) {
|
||||||
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, window->handle, 0, 0, 0);
|
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, window->handle, 0, 0, 0);
|
||||||
EsHandleClose(window->handle);
|
EsHandleClose(window->handle);
|
||||||
window->checkVisible.Free();
|
window->checkVisible.Free();
|
||||||
|
window->dialogs.Free();
|
||||||
window->handle = ES_INVALID_HANDLE;
|
window->handle = ES_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1918,9 +1919,6 @@ void LayoutTable(EsPanel *panel, EsMessage *message) {
|
||||||
|
|
||||||
EsRectangle insets = panel->GetInsets();
|
EsRectangle insets = panel->GetInsets();
|
||||||
|
|
||||||
#define TABLE_AXIS_HORIZONTAL (0)
|
|
||||||
#define TABLE_AXIS_VERTICAL (1)
|
|
||||||
|
|
||||||
for (int _axis = 0; _axis < 2; _axis++) {
|
for (int _axis = 0; _axis < 2; _axis++) {
|
||||||
int axis = (~panel->flags & ES_PANEL_HORIZONTAL) ? (1 - _axis) : _axis;
|
int axis = (~panel->flags & ES_PANEL_HORIZONTAL) ? (1 - _axis) : _axis;
|
||||||
int gapSize = _axis ? panel->GetGapMinor() : panel->GetGapMajor();
|
int gapSize = _axis ? panel->GetGapMinor() : panel->GetGapMajor();
|
||||||
|
@ -1941,7 +1939,7 @@ void LayoutTable(EsPanel *panel, EsMessage *message) {
|
||||||
size = 0;
|
size = 0;
|
||||||
} else {
|
} else {
|
||||||
int alternate = _axis ? calculatedSize[1 - axis][i] : 0;
|
int alternate = _axis ? calculatedSize[1 - axis][i] : 0;
|
||||||
size = axis == TABLE_AXIS_HORIZONTAL ? child->GetWidth(alternate) : child->GetHeight(alternate);
|
size = axis ? child->GetHeight(alternate) : child->GetWidth(alternate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) EsPrint("\tChild %d (%z) in cells %d->%d has size %d\n", i, child->cName, child->tableCell.from[axis], child->tableCell.to[axis], size);
|
if (debug) EsPrint("\tChild %d (%z) in cells %d->%d has size %d\n", i, child->cName, child->tableCell.from[axis], child->tableCell.to[axis], size);
|
||||||
|
@ -2091,7 +2089,20 @@ void LayoutTable(EsPanel *panel, EsMessage *message) {
|
||||||
calculatedSize[axis][i] = size;
|
calculatedSize[axis][i] = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Calculate the position of the bands.
|
// Step 5: Calculate justification gap.
|
||||||
|
|
||||||
|
if ((axis ? (panel->flags & ES_PANEL_TABLE_V_JUSTIFY) : (panel->flags & ES_PANEL_TABLE_H_JUSTIFY))
|
||||||
|
&& panel->bandCount[axis] > 1 && message->type == ES_MSG_LAYOUT) {
|
||||||
|
int32_t usedSize = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < panel->bandCount[axis]; i++) {
|
||||||
|
usedSize += calculatedProperties[axis][i].preferredSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
gapSize = (in[axis] - usedSize) / (panel->bandCount[axis] - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6: Calculate the position of the bands.
|
||||||
|
|
||||||
int position = insetStart;
|
int position = insetStart;
|
||||||
|
|
||||||
|
@ -2099,14 +2110,14 @@ void LayoutTable(EsPanel *panel, EsMessage *message) {
|
||||||
if (i) position += gapSize;
|
if (i) position += gapSize;
|
||||||
EsPanelBand *band = calculatedProperties[axis] + i;
|
EsPanelBand *band = calculatedProperties[axis] + i;
|
||||||
int size = band->preferredSize;
|
int size = band->preferredSize;
|
||||||
band->maximumSize = position; // Aliasing maximumSize with position.
|
band->maximumSize = position; // HACK Aliasing maximumSize with position.
|
||||||
position += size;
|
position += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
out[axis] = position + insetEnd;
|
out[axis] = position + insetEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6: Move the children to their new location.
|
// Step 7: Move the children to their new location.
|
||||||
|
|
||||||
if (message->type == ES_MSG_GET_WIDTH) {
|
if (message->type == ES_MSG_GET_WIDTH) {
|
||||||
message->measure.width = out[0];
|
message->measure.width = out[0];
|
||||||
|
@ -3513,22 +3524,26 @@ int ProcessDialogClosingMessage(EsElement *element, EsMessage *message) {
|
||||||
|
|
||||||
void EsDialogClose(EsWindow *window) {
|
void EsDialogClose(EsWindow *window) {
|
||||||
EsMessageMutexCheck();
|
EsMessageMutexCheck();
|
||||||
EsAssert(window->hasDialog);
|
EsAssert(window->dialogs.Length());
|
||||||
|
|
||||||
EsAssert(window->dialogWrapper->children[0]->messageClass == ProcessPanelMessage);
|
EsElement *dialog = window->dialogs.Pop();
|
||||||
window->dialogWrapper->children[0]->messageClass = ProcessDialogClosingMessage;
|
|
||||||
EsElementStartTransition(window->dialogWrapper->children[0], ES_TRANSITION_ZOOM_OUT_LIGHT, ES_ELEMENT_TRANSITION_EXIT, 1.0f);
|
|
||||||
|
|
||||||
window->dialogWrapper = nullptr;
|
EsAssert(dialog->messageClass == ProcessPanelMessage);
|
||||||
|
dialog->messageClass = ProcessDialogClosingMessage;
|
||||||
|
EsElementStartTransition(dialog, ES_TRANSITION_ZOOM_OUT_LIGHT, ES_ELEMENT_TRANSITION_EXIT, 1.0f);
|
||||||
|
|
||||||
|
if (!window->dialogs.Length()) {
|
||||||
window->children[0]->children[0]->state &= ~UI_STATE_BLOCK_INTERACTION;
|
window->children[0]->children[0]->state &= ~UI_STATE_BLOCK_INTERACTION;
|
||||||
window->children[1]->state &= ~UI_STATE_BLOCK_INTERACTION;
|
window->children[1]->state &= ~UI_STATE_BLOCK_INTERACTION;
|
||||||
window->hasDialog = false;
|
|
||||||
|
|
||||||
if (window->inactiveFocus) {
|
if (window->inactiveFocus) {
|
||||||
EsElementFocus(window->inactiveFocus, false);
|
EsElementFocus(window->inactiveFocus, false);
|
||||||
window->inactiveFocus->Repaint(true);
|
window->inactiveFocus->Repaint(true);
|
||||||
window->inactiveFocus = nullptr;
|
window->inactiveFocus = nullptr;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
window->dialogs.Last()->state &= ~UI_STATE_BLOCK_INTERACTION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titleBytes,
|
EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titleBytes,
|
||||||
|
@ -3539,7 +3554,7 @@ EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titl
|
||||||
if (!heading) return nullptr;
|
if (!heading) return nullptr;
|
||||||
|
|
||||||
if (iconID) {
|
if (iconID) {
|
||||||
EsIconDisplayCreate(heading, ES_FLAGS_DEFAULT, {}, iconID);
|
EsIconDisplayCreate(heading, ES_FLAGS_DEFAULT, 0, iconID);
|
||||||
}
|
}
|
||||||
|
|
||||||
EsTextDisplayCreate(heading, ES_CELL_H_FILL | ES_CELL_V_CENTER, ES_STYLE_TEXT_HEADING2,
|
EsTextDisplayCreate(heading, ES_CELL_H_FILL | ES_CELL_V_CENTER, ES_STYLE_TEXT_HEADING2,
|
||||||
|
@ -3552,7 +3567,7 @@ EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titl
|
||||||
if (!buttonArea) return nullptr;
|
if (!buttonArea) return nullptr;
|
||||||
|
|
||||||
if (flags & ES_DIALOG_ALERT_OK_BUTTON) {
|
if (flags & ES_DIALOG_ALERT_OK_BUTTON) {
|
||||||
EsButton *button = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT, 0, "OK");
|
EsButton *button = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT | ES_BUTTON_CANCEL, 0, INTERFACE_STRING(CommonOK));
|
||||||
EsButtonOnCommand(button, [] (EsInstance *instance, EsElement *, EsCommand *) { EsDialogClose(instance->window); });
|
EsButtonOnCommand(button, [] (EsInstance *instance, EsElement *, EsCommand *) { EsDialogClose(instance->window); });
|
||||||
EsElementFocus(button);
|
EsElementFocus(button);
|
||||||
}
|
}
|
||||||
|
@ -3562,10 +3577,9 @@ EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titl
|
||||||
|
|
||||||
EsElement *EsDialogShow(EsWindow *window) {
|
EsElement *EsDialogShow(EsWindow *window) {
|
||||||
// TODO Show on a separate window?
|
// TODO Show on a separate window?
|
||||||
// TODO Maybe allow nested dialogs?
|
// TODO Support dialogs owned by other processes.
|
||||||
|
|
||||||
EsAssert(window->windowStyle == ES_WINDOW_NORMAL); // Can only show dialogs on normal windows.
|
EsAssert(window->windowStyle == ES_WINDOW_NORMAL); // Can only show dialogs on normal windows.
|
||||||
EsAssert(!window->hasDialog); // Cannot nest dialogs.
|
|
||||||
|
|
||||||
if (window->focused) {
|
if (window->focused) {
|
||||||
window->inactiveFocus = window->focused;
|
window->inactiveFocus = window->focused;
|
||||||
|
@ -3575,15 +3589,20 @@ EsElement *EsDialogShow(EsWindow *window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EsElement *mainStack = window->children[0];
|
EsElement *mainStack = window->children[0];
|
||||||
|
|
||||||
|
if (!window->dialogs.Length()) {
|
||||||
mainStack->children[0]->state |= UI_STATE_BLOCK_INTERACTION; // Main content.
|
mainStack->children[0]->state |= UI_STATE_BLOCK_INTERACTION; // Main content.
|
||||||
window->children[1]->state |= UI_STATE_BLOCK_INTERACTION; // Toolbar.
|
window->children[1]->state |= UI_STATE_BLOCK_INTERACTION; // Toolbar.
|
||||||
|
} else {
|
||||||
|
window->dialogs.Last()->state |= UI_STATE_BLOCK_INTERACTION;
|
||||||
|
}
|
||||||
|
|
||||||
window->hasDialog = true;
|
EsElement *wrapper = EsPanelCreate(mainStack, ES_PANEL_VERTICAL | ES_CELL_FILL, ES_STYLE_DIALOG_WRAPPER);
|
||||||
window->dialogWrapper = EsPanelCreate(mainStack, ES_PANEL_VERTICAL | ES_CELL_FILL, ES_STYLE_DIALOG_WRAPPER);
|
wrapper->cName = "dialog wrapper";
|
||||||
window->dialogWrapper->cName = "dialog wrapper";
|
EsPanel *dialog = EsPanelCreate(wrapper, ES_PANEL_VERTICAL | ES_CELL_SHRINK, ES_STYLE_DIALOG_SHADOW);
|
||||||
EsPanel *dialog = EsPanelCreate(window->dialogWrapper, ES_PANEL_VERTICAL | ES_CELL_SHRINK, ES_STYLE_DIALOG_SHADOW);
|
|
||||||
dialog->cName = "dialog";
|
dialog->cName = "dialog";
|
||||||
EsElementStartTransition(dialog, ES_TRANSITION_ZOOM_OUT_LIGHT, ES_FLAGS_DEFAULT, 1.0f);
|
EsElementStartTransition(dialog, ES_TRANSITION_ZOOM_OUT_LIGHT, ES_FLAGS_DEFAULT, 1.0f);
|
||||||
|
window->dialogs.Add(dialog);
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
@ -3874,9 +3893,12 @@ int ProcessButtonMessage(EsElement *element, EsMessage *message) {
|
||||||
if (button->window->enterButton == button) {
|
if (button->window->enterButton == button) {
|
||||||
button->customStyleState &= ~THEME_STATE_DEFAULT_BUTTON;
|
button->customStyleState &= ~THEME_STATE_DEFAULT_BUTTON;
|
||||||
button->window->enterButton = button->window->defaultEnterButton;
|
button->window->enterButton = button->window->defaultEnterButton;
|
||||||
|
|
||||||
|
if (button->window->enterButton) {
|
||||||
button->window->enterButton->customStyleState |= THEME_STATE_DEFAULT_BUTTON;
|
button->window->enterButton->customStyleState |= THEME_STATE_DEFAULT_BUTTON;
|
||||||
button->window->enterButton->MaybeRefreshStyle();
|
button->window->enterButton->MaybeRefreshStyle();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (message->type == ES_MSG_GET_INSPECTOR_INFORMATION) {
|
} else if (message->type == ES_MSG_GET_INSPECTOR_INFORMATION) {
|
||||||
EsBufferFormat(message->getContent.buffer, "'%s'", button->labelBytes, button->label);
|
EsBufferFormat(message->getContent.buffer, "'%s'", button->labelBytes, button->label);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3932,7 +3954,9 @@ EsButton *EsButtonCreate(EsElement *parent, uint64_t flags, const EsStyle *style
|
||||||
button->window->defaultEnterButton = button;
|
button->window->defaultEnterButton = button;
|
||||||
button->window->enterButton = button;
|
button->window->enterButton = button;
|
||||||
button->customStyleState |= THEME_STATE_DEFAULT_BUTTON;
|
button->customStyleState |= THEME_STATE_DEFAULT_BUTTON;
|
||||||
} else if (flags & ES_BUTTON_CANCEL) {
|
}
|
||||||
|
|
||||||
|
if (flags & ES_BUTTON_CANCEL) {
|
||||||
button->window->escapeButton = button;
|
button->window->escapeButton = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5330,19 +5354,25 @@ const EsStyle styleFileMenuNameTextbox = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void InstanceRenameFromTextbox(EsWindow *window, APIInstance *instance, EsTextbox *textbox) {
|
||||||
|
size_t newNameBytes;
|
||||||
|
char *newName = EsTextboxGetContents(textbox, &newNameBytes);
|
||||||
|
uint8_t *buffer = (uint8_t *) EsHeapAllocate(1 + newNameBytes, false);
|
||||||
|
buffer[0] = DESKTOP_MSG_RENAME;
|
||||||
|
EsMemoryCopy(buffer + 1, newName, newNameBytes);
|
||||||
|
MessageDesktop(buffer, 1 + newNameBytes, window->handle);
|
||||||
|
EsHeapFree(buffer);
|
||||||
|
EsHeapFree(instance->newName);
|
||||||
|
instance->newName = newName;
|
||||||
|
instance->newNameBytes = newNameBytes;
|
||||||
|
}
|
||||||
|
|
||||||
int FileMenuNameTextboxMessage(EsElement *element, EsMessage *message) {
|
int FileMenuNameTextboxMessage(EsElement *element, EsMessage *message) {
|
||||||
if (message->type == ES_MSG_TEXTBOX_EDIT_END) {
|
if (message->type == ES_MSG_TEXTBOX_EDIT_END) {
|
||||||
APIInstance *instance = (APIInstance *) element->instance->_private;
|
APIInstance *instance = (APIInstance *) element->instance->_private;
|
||||||
|
|
||||||
if (!message->endEdit.rejected && !message->endEdit.unchanged) {
|
if (!message->endEdit.rejected && !message->endEdit.unchanged) {
|
||||||
size_t newNameBytes;
|
InstanceRenameFromTextbox(element->instance->window, instance, instance->fileMenuNameTextbox);
|
||||||
char *newName = EsTextboxGetContents(instance->fileMenuNameTextbox, &newNameBytes);
|
|
||||||
uint8_t *buffer = (uint8_t *) EsHeapAllocate(1 + newNameBytes, false);
|
|
||||||
buffer[0] = DESKTOP_MSG_RENAME;
|
|
||||||
EsMemoryCopy(buffer + 1, newName, newNameBytes);
|
|
||||||
MessageDesktop(buffer, 1 + newNameBytes, element->instance->window->handle);
|
|
||||||
EsHeapFree(buffer);
|
|
||||||
EsHeapFree(newName);
|
|
||||||
EsElementDestroy(element->window);
|
EsElementDestroy(element->window);
|
||||||
} else {
|
} else {
|
||||||
EsPanelSwitchTo(instance->fileMenuNameSwitcher, instance->fileMenuNamePanel, ES_TRANSITION_SLIDE_DOWN);
|
EsPanelSwitchTo(instance->fileMenuNameSwitcher, instance->fileMenuNamePanel, ES_TRANSITION_SLIDE_DOWN);
|
||||||
|
@ -5354,11 +5384,28 @@ int FileMenuNameTextboxMessage(EsElement *element, EsMessage *message) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextboxSelectSectionBeforeFileExtension(EsTextbox *textbox, const char *name, ptrdiff_t nameBytes) {
|
||||||
|
uintptr_t extensionOffset = 0;
|
||||||
|
|
||||||
|
if (nameBytes == -1) {
|
||||||
|
nameBytes = EsCStringLength(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (intptr_t i = 1; i < nameBytes; i++) {
|
||||||
|
if (name[i] == '.') {
|
||||||
|
extensionOffset = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionOffset) {
|
||||||
|
EsTextboxSetSelection(textbox, 0, 0, 0, extensionOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FileMenuRename(EsInstance *_instance, EsElement *, EsCommand *) {
|
void FileMenuRename(EsInstance *_instance, EsElement *, EsCommand *) {
|
||||||
APIInstance *instance = (APIInstance *) _instance->_private;
|
APIInstance *instance = (APIInstance *) _instance->_private;
|
||||||
EsTextboxClear(instance->fileMenuNameTextbox, false);
|
EsTextboxClear(instance->fileMenuNameTextbox, false);
|
||||||
|
|
||||||
uintptr_t extensionOffset = 0;
|
|
||||||
const char *initialName = nullptr;
|
const char *initialName = nullptr;
|
||||||
ptrdiff_t initialNameBytes = 0;
|
ptrdiff_t initialNameBytes = 0;
|
||||||
|
|
||||||
|
@ -5376,17 +5423,10 @@ void FileMenuRename(EsInstance *_instance, EsElement *, EsCommand *) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EsTextboxInsert(instance->fileMenuNameTextbox, initialName, initialNameBytes, false);
|
EsTextboxInsert(instance->fileMenuNameTextbox, initialName, initialNameBytes, false);
|
||||||
|
|
||||||
for (intptr_t i = 1; i < initialNameBytes; i++) {
|
|
||||||
if (initialName[i] == '.') {
|
|
||||||
extensionOffset = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EsPanelSwitchTo(instance->fileMenuNameSwitcher, instance->fileMenuNameTextbox, ES_TRANSITION_SLIDE_UP);
|
EsPanelSwitchTo(instance->fileMenuNameSwitcher, instance->fileMenuNameTextbox, ES_TRANSITION_SLIDE_UP);
|
||||||
EsElementFocus(instance->fileMenuNameTextbox);
|
EsElementFocus(instance->fileMenuNameTextbox);
|
||||||
EsTextboxStartEdit(instance->fileMenuNameTextbox);
|
EsTextboxStartEdit(instance->fileMenuNameTextbox);
|
||||||
if (extensionOffset) EsTextboxSetSelection(instance->fileMenuNameTextbox, 0, 0, 0, extensionOffset);
|
TextboxSelectSectionBeforeFileExtension(instance->fileMenuNameTextbox, initialName, initialNameBytes);
|
||||||
instance->fileMenuNameTextbox->messageUser = FileMenuNameTextboxMessage;
|
instance->fileMenuNameTextbox->messageUser = FileMenuNameTextboxMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6577,7 +6617,7 @@ int AccessKeyLayerMessage(EsElement *element, EsMessage *message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccessKeyModeEnter(EsWindow *window) {
|
void AccessKeyModeEnter(EsWindow *window) {
|
||||||
if (window->hasDialog || gui.menuMode || gui.accessKeyMode || window->windowStyle != ES_WINDOW_NORMAL) {
|
if (window->dialogs.Length() || gui.menuMode || gui.accessKeyMode || window->windowStyle != ES_WINDOW_NORMAL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6795,7 +6835,7 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window->hasDialog) {
|
if (!window->dialogs.Length()) {
|
||||||
// TODO Sort out what commands can be used from within dialogs and menus.
|
// TODO Sort out what commands can be used from within dialogs and menus.
|
||||||
|
|
||||||
if (!gui.keyboardShortcutNames.itemCount) UIInitialiseKeyboardShortcutNamesTable();
|
if (!gui.keyboardShortcutNames.itemCount) UIInitialiseKeyboardShortcutNamesTable();
|
||||||
|
|
|
@ -475,15 +475,8 @@ define ES_PANEL_SWITCHER_MEASURE_SHOWN (0 << 15) // Use the shown child to det
|
||||||
define ES_PANEL_SWITCHER_MEASURE_LARGEST (1 << 15) // Use the largest child to determine size.
|
define ES_PANEL_SWITCHER_MEASURE_LARGEST (1 << 15) // Use the largest child to determine size.
|
||||||
|
|
||||||
// For ES_PANEL_TABLE.
|
// For ES_PANEL_TABLE.
|
||||||
// TODO Implement these!
|
define ES_PANEL_TABLE_H_JUSTIFY (1 << 16)
|
||||||
define ES_PANEL_H_LEFT (1 << 16)
|
define ES_PANEL_TABLE_V_JUSTIFY (1 << 17)
|
||||||
define ES_PANEL_H_RIGHT (1 << 17)
|
|
||||||
define ES_PANEL_H_CENTER (1 << 18)
|
|
||||||
define ES_PANEL_H_JUSTIFY (1 << 19)
|
|
||||||
define ES_PANEL_V_TOP (1 << 20)
|
|
||||||
define ES_PANEL_V_BOTTOM (1 << 21)
|
|
||||||
define ES_PANEL_V_CENTER (1 << 22)
|
|
||||||
define ES_PANEL_V_JUSTIFY (1 << 23)
|
|
||||||
|
|
||||||
define ES_PANEL_RADIO_GROUP (1 << 30) // Determines how arrow keys/tabs behave.
|
define ES_PANEL_RADIO_GROUP (1 << 30) // Determines how arrow keys/tabs behave.
|
||||||
|
|
||||||
|
|
|
@ -85,14 +85,6 @@ const EsStyle styleSettingsNumberTextbox = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const EsStyle styleSettingsTable = {
|
|
||||||
.metrics = {
|
|
||||||
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_GAP_MINOR,
|
|
||||||
.gapMajor = 7,
|
|
||||||
.gapMinor = 7,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const EsStyle styleSettingsCheckboxGroup = {
|
const EsStyle styleSettingsCheckboxGroup = {
|
||||||
.metrics = {
|
.metrics = {
|
||||||
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_GAP_MINOR,
|
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_GAP_MINOR,
|
||||||
|
@ -307,7 +299,7 @@ void SettingsPageUnimplemented(EsElement *element, SettingsPage *page) {
|
||||||
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
||||||
SettingsAddTitle(container, page);
|
SettingsAddTitle(container, page);
|
||||||
|
|
||||||
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
||||||
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
||||||
}
|
}
|
||||||
|
@ -529,7 +521,7 @@ void SettingsPageMouse(EsElement *element, SettingsPage *page) {
|
||||||
SettingsAddSlider(container, INTERFACE_STRING(DesktopSettingsMouseCursorTrails), 'T', "general", "cursor_trails", 0, 7, 8,
|
SettingsAddSlider(container, INTERFACE_STRING(DesktopSettingsMouseCursorTrails), 'T', "general", "cursor_trails", 0, 7, 8,
|
||||||
INTERFACE_STRING(DesktopSettingsMouseCursorTrailsNone), INTERFACE_STRING(DesktopSettingsMouseCursorTrailsMany));
|
INTERFACE_STRING(DesktopSettingsMouseCursorTrailsNone), INTERFACE_STRING(DesktopSettingsMouseCursorTrailsMany));
|
||||||
|
|
||||||
table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsPanelSetBands(table, 2);
|
EsPanelSetBands(table, 2);
|
||||||
|
|
||||||
SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsMouseLinesPerScrollNotch), 'S', "general", "scroll_lines_per_notch",
|
SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsMouseLinesPerScrollNotch), 'S', "general", "scroll_lines_per_notch",
|
||||||
|
@ -542,7 +534,7 @@ void SettingsPageMouse(EsElement *element, SettingsPage *page) {
|
||||||
|
|
||||||
EsSpacerCreate(container, ES_CELL_H_FILL, ES_STYLE_BUTTON_GROUP_SEPARATOR);
|
EsSpacerCreate(container, ES_CELL_H_FILL, ES_STYLE_BUTTON_GROUP_SEPARATOR);
|
||||||
|
|
||||||
table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsPanelSetBands(table, 2);
|
EsPanelSetBands(table, 2);
|
||||||
|
|
||||||
SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsMouseDoubleClickSpeed), 'D', "general", "click_chain_timeout_ms",
|
SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsMouseDoubleClickSpeed), 'D', "general", "click_chain_timeout_ms",
|
||||||
|
@ -561,11 +553,11 @@ void SettingsPageKeyboard(EsElement *element, SettingsPage *page) {
|
||||||
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
||||||
SettingsAddTitle(container, page);
|
SettingsAddTitle(container, page);
|
||||||
|
|
||||||
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
||||||
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
||||||
|
|
||||||
EsPanel *table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsPanelSetBands(table, 2);
|
EsPanelSetBands(table, 2);
|
||||||
|
|
||||||
EsTextbox *textbox;
|
EsTextbox *textbox;
|
||||||
|
@ -606,11 +598,11 @@ void SettingsPageDisplay(EsElement *element, SettingsPage *page) {
|
||||||
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
||||||
SettingsAddTitle(container, page);
|
SettingsAddTitle(container, page);
|
||||||
|
|
||||||
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
||||||
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
||||||
|
|
||||||
EsPanel *table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsPanelSetBands(table, 2);
|
EsPanelSetBands(table, 2);
|
||||||
SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsDisplayUIScale), 'S', "general", "ui_scale",
|
SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsDisplayUIScale), 'S', "general", "ui_scale",
|
||||||
100, 400, INTERFACE_STRING(CommonUnitPercent), 0.05, 5);
|
100, 400, INTERFACE_STRING(CommonUnitPercent), 0.05, 5);
|
||||||
|
@ -687,11 +679,11 @@ void SettingsPageTheme(EsElement *element, SettingsPage *page) {
|
||||||
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
||||||
SettingsAddTitle(container, page);
|
SettingsAddTitle(container, page);
|
||||||
|
|
||||||
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
||||||
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
||||||
|
|
||||||
EsPanel *table = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
EsPanel *table = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
|
||||||
EsPanelSetBands(table, 2);
|
EsPanelSetBands(table, 2);
|
||||||
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, 0, INTERFACE_STRING(DesktopSettingsThemeWallpaper));
|
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, 0, INTERFACE_STRING(DesktopSettingsThemeWallpaper));
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ private define ES_STYLE_PANEL_CONTAINER_WINDOW_ROOT (ES_STYLE_CAST(1307))
|
||||||
private define ES_STYLE_PANEL_CRASH_INFO (ES_STYLE_CAST(1309))
|
private define ES_STYLE_PANEL_CRASH_INFO (ES_STYLE_CAST(1309))
|
||||||
define ES_STYLE_PANEL_DOCUMENT (ES_STYLE_CAST(1547))
|
define ES_STYLE_PANEL_DOCUMENT (ES_STYLE_CAST(1547))
|
||||||
define ES_STYLE_PANEL_FILLED (ES_STYLE_CAST(1313))
|
define ES_STYLE_PANEL_FILLED (ES_STYLE_CAST(1313))
|
||||||
|
define ES_STYLE_PANEL_FORM_TABLE (ES_STYLE_CAST(1671))
|
||||||
define ES_STYLE_PANEL_GROUP_BOX (ES_STYLE_CAST(1315))
|
define ES_STYLE_PANEL_GROUP_BOX (ES_STYLE_CAST(1315))
|
||||||
define ES_STYLE_PANEL_INSET (ES_STYLE_CAST(1641))
|
define ES_STYLE_PANEL_INSET (ES_STYLE_CAST(1641))
|
||||||
private define ES_STYLE_PANEL_INSPECTOR_WINDOW_CONTAINER (ES_STYLE_CAST(1317))
|
private define ES_STYLE_PANEL_INSPECTOR_WINDOW_CONTAINER (ES_STYLE_CAST(1317))
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -5,12 +5,15 @@
|
||||||
|
|
||||||
#define ELLIPSIS "…"
|
#define ELLIPSIS "…"
|
||||||
#define HYPHENATION_POINT "‧"
|
#define HYPHENATION_POINT "‧"
|
||||||
|
#define OPEN_SPEECH "\u201C"
|
||||||
|
#define CLOSE_SPEECH "\u201D"
|
||||||
#define SYSTEM_BRAND_SHORT "Essence"
|
#define SYSTEM_BRAND_SHORT "Essence"
|
||||||
|
|
||||||
// Common.
|
// Common.
|
||||||
|
|
||||||
DEFINE_INTERFACE_STRING(CommonErrorTitle, "Error");
|
DEFINE_INTERFACE_STRING(CommonErrorTitle, "Error");
|
||||||
|
|
||||||
|
DEFINE_INTERFACE_STRING(CommonOK, "OK");
|
||||||
DEFINE_INTERFACE_STRING(CommonCancel, "Cancel");
|
DEFINE_INTERFACE_STRING(CommonCancel, "Cancel");
|
||||||
|
|
||||||
DEFINE_INTERFACE_STRING(CommonUndo, "Undo");
|
DEFINE_INTERFACE_STRING(CommonUndo, "Undo");
|
||||||
|
@ -162,7 +165,7 @@ DEFINE_INTERFACE_STRING(FileSaveErrorTooLarge, "The drive does not support files
|
||||||
DEFINE_INTERFACE_STRING(FileSaveErrorConcurrentAccess, "Another application is modifying the file.");
|
DEFINE_INTERFACE_STRING(FileSaveErrorConcurrentAccess, "Another application is modifying the file.");
|
||||||
DEFINE_INTERFACE_STRING(FileSaveErrorDriveFull, "The drive is full. Try deleting some files to free up space.");
|
DEFINE_INTERFACE_STRING(FileSaveErrorDriveFull, "The drive is full. Try deleting some files to free up space.");
|
||||||
DEFINE_INTERFACE_STRING(FileSaveErrorResourcesLow, "The system is low on resources. Close some applcations and try again.");
|
DEFINE_INTERFACE_STRING(FileSaveErrorResourcesLow, "The system is low on resources. Close some applcations and try again.");
|
||||||
DEFINE_INTERFACE_STRING(FileSaveErrorAlreadyExists, "There is already a file with this name.");
|
DEFINE_INTERFACE_STRING(FileSaveErrorAlreadyExists, "There is already a file called " OPEN_SPEECH "%s" CLOSE_SPEECH " in this folder.");
|
||||||
DEFINE_INTERFACE_STRING(FileSaveErrorTooManyFiles, "Too many files already have the same name.");
|
DEFINE_INTERFACE_STRING(FileSaveErrorTooManyFiles, "Too many files already have the same name.");
|
||||||
DEFINE_INTERFACE_STRING(FileSaveErrorUnknown, "An unknown error occurred. Please try again later.");
|
DEFINE_INTERFACE_STRING(FileSaveErrorUnknown, "An unknown error occurred. Please try again later.");
|
||||||
|
|
||||||
|
@ -171,6 +174,14 @@ DEFINE_INTERFACE_STRING(FileLoadErrorDrive, "The drive containing the file was u
|
||||||
DEFINE_INTERFACE_STRING(FileLoadErrorResourcesLow, "The system is low on resources. Close some applcations and try again.");
|
DEFINE_INTERFACE_STRING(FileLoadErrorResourcesLow, "The system is low on resources. Close some applcations and try again.");
|
||||||
DEFINE_INTERFACE_STRING(FileLoadErrorUnknown, "An unknown error occurred. Please try again later.");
|
DEFINE_INTERFACE_STRING(FileLoadErrorUnknown, "An unknown error occurred. Please try again later.");
|
||||||
|
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseWithModificationsTitle, "Do you want to save this document?");
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseWithModificationsContent, "You need to save your changes to " OPEN_SPEECH "%s" CLOSE_SPEECH " before you can close it.");
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseWithModificationsSave, "Save and close");
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseWithModificationsDelete, "Discard");
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseNewTitle, "Do you want to keep this document?");
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseNewContent, "You need to save it before you can close " OPEN_SPEECH "%s" CLOSE_SPEECH ".");
|
||||||
|
DEFINE_INTERFACE_STRING(FileCloseNewName, "Name:");
|
||||||
|
|
||||||
// Image Editor.
|
// Image Editor.
|
||||||
|
|
||||||
DEFINE_INTERFACE_STRING(ImageEditorToolBrush, "Brush");
|
DEFINE_INTERFACE_STRING(ImageEditorToolBrush, "Brush");
|
||||||
|
|
Loading…
Reference in New Issue