Code Editor starting to work. Integration with raw data is screwball for some reason.

This commit is contained in:
Scott Duensing 2023-04-25 20:52:53 -05:00
parent 917eedb95b
commit 870d2822e0
16 changed files with 498 additions and 139 deletions

16
embedded/gitattributes Normal file
View file

@ -0,0 +1,16 @@
#
# GitAttributes for JoeyDev Projects
#
# JoeyLib Formats
*.img filter=lfs diff=lfs merge=lfs -text
*.stn filter=lfs diff=lfs merge=lfs -text
*.vec filter=lfs diff=lfs merge=lfs -text
*.snd filter=lfs diff=lfs merge=lfs -text
# Native Formats
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.mod filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text

6
embedded/gitignore Normal file
View file

@ -0,0 +1,6 @@
#
# GitIgnore for JoeyDev Projects
#
# No baked data.
*.dat

38
embedded/missing.h Normal file
View file

@ -0,0 +1,38 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef MISSING_H
#define MISSING_H
// These are valid for 64 bit hosts.
typedef short int16_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Things missing that are nice to have.
extern int fputc(int c, FILE *stream);
extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
#endif // MISSING_H

16
embedded/recipe.c Normal file
View file

@ -0,0 +1,16 @@
/*
/
/ JoeyDev Recipe
/
*/
#include <recipe.h>
int recipe(char *fileIn, char *outputPath) {
// This program runs with the current working directory set to 'outputPath'.
return 0; // Return a positive non-zero value on failure.
}

View file

@ -29,25 +29,14 @@
#include <stdatomic.h>
#include <stdbool.h>
#include <stdnoreturn.h>
// These are valid for 64 bit hosts.
typedef short int16_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#include <missing.h>
// Our shared data.
extern char **___recipeTargets;
// Things missing that are nice to have.
extern int fputc(int c, FILE *stream);
extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
// Our API.
extern char *utilCreateString(char *format, ...);
extern void recipeAddTarget(char *target);
extern void recipeMessage(char *format, ...);

View file

@ -24,7 +24,7 @@
#define EDITOR_H
void winEditorCreate(void);
void winEditorCreate(char *filename);
#endif // EDITOR_H

View file

@ -44,6 +44,7 @@ void utilDequote(char *string);
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted);
void utilExtractResource(char *path);
char *utilFileBasename(char *path);
gboolean utilFileCopy(char *from, char *to);
gboolean utilFileExists(char *filename);
gboolean utilFileOpen(WindowDataT *self, char *extension, char *what);
char *utilFileRemoveExtension(char *filename);

View file

