diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fb9d46..40449b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(SOURCE_FILES src/draw.c src/image.c src/vecparse.c + ui/generated/resources.c thirdparty/memwatch/memwatch.c ) diff --git a/include/common.h b/include/common.h index f05dc03..eddfcfb 100644 --- a/include/common.h +++ b/include/common.h @@ -35,7 +35,7 @@ #define debug(...) printf(__VA_ARGS__) #define MEMWATCH #else -#define debug(s) +#define debug(...) #endif #include "memwatch.h" @@ -43,9 +43,6 @@ // Prevents "unused" warnings on event handlers and provides proper exports on various OSs. #define EVENT __attribute__((unused)) G_MODULE_EXPORT -// Allows passing just the name of an embedded resource instead of the name and length. -#define EMBEDDED(name) name, name ## _len - // Allocation helpers. #define NEW(t) (t*)calloc(1, sizeof(t)) // Add check for NULL and die here. #define DEL(v) {if(v!=NULL) {free(v); v=NULL;}} diff --git a/include/utils.h b/include/utils.h index e3919ec..14d5b32 100644 --- a/include/utils.h +++ b/include/utils.h @@ -31,10 +31,9 @@ char *utilCreateString(char *format, ...); char *utilCreateStringVArgs(char *format, va_list args); void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted); gboolean utilFileExists(char *filename); -GdkPixbuf *utilGetPixbufFromMemory(char *data, unsigned int len); WindowDataT *utilGetWindowData(GtkWidget *window); -gboolean utilGetWidgetsFromMemory(char *name[], GtkWidget **widgets[], char *data, unsigned int len, gpointer userData); -GtkWidget *utilGetWindowFromMemory(char *name, char *data, unsigned int len, gpointer userData); +gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData); +GtkWidget *utilGetWindowFromMemory(char *resource, char *name, gpointer userData); gboolean utilQuestionDialog(GtkWidget *parent, char *title, char *question); void utilWindowRegister(gpointer windowData); int utilWindowsCloseAll(void); diff --git a/src/joeydev.c b/src/joeydev.c index 478116f..e866364 100644 --- a/src/joeydev.c +++ b/src/joeydev.c @@ -24,9 +24,6 @@ #include "common.h" #include "utils.h" - -#include "gladeJoeyDev.h" -#include "pngLogo.h" #include "vector.h" #include "joeydev.h" @@ -48,7 +45,7 @@ EVENT void toolJoeyDevAboutClicked(GtkWidget *object, gpointer userData) { (void)object; (void)userData; - pixbuf = utilGetPixbufFromMemory(EMBEDDED(___ui_Logo_png)); + pixbuf = gdk_pixbuf_new_from_resource("/com/kangaroopunch/joeydev/Logo.png", NULL); dialog = gtk_about_dialog_new(); gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), "JoeyDev"); @@ -104,5 +101,5 @@ EVENT gboolean winJoeyDevClose(GtkWidget *object, gpointer userData) { void winJoeyDevCreate(void) { - _winJoeyDev = utilGetWindowFromMemory("_winJoeyDev", EMBEDDED(___ui_JoeyDev_glade), NULL); + _winJoeyDev = utilGetWindowFromMemory("/com/kangaroopunch/joeydev/JoeyDev.glade", "winJoeyDev", NULL); } diff --git a/src/utils.c b/src/utils.c index e75a1b8..4e9c4d4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -89,30 +89,18 @@ gboolean utilFileExists(char *filename) { } -GdkPixbuf *utilGetPixbufFromMemory(char *data, unsigned int len) { - GdkPixbufLoader *loader; - GdkPixbuf *pixbuf; - - loader = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(loader, (const guchar *)data, len, NULL); - pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); - gdk_pixbuf_loader_close(loader, NULL); - - return pixbuf; -} - - WindowDataT *utilGetWindowData(GtkWidget *window) { return hmget(_windowList, window); } -GtkWidget *utilGetWindowFromMemory(char *name, char *data, unsigned int len, gpointer userData) { +GtkWidget *utilGetWindowFromMemory(char *resource, char *name, gpointer userData) { GtkBuilder *gtkBuilder; GtkWidget *window; gtkBuilder = gtk_builder_new(); - if (gtk_builder_add_from_string(gtkBuilder, data, len, NULL) == 0) { + + if (gtk_builder_add_from_resource(gtkBuilder, resource, NULL) == 0) { printf("Failed to build UI '%s'!\n", name); exit(1); } @@ -126,12 +114,12 @@ GtkWidget *utilGetWindowFromMemory(char *name, char *data, unsigned int len, gpo } -gboolean utilGetWidgetsFromMemory(char *name[], GtkWidget **widgets[], char *data, unsigned int len, gpointer userData) { +gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData) { GtkBuilder *gtkBuilder; int x; gtkBuilder = gtk_builder_new(); - if (gtk_builder_add_from_string(gtkBuilder, data, len, NULL) == 0) { + if (gtk_builder_add_from_resource(gtkBuilder, resource, NULL) == 0) { printf("Failed to build UI '%s'!\n", name[0]); exit(1); } diff --git a/src/vector.c b/src/vector.c index c7c9c2e..17af6ae 100644 --- a/src/vector.c +++ b/src/vector.c @@ -29,7 +29,6 @@ #include #include #include "scintillaHeaders.h" -#include "gladeVector.h" #include "vector.h" #include "utils.h" #include "draw.h" @@ -49,26 +48,27 @@ typedef struct VectorDataS { - WindowDataT windowData; - GtkWidget *drawVectorImage; - GtkWidget *boxVectorForEditor; - GtkWidget *editor; - GtkWidget *fileVectorTraceImage; - ScintillaObject *sci; - void *pLexer; - int id; - cairo_surface_t *surface; - cairo_surface_t *scaled; - cairo_surface_t *target; - cairo_surface_t *trace; - jlContextT *jlc; - double traceImagePercent; - float *variables; - char *filename; - char *title; - char *tracename; - char *buffer; - int bufferLength; + WindowDataT windowData; + GtkWidget *drawVectorImage; + GtkWidget *boxVectorForEditor; + GtkWidget *editor; + GtkWidget *fileVectorTraceImage; + ScintillaObject *sci; + void *pLexer; + int id; + cairo_surface_t *surface; + cairo_surface_t *scaled; + cairo_surface_t *target; + cairo_surface_t *trace; + jlContextT *jlc; + double traceImagePercent; + float *variables; + char *filename; + char *title; + char *tracename; + char *buffer; + int bufferLength; + PointT **pointList; } VectorDataT; @@ -76,8 +76,9 @@ static int _nextEditorId = 0; static int byte(VectorDataT *self, unsigned char byte); -EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer userData); 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); EVENT void editorVectorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData); EVENT void fileVectorTraceImageFileSet(GtkWidget *object, gpointer userData); static int getWord(VecByteCodeT *bytecode, int *index); @@ -115,6 +116,22 @@ static int byte(VectorDataT *self, unsigned char byte) { } +EVENT void drawVectorImageClick(GtkWidget *object, GdkEventButton *event, gpointer userData) { + VectorDataT *self = (VectorDataT *)userData; + char temp[8]; + int x = (int)(event->x * 0.5); + int y = (int)(event->y * 0.5); + + (void)object; + + if (event->type == GDK_DOUBLE_BUTTON_PRESS) { + snprintf(temp, 8, "%d,%d", x, y); + SSM(SCI_ADDTEXT, strlen(temp), (sptr_t)temp); + SSM(SCI_GRABFOCUS, 0, 0); + } +} + + EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer userData) { VectorDataT *self = (VectorDataT *)userData; int width = cairo_image_surface_get_width(self->surface); @@ -171,17 +188,45 @@ EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer user } -EVENT void drawVectorImageClick(GtkWidget *object, GdkEventButton *event, gpointer userData) { - VectorDataT *self = (VectorDataT *)userData; - char temp[8]; +EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *event, gpointer userData) { + VectorDataT *self = (VectorDataT *)userData; + int closest = -1; + int distance = INT_MAX; + int x = (int)(event->x * 0.5); + int y = (int)(event->y * 0.5); + int temp; + int i; + char buffer[8]; - (void)object; - - if (event->type == GDK_DOUBLE_BUTTON_PRESS) { - snprintf(temp, 8, "%d,%d", (int)(event->x * 0.5), (int)(event->y * 0.5)); - SSM(SCI_ADDTEXT, strlen(temp), (sptr_t)temp); - SSM(SCI_GRABFOCUS, 0, 0); + // Find closest point to mouse pointer. + for (i=0; ipointList); i++) { + temp = sqrt(pow(x - self->pointList[i]->x, 2) + pow(y - self->pointList[i]->y, 2)); + if (temp < distance) { + closest = i; + distance = temp; + } } + + // Did we find a point to edit? + if (closest >= 0) { + // Select first occurrence of it in the text editor. + snprintf(buffer, 8, "%d,%d", self->pointList[closest]->x, self->pointList[closest]->y); + SSM(SCI_TARGETWHOLEDOCUMENT, 0, 0); + SSM(SCI_SETSEARCHFLAGS, SCFIND_NONE, 0); + temp = SSM(SCI_SEARCHINTARGET, strlen(buffer), (sptr_t)buffer); + // Did we find it in the text? + if (temp >= 0) { + // Select the text. + SSM(SCI_SETSEL, temp, temp + strlen(buffer)); + // If they're holding the button down, update the point. + if (event->state & GDK_BUTTON1_MASK) { + snprintf(buffer, 8, "%d,%d", x, y); + SSM(SCI_REPLACETARGET, -1, (sptr_t)buffer); + } + } + } + + return FALSE; } @@ -564,16 +609,21 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { float f1; float f2; time_t startTime; + GtkWidget *dialog; int index = 0; int *stack = NULL; - GtkWidget *dialog; + PointT *p = NULL; -#define GET_BYTE (bytecode->bytes[index++]) -#define GET_WORD getWord(bytecode, &index) +#define GET_BYTE (bytecode->bytes[index++]) +#define GET_WORD getWord(bytecode, &index) +#define ADD_POINT(px,py) p=NEW(PointT); p->x=(px); p->y=(py); arrput(self->pointList, p) debug("-----------------------------------\n"); - self->variables = NULL; + // Clear collected points array. + while (arrlen(self->pointList) > 0) { + arrdel(self->pointList, 0); + } // Reset JoeyLib draw state. jlPaletteDefault(self->jlc); @@ -582,6 +632,7 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { jlDrawColorSet(self->jlc, 15); startTime = time(NULL); + self->variables = NULL; while (index < bytecode->length && difftime(time(NULL), startTime) < RENDER_TIMEOUT) { switch (bytecode->bytes[index++]) { @@ -597,6 +648,8 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { y2 = word(self, GET_WORD); debug("Box %d,%d to %d,%d\n", x1, y1, x2, y2); jlDrawBox(self->jlc, x1, y1, x2, y2); + ADD_POINT(x1, y1); + ADD_POINT(x2, y2); break; case PARSE_CALL: @@ -612,6 +665,7 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { y1 = word(self, GET_WORD); debug("Circle %d at %d,%d\n", y2, x1, y1); jlDrawCircle(self->jlc, x1, y1, y2); + ADD_POINT(x1, y1); break; case PARSE_CLEAR: @@ -636,6 +690,8 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { y2 = word(self, GET_WORD); debug("Ellipse %d,%d to %d,%d\n", x1, y1, x2, y2); jlDrawEllipse(self->jlc, x1, y1, x2, y2); + ADD_POINT(x1, y1); + ADD_POINT(x2, y2); break; case PARSE_FILL: @@ -649,6 +705,7 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { debug("Fill %d,%d to %d\n", x1, y1, x2); jlDrawFillTo(self->jlc, x1, y1, x2); } + ADD_POINT(x1, y1); break; case PARSE_GOTO: @@ -712,12 +769,14 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { count = word(self, GET_WORD); x1 = word(self, GET_WORD); y1 = word(self, GET_WORD); + ADD_POINT(x1, y1); debug("Line %d,%d", x1, y1); for (i=0; ijlc, x1, y1, x2, y2); + ADD_POINT(x2, y2); x1 = x2; y1 = y2; } @@ -823,6 +882,7 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { y1 = word(self, GET_WORD); debug("Plot %d,%d\n", x1, y1); jlDrawPixelSet(self->jlc, x1, y1); + ADD_POINT(x1, y1); break; case PARSE_RECTANGLE: @@ -832,6 +892,8 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { y2 = word(self, GET_WORD); debug("Rectangle %d,%d to %d,%d\n", x1, y1, x2, y2); jlDrawBoxFilled(self->jlc, x1, y1, x2, y2); + ADD_POINT(x1, y1); + ADD_POINT(x2, y2); break; case PARSE_RETURN: @@ -842,6 +904,8 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) { } // switch } // while + debug("Points: %ld\n", arrlen(self->pointList)); + // Clear variables. while (arrlen(self->variables) > 0) { arrdel(self->variables, 0); @@ -977,7 +1041,7 @@ void winVectorCreate(void) { widgets[1] = &self->boxVectorForEditor; widgets[2] = &self->drawVectorImage; widgets[3] = &self->fileVectorTraceImage; - utilGetWidgetsFromMemory(widgetNames, widgets, EMBEDDED(___ui_Vector_glade), self); + utilGetWidgetsFromMemory("/com/kangaroopunch/joeydev/Vector.glade", widgetNames, widgets, self); // Grab title. self->title = strdup(gtk_window_get_title(GTK_WINDOW(self->windowData.window))); @@ -985,6 +1049,7 @@ void winVectorCreate(void) { // Add missing event to drawVectorImage gtk_widget_add_events(self->drawVectorImage, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(self->drawVectorImage), "button-press-event", G_CALLBACK(drawVectorImageClick), self); + gtk_widget_add_events(self->drawVectorImage, GDK_POINTER_MOTION_MASK); // Create Scintilla editor. self->editor = scintilla_new(); diff --git a/tools/prebuild.sh b/tools/prebuild.sh index 0532b37..aa9f593 100755 --- a/tools/prebuild.sh +++ b/tools/prebuild.sh @@ -24,6 +24,33 @@ ROOT=$1 + +pushd "${ROOT}" || exit &> /dev/null + + mkdir -p ui/generated + + glib-compile-resources \ + --sourcedir=ui/ \ + --target=ui/generated/resources \ + --generate \ + ui/joeydev.gresource.xml + + glib-compile-resources \ + --sourcedir=ui/ \ + --target=ui/generated/resources.c \ + --generate-source \ + ui/joeydev.gresource.xml + + glib-compile-resources \ + --sourcedir=ui/ \ + --target=ui/generated/resources.h \ + --generate-header \ + ui/joeydev.gresource.xml + +popd || true &> /dev/null + + +:<<'OLD' pushd "${ROOT}/tools" || exit &> /dev/null echo Generating UI Headers... rm -f ../ui/generated/*.h &> /dev/null || true @@ -47,3 +74,4 @@ pushd "${ROOT}/tools" || exit &> /dev/null done done popd || true &> /dev/null +OLD diff --git a/ui/JoeyDev.glade b/ui/JoeyDev.glade index 6e39c5d..91dcae5 100644 --- a/ui/JoeyDev.glade +++ b/ui/JoeyDev.glade @@ -2,7 +2,7 @@ - + False JoeyDev False diff --git a/ui/Vector.glade b/ui/Vector.glade index 426a87f..4a4ac2e 100644 --- a/ui/Vector.glade +++ b/ui/Vector.glade @@ -25,8 +25,7 @@ - 1000 - 500 + 1250 False Vector @@ -203,6 +202,31 @@ True False vertical + + + True + False + icons + + + True + False + Line + True + dialog-ok + + + False + True + + + + + False + True + 0 + + 640 @@ -210,11 +234,12 @@ True False + False False - 0 + 1 @@ -254,7 +279,7 @@ False True - 1 + 2 @@ -292,7 +317,7 @@ False True - 2 + 3 diff --git a/ui/joeydev.gresource.xml b/ui/joeydev.gresource.xml new file mode 100644 index 0000000..437d25a --- /dev/null +++ b/ui/joeydev.gresource.xml @@ -0,0 +1,8 @@ + + + + JoeyDev.glade + Vector.glade + Logo.png + +