Now loading UI elements from GLib resources instead of our own.

This commit is contained in:
Scott Duensing 2022-12-11 16:35:24 -06:00
parent 0a7dfc1184
commit 1d0a565e05
10 changed files with 179 additions and 71 deletions

View file

@ -34,6 +34,7 @@ set(SOURCE_FILES
src/draw.c
src/image.c
src/vecparse.c
ui/generated/resources.c
thirdparty/memwatch/memwatch.c
)

View file

@ -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;}}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -29,7 +29,6 @@
#include <string.h>
#include <math.h>
#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; i<arrlen(self->pointList); 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; i<count - 1; i++) {
x2 = word(self, GET_WORD);
y2 = word(self, GET_WORD);
debug(" to %d,%d", x2, y2);
jlDrawLine(self->jlc, 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();

View file

@ -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

View file

@ -2,7 +2,7 @@
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="_winJoeyDev">
<object class="GtkWindow" id="winJoeyDev">
<property name="can-focus">False</property>
<property name="title" translatable="yes">JoeyDev</property>
<property name="resizable">False</property>

View file

@ -25,8 +25,7 @@
</patterns>
</object>
<object class="GtkWindow" id="winVector">
<property name="width-request">1000</property>
<property name="height-request">500</property>
<property name="width-request">1250</property>
<property name="can-focus">False</property>
<property name="title" translatable="yes">Vector</property>
<signal name="delete-event" handler="winVectorClose" swapped="no"/>
@ -203,6 +202,31 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="toolbar-style">icons</property>
<child>
<object class="GtkToolButton" id="toolLine">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Line</property>
<property name="use-underline">True</property>
<property name="icon-name">dialog-ok</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkDrawingArea" id="drawVectorImage">
<property name="width-request">640</property>
@ -210,11 +234,12 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<signal name="draw" handler="drawVectorImageDraw" swapped="no"/>
<signal name="motion-notify-event" handler="drawVectorImageMotionEvent" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
@ -254,7 +279,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
@ -292,7 +317,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
</object>

8
ui/joeydev.gresource.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/kangaroopunch/joeydev">
<file preprocess="xml-stripblanks">JoeyDev.glade</file>
<file preprocess="xml-stripblanks">Vector.glade</file>
<file>Logo.png</file>
</gresource>
</gresources>