diff --git a/src/compiler.c b/src/compiler.c index 48be3c8..58595f0 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -185,6 +185,7 @@ void compilerRunRecipe(CompilerContextT *context, char *recipe, char *input, cha context->isRunning = TRUE; g_idle_add(compilerRunRecipeFinished, context); + //***TODO*** There needs to be a way to kill this thread if the recipe runs away. pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); err = pthread_create(&context->thread, &attr, &compilerRunRecipeThread, context); diff --git a/src/messages.c b/src/messages.c index 74426b8..8e40c4d 100644 --- a/src/messages.c +++ b/src/messages.c @@ -32,6 +32,7 @@ static char **_pendingMessages = NULL; static pthread_mutex_t _mtxMessage; +static gboolean messageScroll(gpointer userData); static gboolean messagesUpdate(gpointer userData); EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData); static void winMessagesDelete(gpointer userData); @@ -70,6 +71,26 @@ void message(MessageTypesT level, char *format, ...) { } +static gboolean messageScroll(gpointer userData) { + GtkAdjustment *adjustment; + static int count = 100; // Try this many times to scroll. + + (void)userData; + + //***TODO*** This doesn't always scroll to the very end. + adjustment = gtk_list_box_get_adjustment(GTK_LIST_BOX(_lstMessages)); + gtk_adjustment_set_value(adjustment, gtk_adjustment_get_upper(adjustment)); + gtk_widget_show_all(_lstMessages); + utilForceUpdate(); + + count--; + if (count > 0) return G_SOURCE_CONTINUE; + + count = 100; + return G_SOURCE_REMOVE; +} + + void messageShutdown(void) { g_idle_remove_by_data(messagesUpdate); pthread_mutex_destroy(&_mtxMessage); @@ -101,7 +122,6 @@ static gboolean messagesUpdate(gpointer userData) { GtkWidget *row; GtkWidget *box; GtkWidget *label; - GtkAdjustment *adjustment; char *string = NULL; (void)userData; @@ -144,14 +164,12 @@ static gboolean messagesUpdate(gpointer userData) { gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(row), box); gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1); - - // Scroll to show new row. - //***TODO*** This doesn't always scroll to the very end. - adjustment = gtk_list_box_get_adjustment(GTK_LIST_BOX(_lstMessages)); - gtk_adjustment_set_value(adjustment, gtk_adjustment_get_upper(adjustment)); gtk_widget_show_all(_lstMessages); utilForceUpdate(); + // Scroll to show new row. + g_idle_add(messageScroll, NULL); + DEL(string); // Finally free the string allocated in message(). } @@ -159,6 +177,21 @@ static gboolean messagesUpdate(gpointer userData) { } +EVENT void toolMessagesClearClicked(GtkWidget *widget, gpointer userData) { + GList *children; + GList *iter; + + (void)widget; + (void)userData; + + children = gtk_container_get_children(GTK_CONTAINER(_lstMessages)); + for (iter = children; iter != NULL; iter = g_list_next(iter)) { + gtk_widget_destroy(GTK_WIDGET(iter->data)); + } + g_list_free(children); +} + + EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData) { // userData is not reliable due to util indirectly calling us. WindowDataT *self = (WindowDataT *)utilGetWindowData(object); diff --git a/src/project.c b/src/project.c index eacb77d..c2539c5 100644 --- a/src/project.c +++ b/src/project.c @@ -77,6 +77,8 @@ typedef struct ProjectDataS { WindowDataT windowData; GtkWidget *treeProject; StringHashT **recipes; + char *projectType; + char *projectName; char *configName; char *buildHost; int buildHTTPPort; @@ -133,6 +135,7 @@ EVENT void menuProjectFileSaveAs(GtkWidget *object, gpointer userData); EVENT void menuProjectFileClose(GtkWidget *object, gpointer userData); EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData); EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData); +EVENT void menuProjectProjectProperties(GtkWidget *object, gpointer userData); EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData); EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData); EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData); @@ -536,6 +539,18 @@ static void loadProject(ProjectDataT *self) { DEL(raw); } + // Is this a 'project' line? + if (strcasecmp(c, "project") == 0) { + c = utilGetToken(NULL, " ", "\"", "\""); + utilDequote(c); + DEL(self->projectType); + self->projectType = strdup(c); + c = utilGetToken(NULL, " ", "\"", "\""); + utilDequote(c); + DEL(self->projectName); + self->projectName = strdup(c); + } + } fclose(in); DEL(line); @@ -543,6 +558,13 @@ static void loadProject(ProjectDataT *self) { } else { message(MSG_SEVERE, "Unknown error attempting to load %s!", self->windowData.filename); } + + if (self->projectType == NULL) { + self->projectType = strdup("Application"); + } + if (self->projectName == NULL) { + self->projectName = strdup("None"); + } } @@ -582,6 +604,12 @@ EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData) { clearRecipeData(self); + // Clear project properties. + DEL(self->projectName); + DEL(self->projectType); + self->projectType = strdup("Application"); + self->projectName = strdup("None"); + // Nuke filename & mark clean. DEL(self->windowData.filename); DEL(self->windowData.path); @@ -626,6 +654,8 @@ EVENT void menuProjectFileSave(GtkWidget *object, gpointer userData) { // Save! Write out header. fprintf(out, "%s\n", PROJECT_VERSION); fprintf(out, "------------------------------------------------------------------------------\n"); + // Write out project properties. + fprintf(out, "project \"%s\" \"%s\"\n", self->projectType, self->projectName); // Write out file list. gtk_tree_model_get_iter_first(model, &iter); do { @@ -778,6 +808,60 @@ EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData) { } +EVENT void menuProjectProjectProperties(GtkWidget *object, gpointer userData) { + ProjectDataT *self = (ProjectDataT *)userData; + GtkWidget *dialogProperties; + GtkWidget *comboType; + GtkWidget *txtName; + + (void)object; + + char *temp = NULL; + char *widgetNames[] = { + "dialogProjectProperties", + "comboProjectType", + "txtProjectName", + NULL + }; + GtkWidget **widgets[] = { + &dialogProperties, + &comboType, + &txtName + }; + GtkEntryBuffer *buffer; + int result; + + utilGetWidgetsFromMemory("/com/kangaroopunch/joeydev/ProjectProperties.glade", widgetNames, widgets, self); + + if (strcmp(self->projectType, "JoeyLib") == 0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(comboType), 1); + } else { + gtk_combo_box_set_active(GTK_COMBO_BOX(comboType), 0); + } + + buffer = gtk_entry_get_buffer(GTK_ENTRY(txtName)); + gtk_entry_buffer_set_text(GTK_ENTRY_BUFFER(buffer), self->projectName, strlen(self->projectName)); + + result = gtk_dialog_run(GTK_DIALOG(dialogProperties)); + if (result == GTK_RESPONSE_OK) { + if (strcmp(self->projectName, gtk_entry_buffer_get_text(GTK_ENTRY_BUFFER(buffer))) != 0) { + DEL(self->projectName); + self->projectName = strdup(gtk_entry_buffer_get_text(GTK_ENTRY_BUFFER(buffer))); + utilSetDirty((WindowDataT *)self, TRUE); + } + temp = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(comboType)); + if (strcmp(self->projectType, temp) != 0) { + DEL(self->projectType); + self->projectType = strdup(temp); + utilSetDirty((WindowDataT *)self, TRUE); + } + DEL(temp); + } + + gtk_widget_destroy(dialogProperties); +} + + EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) { ProjectDataT *self = (ProjectDataT *)userData; GtkWidget *dialog; @@ -1021,9 +1105,9 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) { return; } // Write what we're building. - fprintf(out, "application\n"); //***TODO*** We don't know how to handle other types yet. + fprintf(out, "%s\n", self->projectType); // Write it's title. - fprintf(out, "%s\n", "CRAP - MISSING!"); //***TODO*** Collect and remember project name! Derp! + fprintf(out, "%s\n", self->projectName); // Write desired build targets. for (i=0; itargets); i++) { archPrinted = FALSE; diff --git a/ui/Messages.glade b/ui/Messages.glade index 39ed6cf..9c04a1d 100644 --- a/ui/Messages.glade +++ b/ui/Messages.glade @@ -6,24 +6,63 @@ False Messages 800 - 300 + 350 + emblem-documents - + True - True - in + False + vertical - + True False - + True False + Clear all messages + Clear + True + edit-delete + + + + False + True + + + + + False + True + 0 + + + + + True + True + in + + + True + False + + + True + False + + + + True + True + 1 + diff --git a/ui/Project.glade b/ui/Project.glade index 4512805..b9fff1c 100644 --- a/ui/Project.glade +++ b/ui/Project.glade @@ -117,6 +117,21 @@ + + + True + False + + + + + True + False + Properties... + True + + + diff --git a/ui/ProjectProperties.glade b/ui/ProjectProperties.glade new file mode 100644 index 0000000..96d5205 --- /dev/null +++ b/ui/ProjectProperties.glade @@ -0,0 +1,150 @@ + + + + + + 15 + + + False + Project Properties + 300 + 200 + dialog + + + False + 15 + 15 + vertical + 2 + + + False + end + + + Cancel + True + True + True + + + True + True + 0 + + + + + OK + True + True + True + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + center + vertical + + + + True + False + 15 + 15 + + + True + False + end + Project Type: + + + 0 + 0 + + + + + True + False + end + Project Name: + + + 0 + 1 + + + + + True + True + entrybufferProjectName + 15 + alpha + + + 1 + 1 + + + + + True + False + 0 + True + + Application + JoeyLib + + + + False + + + + + 1 + 0 + + + + + False + True + 0 + + + + + True + True + 1 + + + + + + button1 + button2 + + + diff --git a/ui/joeydev.gresource.xml b/ui/joeydev.gresource.xml index 0eb417d..46d4a74 100644 --- a/ui/joeydev.gresource.xml +++ b/ui/joeydev.gresource.xml @@ -3,6 +3,7 @@ JoeyDev.glade Project.glade + ProjectProperties.glade BuildServer.glade Cook.glade Editor.glade