rename button in file menu

This commit is contained in:
nakst 2021-09-13 12:06:14 +01:00
parent b66cdda741
commit c166eee594
6 changed files with 324 additions and 120 deletions

View File

@ -590,6 +590,29 @@ void _start() {
EsHandleClose(message->user.context1.u);
EsHeapFree(_path);
} else if (message->type == ES_MSG_FILE_MANAGER_PATH_MOVED) {
char *data = (char *) EsHeapAllocate(message->user.context2.u, false);
uintptr_t *bytes = (uintptr_t *) data;
char *paths = data + sizeof(size_t) * 2;
EsConstantBufferRead(message->user.context1.u, data);
String oldPath = StringFromLiteralWithSize(paths, bytes[0]);
String newPath = StringFromLiteralWithSize(paths + bytes[0], bytes[1]);
FolderPathMoved(oldPath, newPath, false);
size_t pathSectionCount;
pathSectionCount = PathCountSections(oldPath);
for (uintptr_t i = 0; i < pathSectionCount; i++) {
FolderFileUpdatedAtPath(PathGetParent(oldPath, i + 1), nullptr);
}
pathSectionCount = PathCountSections(newPath);
for (uintptr_t i = 0; i < pathSectionCount; i++) {
FolderFileUpdatedAtPath(PathGetParent(newPath, i + 1), nullptr);
}
EsHeapFree(data);
} else if (message->type == MESSAGE_BLOCKING_TASK_COMPLETE) {
Instance *instance = (Instance *) message->user.context1.p;
if (message->user.context2.u == instance->blockingTaskID) BlockingTaskComplete(instance);

View File

@ -63,6 +63,7 @@ struct EnumString { const char *cName; int value; };
#define DESKTOP_MSG_UNHANDLED_KEY_EVENT (15)
#define DESKTOP_MSG_START_USER_TASK (16)
#define DESKTOP_MSG_SET_PROGRESS (17)
#define DESKTOP_MSG_RENAME (18)
struct EsFileStore {
#define FILE_STORE_HANDLE (1)
@ -218,6 +219,11 @@ struct APIInstance {
EsInstanceClassEditorSettings editorSettings;
EsInstanceClassViewerSettings viewerSettings;
};
// For the file menu.
EsPanel *fileMenuNameSwitcher;
EsPanel *fileMenuNamePanel;
EsTextbox *fileMenuNameTextbox;
};
MountPoint *NodeAddMountPoint(const char *prefix, size_t prefixBytes, EsHandle base, bool queryInformation) {
@ -982,6 +988,41 @@ EsMessage *EsMessageReceive() {
EsHandleClose(message.message.tabOperation.handle);
}
}
} else if (type == ES_MSG_INSTANCE_RENAME_RESPONSE) {
EsInstance *instance = InstanceFromWindowID(message.message.tabOperation.id);
if (instance) {
if (message.message.tabOperation.error == ES_SUCCESS) {
EsRectangle bounds = EsElementGetWindowBounds(instance->window->toolbarSwitcher);
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, bounds.b, INTERFACE_STRING(FileRenameSuccess));
} else {
const char *errorMessage = interfaceString_FileSaveErrorUnknown;
switch (message.message.tabOperation.error) {
case ES_ERROR_FILE_DOES_NOT_EXIST:
case ES_ERROR_NODE_DELETED:
case ES_ERROR_PERMISSION_NOT_GRANTED:
case ES_ERROR_INCORRECT_NODE_TYPE:
errorMessage = interfaceString_FileSaveErrorFileDeleted;
break;
case ES_ERROR_DRIVE_ERROR_FILE_DAMAGED:
errorMessage = interfaceString_FileSaveErrorCorrupt;
break;
case ES_ERROR_DRIVE_CONTROLLER_REPORTED:
errorMessage = interfaceString_FileSaveErrorDrive;
break;
case ES_ERROR_INSUFFICIENT_RESOURCES:
errorMessage = interfaceString_FileSaveErrorResourcesLow;
break;
case ES_ERROR_FILE_ALREADY_EXISTS:
errorMessage = interfaceString_FileSaveErrorAlreadyExists;
break;
}
EsDialogShowAlert(instance->window, INTERFACE_STRING(FileCannotRename),
errorMessage, -1, ES_ICON_DIALOG_ERROR, ES_DIALOG_ALERT_OK_BUTTON);
}
}
} else if (type == ES_MSG_INSTANCE_DOCUMENT_RENAMED) {
char *buffer = (char *) EsHeapAllocate(message.message.tabOperation.bytes, false);
@ -1202,6 +1243,9 @@ void EsInstanceSaveComplete(EsMessage *message, bool success) {
case ES_ERROR_FILE_ALREADY_EXISTS:
errorMessage = interfaceString_FileSaveErrorAlreadyExists;
break;
case ES_ERROR_TOO_MANY_FILES_WITH_NAME:
errorMessage = interfaceString_FileSaveErrorTooManyFiles;
break;
}
EsDialogShowAlert(instance->window, INTERFACE_STRING(FileCannotSave),

View File

@ -1624,7 +1624,7 @@ EsError TemporaryFileCreate(EsHandle *handle, char **path, size_t *pathBytes, ui
return file.error;
}
void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *newName, size_t newNameBytes) {
void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *newName, size_t newNameBytes, bool failIfAlreadyExists) {
if (!instance->processHandle) return;
EsMessage m = {};
@ -1640,9 +1640,9 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
EsHeapFree(folder);
size_t nameBytes = EsPathFindUniqueName(name, folderBytes + newNameBytes, folderBytes + newNameBytes + 32);
if (!nameBytes) {
if (!nameBytes || (failIfAlreadyExists && nameBytes != folderBytes + newNameBytes)) {
EsHeapFree(name);
m.tabOperation.error = ES_ERROR_FILE_ALREADY_EXISTS;
m.tabOperation.error = nameBytes ? ES_ERROR_FILE_ALREADY_EXISTS : ES_ERROR_TOO_MANY_FILES_WITH_NAME;
EsMessagePostRemote(instance->processHandle, &m);
return;
}
@ -1710,22 +1710,10 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
EsMessagePostRemote(instance->processHandle, &m);
}
void InstanceAnnouncePathMoved(InstalledApplication *fromApplication, const uint8_t *buffer, size_t embedWindowMessageBytes) {
void InstanceAnnouncePathMoved(InstalledApplication *fromApplication, const char *oldPath, size_t oldPathBytes, const char *newPath, size_t newPathBytes) {
// TODO Update the location of installed applications and other things in the configuration.
// TODO Replace fromApplication with something better.
uintptr_t oldPathBytes, newPathBytes;
EsMemoryCopy(&oldPathBytes, buffer + 1, sizeof(uintptr_t));
EsMemoryCopy(&newPathBytes, buffer + 1 + sizeof(uintptr_t), sizeof(uintptr_t));
if (oldPathBytes >= 0x4000 || newPathBytes >= 0x4000
|| oldPathBytes + newPathBytes + sizeof(uintptr_t) * 2 + 1 != embedWindowMessageBytes) {
return;
}
const char *oldPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2;
const char *newPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes;
EsObjectID documentID = 0;
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
@ -1769,6 +1757,20 @@ void InstanceAnnouncePathMoved(InstalledApplication *fromApplication, const uint
m.tabOperation.bytes = newPathBytes - newNameOffset;
EsMessagePostRemote(instance->processHandle, &m);
}
if (fromApplication != desktop.fileManager && desktop.fileManager && desktop.fileManager->singleProcessHandle) {
char *data = (char *) EsHeapAllocate(sizeof(size_t) * 2 + oldPathBytes + newPathBytes, false);
EsMemoryCopy(data + 0, &oldPathBytes, sizeof(size_t));
EsMemoryCopy(data + sizeof(size_t), &newPathBytes, sizeof(size_t));
EsMemoryCopy(data + sizeof(size_t) * 2, oldPath, oldPathBytes);
EsMemoryCopy(data + sizeof(size_t) * 2 + oldPathBytes, newPath, newPathBytes);
EsMessage m = {};
m.type = ES_MSG_FILE_MANAGER_PATH_MOVED;
m.user.context2 = sizeof(size_t) * 2 + oldPathBytes + newPathBytes;
m.user.context1 = EsConstantBufferCreate(data, m.user.context2.u, desktop.fileManager->singleProcessHandle);
EsMessagePostRemote(desktop.fileManager->singleProcessHandle, &m);
EsHeapFree(data);
}
}
void ApplicationInstanceCompleteSave(ApplicationInstance *fromInstance) {
@ -2253,7 +2255,19 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
InstanceAnnouncePathMoved(application, buffer, message->desktop.bytes);
uintptr_t oldPathBytes, newPathBytes;
EsMemoryCopy(&oldPathBytes, buffer + 1, sizeof(uintptr_t));
EsMemoryCopy(&newPathBytes, buffer + 1 + sizeof(uintptr_t), sizeof(uintptr_t));
if (oldPathBytes >= 0x4000 || newPathBytes >= 0x4000
|| oldPathBytes + newPathBytes + sizeof(uintptr_t) * 2 + 1 != message->desktop.bytes) {
return;
}
const char *oldPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2;
const char *newPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes;
InstanceAnnouncePathMoved(application, oldPath, oldPathBytes, newPath, newPathBytes);
}
} else if (buffer[0] == DESKTOP_MSG_START_USER_TASK && pipe) {
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
@ -2335,7 +2349,39 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
EsElementRepaint(desktop.tasksButton);
}
} else if (buffer[0] == DESKTOP_MSG_REQUEST_SAVE) {
ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, message->desktop.bytes - 1);
ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, message->desktop.bytes - 1, false);
} else if (buffer[0] == DESKTOP_MSG_RENAME) {
const char *newName = (const char *) buffer + 1;
size_t newNameBytes = message->desktop.bytes - 1;
OpenDocument *document = desktop.openDocuments.Get(&instance->documentID);
if (!instance->documentID) {
ApplicationInstanceRequestSave(instance, newName, newNameBytes, true);
} else if (document) {
size_t folderBytes = 0, oldPathBytes, newPathBytes;
for (uintptr_t i = 0; i < document->pathBytes; i++) {
if (document->path[i] == '/') {
folderBytes = i;
}
}
char *oldPath = EsStringAllocateAndFormat(&oldPathBytes, "%s", document->pathBytes, document->path);
char *newPath = EsStringAllocateAndFormat(&newPathBytes, "%s/%s", folderBytes, document->path, newNameBytes, newName);
EsMessage m = {};
m.type = ES_MSG_INSTANCE_RENAME_RESPONSE;
m.tabOperation.id = instance->embeddedWindowID;
m.tabOperation.error = EsPathMove(oldPath, oldPathBytes, newPath, newPathBytes);
EsMessagePostRemote(instance->processHandle, &m);
if (m.tabOperation.error == ES_SUCCESS) {
InstanceAnnouncePathMoved(nullptr, oldPath, oldPathBytes, newPath, newPathBytes);
}
EsHeapFree(oldPath);
EsHeapFree(newPath);
}
} else if (buffer[0] == DESKTOP_MSG_COMPLETE_SAVE) {
ApplicationInstanceCompleteSave(instance);
} else if (buffer[0] == DESKTOP_MSG_SHOW_IN_FILE_MANAGER) {

View File

@ -1072,105 +1072,6 @@ void EsMenuCloseAll() {
}
}
// --------------------------------- File menu.
const EsStyle styleFileMenuDocumentInformationPanel1 = {
.metrics = {
.mask = ES_THEME_METRICS_INSETS | ES_THEME_METRICS_GAP_MAJOR,
.insets = ES_RECT_4(10, 10, 5, 5),
.gapMajor = 5,
},
};
const EsStyle styleFileMenuDocumentInformationPanel2 = {
.metrics = {
.mask = ES_THEME_METRICS_GAP_MAJOR,
.gapMajor = 5,
},
};
void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
// TODO Make this user-customizable?
// const EsFileMenuSettings *settings = (const EsFileMenuSettings *) element->userData.p;
APIInstance *instance = (APIInstance *) _instance->_private;
EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR);
EsInstanceClassEditorSettings *editorSettings = &instance->editorSettings;
bool newDocument = !instance->startupInformation || !instance->startupInformation->filePath;
EsMenu *menu = EsMenuCreate(element, ES_FLAGS_DEFAULT);
if (!menu) return;
EsPanel *panel1 = EsPanelCreate(menu, ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel1);
if (!panel1) goto show;
{
// TODO Get this icon from the file type database?
// We'll probably need Desktop to send this via EsApplicationStartupInformation and when the file is renamed.
EsIconDisplayCreate(panel1, ES_FLAGS_DEFAULT, 0, editorSettings->documentIconID);
EsSpacerCreate(panel1, ES_FLAGS_DEFAULT, 0, 5, 0);
EsPanel *panel2 = EsPanelCreate(panel1, ES_FLAGS_DEFAULT, &styleFileMenuDocumentInformationPanel2);
if (!panel2) goto show;
EsPanel *panel3 = EsPanelCreate(panel2, ES_PANEL_HORIZONTAL | ES_PANEL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel3) goto show;
if (newDocument) {
EsTextDisplayCreate(panel3, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL,
editorSettings->newDocumentTitle, editorSettings->newDocumentTitleBytes);
} else {
EsTextDisplayCreate(panel3, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL,
instance->startupInformation->filePath, instance->startupInformation->filePathBytes);
}
EsButton *renameButton = EsButtonCreate(panel3, ES_BUTTON_TOOLBAR); // TODO.
if (!renameButton) goto show;
EsButtonSetIcon(renameButton, ES_ICON_DOCUMENT_EDIT_SYMBOLIC);
if (!newDocument) {
EsPanel *panel4 = EsPanelCreate(panel2, ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel4) goto show;
EsPanelSetBands(panel4, 2 /* columns */);
char buffer[64];
size_t bytes;
bytes = EsStringFormat(buffer, sizeof(buffer), "%D", EsFileStoreGetSize(instance->fileStore));
EsTextDisplayCreate(panel4, ES_CELL_H_RIGHT, ES_STYLE_TEXT_LABEL_SECONDARY, INTERFACE_STRING(CommonFileMenuFileSize));
EsTextDisplayCreate(panel4, ES_CELL_H_LEFT, ES_STYLE_TEXT_LABEL, buffer, bytes);
// TODO Modification date, author, etc.
}
}
EsMenuAddSeparator(menu);
if (instance->instanceClass == ES_INSTANCE_CLASS_EDITOR) {
if (instance->commandSave.disabled) {
EsMenuAddItem(menu, ES_ELEMENT_DISABLED, INTERFACE_STRING(CommonFileUnchanged));
} else {
EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileSave), &instance->commandSave);
}
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileMakeCopy)); // TODO.
EsMenuAddSeparator(menu);
}
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShare)); // TODO.
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileVersionHistory)); // TODO.
EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShowInFileManager), &instance->commandShowInFileManager);
show: EsMenuShow(menu);
}
void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings) {
EsButton *button = EsButtonCreate(element, ES_BUTTON_DROPDOWN, 0, INTERFACE_STRING(CommonFileMenu));
if (!button) return;
button->accessKey = 'F';
button->userData = (void *) settings;
EsButtonOnCommand(button, FileMenuCreate);
}
// --------------------------------- Paint targets.
bool EsPaintTargetTake(EsPaintTarget *target, size_t width, size_t height, bool hasAlphaChannel = true) {
@ -3132,7 +3033,8 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
for (uintptr_t i = 0; i < element->GetChildCount(); i++) {
EsElement *child = element->GetChild(i);
if (child->flags & (ES_ELEMENT_HIDDEN | ES_ELEMENT_NON_CLIENT)) continue;
if (child->flags & ES_ELEMENT_NON_CLIENT) continue;
if ((child->flags & ES_ELEMENT_HIDDEN) && (~panel->flags & ES_PANEL_SWITCHER_MEASURE_LARGEST)) continue;
int size = child->GetWidth(message->measure.height);
if (size > maximum) maximum = size;
}
@ -3153,7 +3055,8 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
for (uintptr_t i = 0; i < element->GetChildCount(); i++) {
EsElement *child = element->GetChild(i);
if (child->flags & (ES_ELEMENT_HIDDEN | ES_ELEMENT_NON_CLIENT)) continue;
if (child->flags & ES_ELEMENT_NON_CLIENT) continue;
if ((child->flags & ES_ELEMENT_HIDDEN) && (~panel->flags & ES_PANEL_SWITCHER_MEASURE_LARGEST)) continue;
int size = child->GetHeight(message->measure.width);
if (size > maximum) maximum = size;
}
@ -5237,6 +5140,183 @@ EsSlider *EsSliderCreate(EsElement *parent, uint64_t flags, const EsStyle *style
return slider;
}
// --------------------------------- File menu.
const EsStyle styleFileMenuDocumentInformationPanel1 = {
.metrics = {
.mask = ES_THEME_METRICS_INSETS | ES_THEME_METRICS_GAP_MAJOR,
.insets = ES_RECT_4(10, 10, 5, 5),
.gapMajor = 5,
},
};
const EsStyle styleFileMenuDocumentInformationPanel2 = {
.metrics = {
.mask = ES_THEME_METRICS_GAP_MAJOR,
.gapMajor = 5,
},
};
const EsStyle styleFileMenuNameTextbox = {
.inherit = ES_STYLE_TEXTBOX_TRANSPARENT,
.metrics = {
.mask = ES_THEME_METRICS_PREFERRED_WIDTH,
.preferredWidth = 0,
},
};
int FileMenuNameTextboxMessage(EsElement *element, EsMessage *message) {
if (message->type == ES_MSG_TEXTBOX_EDIT_END) {
APIInstance *instance = (APIInstance *) element->instance->_private;
if (!message->endEdit.rejected) {
size_t newNameBytes;
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);
} else {
EsPanelSwitchTo(instance->fileMenuNameSwitcher, instance->fileMenuNamePanel, ES_TRANSITION_SLIDE_DOWN);
}
return ES_HANDLED;
}
return 0;
}
void FileMenuRename(EsInstance *_instance, EsElement *, EsCommand *) {
APIInstance *instance = (APIInstance *) _instance->_private;
EsTextboxClear(instance->fileMenuNameTextbox, false);
uintptr_t extensionOffset = 0;
const char *initialName = nullptr;
ptrdiff_t initialNameBytes = 0;
if (instance->startupInformation && instance->startupInformation->filePathBytes) {
initialName = instance->startupInformation->filePath;
initialNameBytes = instance->startupInformation->filePathBytes;
} else {
EsInstanceClassEditorSettings *editorSettings = &instance->editorSettings;
initialName = editorSettings->newDocumentFileName;
initialNameBytes = editorSettings->newDocumentFileNameBytes;
}
if (initialNameBytes == -1) {
initialNameBytes = EsCStringLength(initialName);
}
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);
EsElementFocus(instance->fileMenuNameTextbox);
EsTextboxStartEdit(instance->fileMenuNameTextbox);
if (extensionOffset) EsTextboxSetSelection(instance->fileMenuNameTextbox, 0, 0, 0, extensionOffset);
instance->fileMenuNameTextbox->messageUser = FileMenuNameTextboxMessage;
}
void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
// TODO Make this user-customizable?
// const EsFileMenuSettings *settings = (const EsFileMenuSettings *) element->userData.p;
APIInstance *instance = (APIInstance *) _instance->_private;
EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR);
EsInstanceClassEditorSettings *editorSettings = &instance->editorSettings;
bool newDocument = !instance->startupInformation || !instance->startupInformation->filePath;
EsMenu *menu = EsMenuCreate(element, ES_FLAGS_DEFAULT);
if (!menu) return;
EsPanel *panel1 = EsPanelCreate(menu, ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel1);
if (!panel1) goto show;
{
// TODO Get this icon from the file type database?
// We'll probably need Desktop to send this via EsApplicationStartupInformation and when the file is renamed.
EsIconDisplayCreate(panel1, ES_FLAGS_DEFAULT, 0, editorSettings->documentIconID);
EsSpacerCreate(panel1, ES_FLAGS_DEFAULT, 0, 5, 0);
EsPanel *panel2 = EsPanelCreate(panel1, ES_FLAGS_DEFAULT, &styleFileMenuDocumentInformationPanel2);
if (!panel2) goto show;
EsPanel *switcher = EsPanelCreate(panel2, ES_PANEL_H_LEFT | ES_PANEL_SWITCHER | ES_PANEL_SWITCHER_MEASURE_LARGEST);
if (!switcher) goto show;
EsPanel *panel3 = EsPanelCreate(switcher, ES_PANEL_HORIZONTAL | ES_PANEL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel3) goto show;
instance->fileMenuNameTextbox = EsTextboxCreate(switcher, ES_CELL_H_FILL | ES_TEXTBOX_EDIT_BASED, &styleFileMenuNameTextbox);
instance->fileMenuNameSwitcher = switcher;
instance->fileMenuNamePanel = panel3;
EsPanelSwitchTo(instance->fileMenuNameSwitcher, instance->fileMenuNamePanel, ES_TRANSITION_NONE);
if (newDocument) {
EsTextDisplayCreate(panel3, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL,
editorSettings->newDocumentTitle, editorSettings->newDocumentTitleBytes);
} else {
EsTextDisplayCreate(panel3, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL,
instance->startupInformation->filePath, instance->startupInformation->filePathBytes);
}
EsButton *renameButton = EsButtonCreate(panel3, ES_BUTTON_TOOLBAR); // TODO.
if (!renameButton) goto show;
EsButtonSetIcon(renameButton, ES_ICON_DOCUMENT_EDIT_SYMBOLIC);
EsButtonOnCommand(renameButton, FileMenuRename);
if (!newDocument) {
EsPanel *panel4 = EsPanelCreate(panel2, ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel4) goto show;
EsPanelSetBands(panel4, 2 /* columns */);
char buffer[64];
size_t bytes;
bytes = EsStringFormat(buffer, sizeof(buffer), "%D", EsFileStoreGetSize(instance->fileStore));
EsTextDisplayCreate(panel4, ES_CELL_H_RIGHT, ES_STYLE_TEXT_LABEL_SECONDARY, INTERFACE_STRING(CommonFileMenuFileSize));
EsTextDisplayCreate(panel4, ES_CELL_H_LEFT, ES_STYLE_TEXT_LABEL, buffer, bytes);
// TODO Modification date, author, etc.
}
}
EsMenuAddSeparator(menu);
if (instance->instanceClass == ES_INSTANCE_CLASS_EDITOR) {
if (instance->commandSave.disabled) {
EsMenuAddItem(menu, ES_ELEMENT_DISABLED, INTERFACE_STRING(CommonFileUnchanged));
} else {
EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileSave), &instance->commandSave);
}
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileMakeCopy)); // TODO.
EsMenuAddSeparator(menu);
}
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShare)); // TODO.
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileVersionHistory)); // TODO.
EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShowInFileManager), &instance->commandShowInFileManager);
show: EsMenuShow(menu);
}
void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings) {
EsButton *button = EsButtonCreate(element, ES_BUTTON_DROPDOWN, 0, INTERFACE_STRING(CommonFileMenu));
if (!button) return;
button->accessKey = 'F';
button->userData = (void *) settings;
EsButtonOnCommand(button, FileMenuCreate);
}
// --------------------------------- Message loop and core UI infrastructure.
void EsElement::PrintTree(int depth) {

View File

@ -331,6 +331,7 @@ define ES_ERROR_DIRECTORY_ENTRY_BEING_REMOVED (-72)
define ES_ERROR_CANCELLED (-73)
define ES_ERROR_BLOCK_ACCESS_INVALID (-74)
define ES_ERROR_DEVICE_REMOVED (-75)
define ES_ERROR_TOO_MANY_FILES_WITH_NAME (-76)
define ES_INVALID_HANDLE ((EsHandle) (0))
define ES_CURRENT_THREAD ((EsHandle) (0x10))
@ -468,6 +469,10 @@ define ES_PANEL_VERTICAL (0) // Default.
define ES_PANEL_HORIZONTAL (1 << 8)
define ES_PANEL_REVERSE (1 << 9) // Reverse layout is not supported with ES_PANEL_TABLE yet.
// For ES_PANEL_SWITCHER.
define ES_PANEL_SWITCHER_MEASURE_SHOWN (0 << 15) // Use the shown child to determine size.
define ES_PANEL_SWITCHER_MEASURE_LARGEST (1 << 15) // Use the largest child to determine size.
// For ES_PANEL_TABLE.
// TODO Implement these!
define ES_PANEL_H_LEFT (1 << 16)
@ -968,6 +973,7 @@ enum EsMessageType {
ES_MSG_INSTANCE_DOCUMENT_RENAMED = 0x4A04
ES_MSG_INSTANCE_DOCUMENT_UPDATED = 0x4A05
ES_MSG_PRIMARY_CLIPBOARD_UPDATED = 0x4A06
ES_MSG_INSTANCE_RENAME_RESPONSE = 0x4A07
// Debugger messages:
ES_MSG_APPLICATION_CRASH = 0x4C00
@ -986,6 +992,7 @@ enum EsMessageType {
// File Manager messages:
ES_MSG_FILE_MANAGER_FILE_MODIFIED = 0x5100
ES_MSG_FILE_MANAGER_PATH_MOVED = 0x5101
// Textbox messages:
ES_MSG_TEXTBOX_UPDATED = 0x5200

View File

@ -141,6 +141,9 @@ DEFINE_INTERFACE_STRING(DesktopSettingsThemeWallpaper, "Wallpaper");
DEFINE_INTERFACE_STRING(FileCannotSave, "The document was not saved.");
DEFINE_INTERFACE_STRING(FileCannotOpen, "The file could not be opened.");
DEFINE_INTERFACE_STRING(FileCannotRename, "The file could not be renamed.");
DEFINE_INTERFACE_STRING(FileRenameSuccess, "Renamed");
DEFINE_INTERFACE_STRING(FileSaveErrorFileDeleted, "Another application deleted the file.");
DEFINE_INTERFACE_STRING(FileSaveErrorCorrupt, "The file has been corrupted, and it cannot be modified.");
@ -149,7 +152,8 @@ DEFINE_INTERFACE_STRING(FileSaveErrorTooLarge, "The drive does not support files
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(FileSaveErrorResourcesLow, "The system is low on resources. Close some applcations and try again.");
DEFINE_INTERFACE_STRING(FileSaveErrorAlreadyExists, "Too many files already have the same name.");
DEFINE_INTERFACE_STRING(FileSaveErrorAlreadyExists, "There is already a file with this 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(FileLoadErrorCorrupt, "The file has been corrupted, and it cannot be opened.");