@ -26,6 +26,10 @@
#include "scintillaHeaders.h"
#define MARKER_ERROR_ARROW 0
#define MARKER_ERROR_HIGHLIGHT 1
typedef struct EditorDataS {
WindowDataT windowData;
GtkWidget *boxForEditor;
@ -41,13 +45,38 @@ typedef struct EditorDataS {
static int _nextEditorId = 0;
static void clearEditor(EditorDataT *self);
EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData);
static void loadEditor(EditorDataT *self);
static void loadEditorConfig(char *lexer, EditorDataT *self);
EVENT void menuEditorEditCopy(GtkWidget *object, gpointer userData);
EVENT void menuEditorEditCut(GtkWidget *object, gpointer userData);
EVENT void menuEditorEditDelete(GtkWidget *object, gpointer userData);
EVENT void menuEditorEditPaste(GtkWidget *object, gpointer userData);
EVENT void menuEditorFileClose(GtkWidget *object, gpointer userData);
EVENT void menuEditorFileNew(GtkWidget *object, gpointer userData);
EVENT void menuEditorFileOpen(GtkWidget *object, gpointer userData);
EVENT void menuEditorFileSave(GtkWidget *object, gpointer userData);
EVENT void menuEditorFileSaveAs(GtkWidget *object, gpointer userData);
EVENT void menuEditorHelpEditor(GtkWidget *object, gpointer userData);
static void status(EditorDataT *self, char *message);
EVENT gboolean winEditorClose(GtkWidget *object, gpointer userData);
static void winEditorDelete(gpointer userData);
static void writeEditorConfig(char *lexer, EditorDataT *self);
static void clearEditor(EditorDataT *self) {
(void)self;
// Clear editor.
SSM(SCI_CLEARALL, 0, 0);
// Clear error markers.
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_ARROW, 0);
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_HIGHLIGHT, 0);
}
EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
int lineNumber = (int)SSM(SCI_LINEFROMPOSITION, (uptr_t)notifyData->position, (sptr_t)0);
@ -75,6 +104,26 @@ EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotifi
}
static void loadEditor(EditorDataT *self) {
FILE *in = NULL;
char *line = NULL;
size_t len = 0;
in = fopen(self->windowData.filename, "rt");
if (in != NULL) {
utilEnsureBufferSize((unsigned char **)&line, (int *)&len, 1024); // Not technically needed, but fixes a pointer warning from memmaker.
while (getline(&line, &len, in) != -1) {
SSM(SCI_ADDTEXT, strlen(line), (sptr_t)line);
}
fclose(in);
DEL(line);
}
// Do again - loading text marks us dirty.
utilSetDirty((WindowDataT *)self, FALSE);
}
static void loadEditorConfig(char *lexer, EditorDataT *self) {
char *config = NULL;
FILE *in = NULL;
@ -168,6 +217,152 @@ static void loadEditorConfig(char *lexer, EditorDataT *self) {
}
EVENT void menuEditorEditCopy(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
SSM(SCI_COPY, 0, 0);
}
EVENT void menuEditorEditCut(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
SSM(SCI_CUT, 0, 0);
}
EVENT void menuEditorEditDelete(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
SSM(SCI_CLEAR, 0, 0);
}
EVENT void menuEditorEditPaste(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
SSM(SCI_PASTE, 0, 0);
}
EVENT void menuEditorFileClose(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
gtk_window_close(GTK_WINDOW(self->windowData.window));
}
EVENT void menuEditorFileNew(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
if (self->windowData.isDirty == TRUE) {
if (!utilQuestionDialog(self->windowData.window, "New", "You have unsaved changes. Start new?")) {
return;
}
status(self, "New image.");
}
clearEditor(self);
// Clear any filename.
DEL(self->windowData.filename);
// Mark clean.
utilSetDirty((WindowDataT *)self, FALSE);
}
EVENT void menuEditorFileOpen(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
(void)object;
if (utilFileOpen((WindowDataT *)userData, "*.*", "Code")) {
clearEditor(self);
loadEditor(self);
}
}
EVENT void menuEditorFileSave(GtkWidget *object, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
int length = SSM(SCI_GETLENGTH, 0, 0);
FILE *out = NULL;
char *code = NULL;
// Do we need to save?
if (self->windowData.isDirty == TRUE) {
// Do we have a filename? If not, kick 'em to SaveAs.
if (self->windowData.filename == NULL) {
menuEditorFileSaveAs(object, userData);
return;
}
// Allocate space to fetch code from editor.
code = (char *)malloc(length + 1);
if (!code) {
//***TODO*** Something bad happened.
return;
}
// Fetch code.
SSM(SCI_GETTEXT, length, (sptr_t)code);
out = fopen(self->windowData.filename, "wt");
if (out != NULL) {
// Save!
fprintf(out, "%s\n", code);
fclose(out);
status(self, "Saved.");
// We're clean now.
utilSetDirty((WindowDataT *)self, FALSE);
} else {
//***TODO*** Something bad happened.
}
// Release code.
DEL(code);
}
}
EVENT void menuEditorFileSaveAs(GtkWidget *object, gpointer userData) {
(void)object;
if (utilFileSaveAs((WindowDataT *)userData, "*.*", "Code")) {
menuEditorFileSave(object, (EditorDataT *)userData);
}
}
EVENT void menuEditorHelpEditor(GtkWidget *object, gpointer userData) {
(void)object;
(void)userData;
gtk_show_uri_on_window(NULL, "https://skunkworks.kangaroopunch.com/skunkworks/joeydev/-/wikis/Code-Editor", GDK_CURRENT_TIME, NULL);
}
static void status(EditorDataT *self, char *message) {
gtk_statusbar_remove_all(GTK_STATUSBAR(self->statusBar), self->statusBarId);
gtk_statusbar_push(GTK_STATUSBAR(self->statusBar), self->statusBarId, message);
}
EVENT gboolean winEditorClose(GtkWidget *object, gpointer userData) {
// userData is not reliable due to menuVectorFileClose and util indirectly calling us.
EditorDataT *self = (EditorDataT *)utilGetWindowData(object);
@ -187,7 +382,7 @@ EVENT gboolean winEditorClose(GtkWidget *object, gpointer userData) {
}
void winEditorCreate(void) {
void winEditorCreate(char *filename) {
EditorDataT *self;
char *widgetNames[] = {
"winEditor",
@ -262,6 +457,12 @@ void winEditorCreate(void) {
SSM(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER);
SSM(SCI_SETFOLDFLAGS, SC_FOLDFLAG_LINEAFTER_CONTRACTED , 0);
// Margin markers.
SSM(SCI_MARKERDEFINE, MARKER_ERROR_ARROW, SC_MARK_SHORTARROW); // Error
SSM(SCI_MARKERSETBACK, MARKER_ERROR_ARROW, 255 | (0 << 8) | (0 << 16)); // RGB
SSM(SCI_MARKERDEFINE, MARKER_ERROR_HIGHLIGHT, SC_MARK_BACKGROUND); // Error
SSM(SCI_MARKERSETBACK, MARKER_ERROR_HIGHLIGHT, 127 | (0 << 8) | (0 << 16)); // RGB
// Add lexer for language support.
self->pLexer = CreateLexer("cpp");
SSM(SCI_SETILEXER, 0, (sptr_t)self->pLexer);
@ -274,6 +475,11 @@ void winEditorCreate(void) {
// Show window.
gtk_widget_show_all(self->windowData.window);
if (filename != NULL) {
self->windowData.filename = strdup(filename);
loadEditor(self);
}
}

View file

@ -70,7 +70,7 @@ EVENT void toolJoeyDevEditorClicked(GtkWidget *widget, gpointer userData) {
(void)widget;
(void)userData;
winEditorCreate();
winEditorCreate(NULL);
}

View file

@ -59,9 +59,11 @@ int main(int argc, char **argv) {
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdnoreturn.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/tccdefs.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/tcclib.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/tgmath.h"); // Not needed.
utilExtractResource("/com/kangaroopunch/joeydev/resources/varargs.h"); // Not needed.
utilExtractResource("/com/kangaroopunch/joeydev/resources/missing.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/recipe.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/recipe.c");
utilExtractResource("/com/kangaroopunch/joeydev/resources/gitignore");
utilExtractResource("/com/kangaroopunch/joeydev/resources/gitattributes");
winJoeyDevCreate();
gtk_main();

View file

@ -33,6 +33,7 @@
#include "ssh.h"
#include "messages.h"
#include "compiler.h"
#include "editor.h"
enum ProjectColumnsE {
@ -80,6 +81,7 @@ typedef struct ProjectDataS {
char *buildPassword;
TargetT **targets;
GtkWidget *tempWidget; // Used to pass data around dialogs.
char *tempString; // Used to pass data around dialogs.
} ProjectDataT;
typedef struct SectionDataS {
@ -110,6 +112,7 @@ static ProjectDataT *_cookingProjectData = NULL;
static void addToRecipeData(ProjectDataT *self, char *key, char *value);
EVENT void buildTargetClicked(GtkButton *widget, gpointer userData);
EVENT void btnEditRawClicked(GtkButton *widget, gpointer userData);
EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData);
EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData);
static void clearRecipeData(ProjectDataT *self);
@ -159,6 +162,26 @@ EVENT void buildTargetClicked(GtkButton *widget, gpointer userData) {
}
EVENT void btnEditRawClicked(GtkButton *widget, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
char *pathTemp = NULL;
char *filename = NULL;
int i;
(void)widget;
pathTemp = strdup(self->windowData.filename);
cwk_path_get_dirname(pathTemp, (size_t *)&i); //***TODO*** Self is getting clobbered here. WTF?
if (i > 0) pathTemp[i] = 0;
//***TODO*** Be sure this is something we can edit as text.
filename = utilCreateString("%s%s", pathTemp, self->tempString);
winEditorCreate(filename);
DEL(filename);
}
EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
char *file = NULL;
@ -167,7 +190,7 @@ EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData) {
file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(self->tempWidget));
if (utilFileExists(file)) {
//***TODO*** Text Editor
winEditorCreate(file);
}
DEL(file);
}
@ -176,29 +199,37 @@ EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData) {
EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
char *newFile = NULL;
FILE *out = NULL;
char *fromTemp = NULL;
char *toTemp = NULL;
char *pathTemp = NULL;
int i;
(void)widget;
//***TODO*** This should be an embedded file.
//***TODO*** We should also provide .gitignore and .gitattribute files.
if (utilFileSaveOtherAs((WindowDataT *)userData, "*.c", "Recipe", &newFile)) {
out = fopen(newFile, "wt");
fprintf(out, ""
"//\n"
"// JoeyBuild Recipe Program\n"
"//\n"
"\n"
"\n"
"#include <recipe.h>\n"
"\n"
"\n"
"int recipe(char *fileIn, char *outputPath) {\n"
"\n"
"\treturn 0; // Return a positive non-zero value on failure.\n"
"}\n"
);
fclose(out);
pathTemp = strdup(self->windowData.filename);
cwk_path_get_dirname(pathTemp, (size_t *)&i);
if (i > 0) pathTemp[i] = 0;
fromTemp = utilCreateString("%s%s", __resourcePath, "recipe.c");
utilFileCopy(fromTemp, newFile);
DEL(fromTemp);
fromTemp = utilCreateString("%s%s", __resourcePath, "gitignore");
toTemp = utilCreateString("%s%s", pathTemp, ".gitignore");
utilFileCopy(fromTemp, toTemp);
DEL(toTemp);
DEL(fromTemp);
fromTemp = utilCreateString("%s%s", __resourcePath, "gitattributes");
toTemp = utilCreateString("%s%s", pathTemp, ".gitattributes");
utilFileCopy(fromTemp, toTemp);
DEL(toTemp);
DEL(fromTemp);
DEL(pathTemp);
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(self->tempWidget), newFile);
}
}
@ -252,6 +283,7 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
gtk_label_set_text(GTK_LABEL(lblRaw), raw);
self->tempWidget = fileRecipe;
self->tempString = strdup(raw);
// Find path of project file.
path = strdup(self->windowData.filename);
@ -285,7 +317,9 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
DEL(path);
DEL(raw);
self->tempWidget = NULL;
DEL(self->tempString);
gtk_widget_destroy(dialogCookSettings);
}
@ -1036,7 +1070,10 @@ EVENT void treeProjectRowActivated(GtkTreeView *treeView, GtkTreePath *path, Gtk
GtkTreeIter iter;
char *name = NULL;
char *pathString = NULL;
char *pathTemp = NULL;
char *filename = NULL;
int section;
int i;
pathString = gtk_tree_path_to_string(path);
if (strstr(pathString, ":") != NULL) {
@ -1047,8 +1084,15 @@ EVENT void treeProjectRowActivated(GtkTreeView *treeView, GtkTreePath *path, Gtk
debug("Double click! [%d] [%s] [%s]\n", section, pathString, name);
if (section == SECTION_CODE || section == SECTION_HEADER) {
//***TODO*** We find our path way too often. Do it once and keep it.
pathTemp = strdup(self->windowData.filename);
cwk_path_get_dirname(pathTemp, (size_t *)&i);
if (i > 0) pathTemp[i] = 0;
filename = utilCreateString("%s%s", pathTemp, name);
// Launch code editor.
//***TODO***
winEditorCreate(filename);
DEL(filename);
DEL(pathTemp);
}
if (section == SECTION_RAW_DATA) {

View file

@ -183,6 +183,33 @@ char *utilFileBasename(char *path) {
}
gboolean utilFileCopy(char *from, char *to) {
FILE *in = NULL;
FILE *out = NULL;
gboolean result = FALSE;
size_t bytes;
in = fopen(from, "rb");
if (in) {
out = fopen(to, "wb");
if (out) {
while (!feof(in)) {
bytes = fread(__utilFilenameBuffer, 1, FILENAME_MAX, in);
if (bytes) {
fwrite(__utilFilenameBuffer, 1, bytes, out);
}
}
result = TRUE;
fclose(out);
}
fclose(in);
}
return result;
}
gboolean utilFileExists(char *filename) {
FILE *f = fopen(filename, "rb");
@ -266,47 +293,7 @@ char *utilFileRemoveExtension(char *filename) {
gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what) {
GtkWidget *dialog;
GtkFileFilter *filter;
gboolean result = FALSE;
char *files = utilCreateString("%s Files", what);
int x;
//***TODO*** Make this use utilFileSaveOtherAS
dialog = gtk_file_chooser_dialog_new("Save As",
GTK_WINDOW(self->window),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
if (self->filename != NULL) {
memcpy(__utilFilenameBuffer, self->filename, strlen(self->filename) + 1);
cwk_path_get_dirname(__utilFilenameBuffer, (size_t *)&x);
if (x > 0) __utilFilenameBuffer[x] = 0;
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),__utilFilenameBuffer);
}
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, files);
gtk_file_filter_add_pattern(filter, extension);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
DEL(self->filename);
self->filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
utilSetDirty(self, TRUE);
result = TRUE;
}
DEL(files);
gtk_widget_destroy(dialog);
return result;
return utilFileSaveOtherAs(self, extension, what, &self->filename);
}

View file

@ -40,6 +40,9 @@
#include "palette.h"
//***TODO*** Reuse editor.c instead of using our own text editor here.
#define RENDER_TIMEOUT 5 // In seconds
#define MARKER_ERROR_ARROW 0
@ -99,6 +102,7 @@ static int _nextEditorId = 0;
static int byte(VectorDataT *self, unsigned char byte);
static void clearVectorEditor(VectorDataT *self);
EVENT void drawVectorImageClick(GtkWidget *object, GdkEventButton *event, gpointer userData);
EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer userData);
EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *event, gpointer userData);
@ -153,6 +157,29 @@ static int byte(VectorDataT *self, unsigned char byte) {
}
static void clearVectorEditor(VectorDataT *self) {
// Clear editor.
SSM(SCI_CLEARALL, 0, 0);
// Clear error markers.
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_ARROW, 0);
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_HIGHLIGHT, 0);
// Reset JoeyLib drawing state.
jlPaletteDefault(self->jlc);
jlDrawColorSet(self->jlc, 0);
jlDrawClear(self->jlc);
jlDrawColorSet(self->jlc, 15);
// Destroy trace image, if any.
if (self->trace != NULL) {
cairo_surface_destroy(self->trace);
self->trace = NULL;
gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(self->fileVectorTraceImage));
}
}
EVENT void drawVectorImageClick(GtkWidget *object, GdkEventButton *event, gpointer userData) {
VectorDataT *self = (VectorDataT *)userData;
char temp[8];
@ -704,26 +731,14 @@ EVENT void menuVectorFileNew(GtkWidget *object, gpointer userData) {
status(self, "New image.");
}
// Clear editor.
SSM(SCI_CLEARALL, 0, 0);
// Clear error markers.
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_ARROW, 0);
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_HIGHLIGHT, 0);
// Reset JoeyLib drawing state.
jlPaletteDefault(self->jlc);
jlDrawColorSet(self->jlc, 0);
jlDrawClear(self->jlc);
jlDrawColorSet(self->jlc, 15);
// Destroy trace image, if any.
if (self->trace != NULL) {
cairo_surface_destroy(self->trace);
self->trace = NULL;
gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(self->fileVectorTraceImage));
}
clearVectorEditor(self);
// Clear any filename.
DEL(self->windowData.filename);
// Refresh widget.
gtk_widget_queue_draw(self->drawVectorImage);
// Mark clean.
utilSetDirty((WindowDataT *)self, FALSE);
}
@ -735,6 +750,7 @@ EVENT void menuVectorFileOpen(GtkWidget *object, gpointer userData) {
(void)object;
if (utilFileOpen((WindowDataT *)userData, "*.vic", "Image")) {
clearVectorEditor(self);
loadVectorImage(self);
}
}

View file

@ -61,7 +61,7 @@
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<!-- n-columns=4 n-rows=2 -->
<!-- n-columns=4 n-rows=3 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -92,19 +92,7 @@
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnNewRecipe">
<property name="label" translatable="yes">New</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="btnNewRecipeClicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
@ -133,14 +121,41 @@
</packing>
</child>
<child>
<object class="GtkButton" id="btnEdit">
<property name="label" translatable="yes">Edit</property>
<object class="GtkButton" id="btnEditRecipe">
<property name="label" translatable="yes">Edit Recipe</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-start">15</property>
<signal name="clicked" handler="btnEditRecipeClicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnEditRaw">
<property name="label" translatable="yes">Edit Raw Data</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="btnEditRawClicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnNewRecipe">
<property name="label" translatable="yes">New</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="btnNewRecipeClicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">1</property>

View file

@ -19,7 +19,7 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorFile">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_File</property>
@ -29,31 +29,43 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorFileNew">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">New</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorFileNew" swapped="no"/>
<accelerator key="n" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorFileOpen">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Open...</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorFileOpen" swapped="no"/>
<accelerator key="o" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorFileSave">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Save</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorFileSave" swapped="no"/>
<accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorFileSaveAs">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Save As...</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorFileSaveAs" swapped="no"/>
<accelerator key="s" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</object>
</child>
<child>
@ -63,10 +75,13 @@
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorFileClose">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Close</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorFileClose" swapped="no"/>
<accelerator key="F4" signal="activate" modifiers="GDK_MOD1_MASK"/>
</object>
</child>
</object>
@ -74,7 +89,7 @@
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorEdit">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Edit</property>
@ -84,31 +99,42 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorEditCut">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Cut</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorEditCut" swapped="no"/>
<accelerator key="x" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorEditCopy">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Copy</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorEditCopy" swapped="no"/>
<accelerator key="c" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorEditPaste">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Paste</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorEditPaste" swapped="no"/>
<accelerator key="v" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorEditDelete">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Delete</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorEditDelete" swapped="no"/>
</object>
</child>
</object>
@ -116,15 +142,7 @@
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorHelp">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Help</property>
@ -134,10 +152,13 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="menuEditorHelpEditor">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Code Editor...</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuEditorHelpEditor" swapped="no"/>
<accelerator key="F1" signal="activate"/>
</object>
</child>
</object>

View file

@ -33,8 +33,10 @@
<file compressed="true" alias="stdnoreturn.h">../thirdparty-installed/lib/tcc/include/stdnoreturn.h</file>
<file compressed="true" alias="tccdefs.h">../thirdparty-installed/lib/tcc/include/tccdefs.h</file>
<file compressed="true" alias="tcclib.h">../thirdparty-installed/lib/tcc/include/tcclib.h</file>
<file compressed="true" alias="tgmath.h">../thirdparty-installed/lib/tcc/include/tgmath.h</file>
<file compressed="true" alias="varargs.h">../thirdparty-installed/lib/tcc/include/varargs.h</file>
<file compressed="true" alias="missing.h">../embedded/missing.h</file>
<file compressed="true" alias="recipe.h">../embedded/recipe.h</file>
<file compressed="true" alias="recipe.c">../embedded/recipe.c</file>
<file compressed="true" alias="gitignore">../embedded/gitignore</file>
<file compressed="true" alias="gitattributes">../embedded/gitattributes</file>
</gresource>
</gresources>