Initial commit: first state machine and interactive dialog window

This commit implements the first state machine crossing EXEC_EDIT with
STATE_RULES_DATA. A dialog window is available to use.

TODO:
	- get OpenGL view
	- get a GTK4 tree view
This commit is contained in:
Jean Sirmai 2024-04-22 18:40:30 +02:00
parent a6845e9b2a
commit 1d8fc9ef22
Signed by: jean
GPG Key ID: FB3115C340E057E3
47 changed files with 4654 additions and 206 deletions

239
(notes) Normal file
View File

@ -0,0 +1,239 @@
contain.c: (136) gtk_box_append (middle_box, GTK_WIDGET (get_GLArea()));
graph_area.h: (177) static inline GLuint create_shader(const int stack_id, int type, const char *src) {...}
graph_area.c: (153) graphics_draw (stack_index[i].stack_id);
graph_area.c: (233) g_signal_connect (adj, "value-changed", G_CALLBACK(on_axis_value_change), (gpointer) label);
graph_area.c: (289) g_signal_connect(GTK_GL_AREA(gl_area), "render", G_CALLBACK(on_glarea_render), NULL);
graph_area.c: g_signal_connect(gl_area, "realize", G_CALLBACK(on_glarea_realize), NULL);
graph_area.c: g_signal_connect(gl_area, "unrealize", G_CALLBACK(on_glarea_unrealize), NULL);
graph_stack.c: (149) if (!graphics_init_shaders(cur_id)) return -1;
graph_stack.c: (153) graphics_init_buffers(cur_id);
graph_stack.c: (288) draw_space_ridges_vertex (stack_id, stack->buffer_vertex_size, space_X, space_Y, space_Z);
graph_stack.c: draw_space_ridges_lines (stack_id);
graph_stack.c: draw_grids_on_space_faces_vertex (stack_id, space_X, space_Y, space_Z);
graph_stack.c: draw_grids_on_space_faces_lines (stack_id, stack->buffer_lines_size, space_X, space_Y, space_Z);
graph_stack.c: (316) stack->arrows_nb = set_arrow (stack_id, stack->arrows_nb, space_X, space_Y, space_Z, arrow.load, arrow.site, arrow.x, arrow.y, arrow.z);
--------------------------------------------------------------------------------
contain is called (#included) in : callback, display, tree, graph_stack, graph_area, init,
--------------------------------------------------------------------------------
// https://docs.gtk.org/gtk4/visual_index.html < widgets gallery
// https://docs.gtk.org/gtk4/section-text-widget.html
// https://docs.gtk.org/gtk4/class.Widget.html#height-for-width-geometry-management
// GTK_ORIENTATION_VERTICAL GTK_ORIENTATION_HORIZONTAL
https://docs.gtk.org/gtk4/visual_index.html widgets gallery
https://forge.a-lec.org/gem-graph/gem-graph-client/src/branch/devel/Makefile
https://docs.gtk.org/gtk4/class.Widget.html#height-for-width-geometry-management
// GtkSizeRequestMode get_request_mode (GtkWidget* widget);
// gtk_window_set_default_size (GTK_WINDOW (a_box), 30, 400); < TO STUDY
https://docs.gtk.org/gtk4/section-text-widget.html texts
https://docs.gtk.org/gtk4/drag-and-drop.html drag-and-drop
https://docs.gtk.org/gtk4/class.GestureZoom.html GtkGestureZoom
https://docs.gtk.org/gtk4/class.ListView.html
https://blog.gtk.org/2020/09/08/on-list-models/ < TODO
https://docs.gtk.org/gio/method.ActionMap.add_action_entries.html
--------------------------------------------------------------------------------
GTK_ORIENTATION_VERTICAL GTK_ORIENTATION_HORIZONTAL
GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT GTK_SIZE_REQUEST_CONSTANT_SIZE
g_signal_connect (button, "clicked", G_CALLBACK (printf("%s\n", text)), text);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
--------------------------------------------------------------------------------
GtkBox GtkGrid GtkRevealer GtkStack
GtkOverlay GtkPaned GtkExpander GtkFixed
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (box, GTK_ALIGN_FILL);
gtk_widget_set_valign (box, GTK_ALIGN_CENTER); // START CENTER END FILL
gtk_window_set_child (GTK_WINDOW (window), box);
puis, après déclaration du bouton, gtk_box_append (GTK_BOX (box), button);
grid = gtk_grid_new ();
gtk_window_set_child (GTK_WINDOW (window), grid);
button = gtk_button_new_with_label (" I "); n fois
gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1); n fois
--------------------------------------------------------------------------------
TODO (or NOT TODO)
GtkWidget *get_text_view(){ // WTF ?!& @Grr #~!
// https://docs.gtk.org/gtk4/section-text-widget.html
GtkWidget *my_view = gtk_text_view_new ();
GtkTextTagTable *my_table = gtk_text_tag_table_new ();
GtkTextBuffer *my_buffer = gtk_text_buffer_new (my_table);
gtk_text_buffer_set_text (my_buffer, "Hello, this is some text", -1);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (my_view), my_buffer);
/* Now you might put the view in a container and display it on the
* screen; when the user edits the text, signals on the buffer
* will be emitted, such as "changed", "insert_text", and so on.
*/
return my_view;
}
/*
https://docs.gtk.org/gtk4/class.ApplicationWindow.html
GtkApplication *app = gtk_application_new ("org.gtk.test", 0);
GtkBuilder *builder = gtk_builder_new_from_string (
"<interface>"
" <menu id='menubar'>"
" <submenu>"
" <attribute name='label' translatable='yes'>_Edit</attribute>"
" <item>"
" <attribute name='label' translatable='yes'>_Copy</attribute>"
" <attribute name='action'>win.copy</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>_Paste</attribute>"
" <attribute name='action'>win.paste</attribute>"
" </item>"
" </submenu>"
" </menu>"
"</interface>",
-1);
GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));
gtk_application_set_menubar (GTK_APPLICATION (app), menubar);
g_object_unref (builder);
// ...
GtkWidget *window = gtk_application_window_new (app);
*/
//------------------------------------------------------------------------------
GtkScrolledWindow *get_scrolled_gl_area(){
GtkScrolledWindow *scrolled = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new());
gtk_scrolled_window_set_min_content_width (scrolled, W_IMAGE);
gtk_scrolled_window_set_min_content_height (scrolled, H_IMAGE);
// GtkAdjustment *width = gtk_adjustment_new (600, 300, 1000, 1, 1, 1000);
// GtkAdjustment *height = gtk_adjustment_new (600, 300, 1000, 1, 1, 1000);
// (value, lower, upper, step_increment, page_increment, page_size)
// GtkWidget *GLarea = gtk_gl_area_new();
// gtk_scrolled_window_set_child (scrolled, GLarea);
// https://docs.gtk.org/gtk4/class.GLArea.html
return scrolled;
}
// https://docs.gtk.org/gtk4/getting_started.html (m'aura bien servi, quand même !)
//typedef anytype = {(int)(*fnct) {printf("typedef {(int)(*fnct) {printf("");}");} GtkModelFnct;
/*
essai run-stop, speed et step by step dans une seule box controls
-----------------------------------------------------------------
#include <stdio.h>
#include <gtk-4.0/gtk/gtk.h>
#include "cold.h"
void print_text(GtkWidget *widget, gpointer data) {g_print (data);}
GtkWidget *get_a_space_test_image(){
GtkWidget *image;
image = GTK_WIDGET(get_scrolled_gl_area());
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/images/aXoris.png");
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/images/gg sketch.png");
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/images/E coli.png");
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/images/E coli resized.png");
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/E coli by David S. Goodsell (2009).png");
return image;
}
GtkWidget *get_scroll_speed(){
GtkAdjustment *speed_adjust = gtk_adjustment_new (0, 0, 100, 1, 0, 0);
GtkWidget *scroll_speed = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, speed_adjust);
return scroll_speed;
}
// TODO cliquer sur "RUN" --> affiche "STOP" (et inversement)
GtkBox *get_RUN_STOP_box(){
GtkBox *RUN_STOP_box = GTK_BOX(gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2)); // spacing = 2
GtkWidget *RUN_Label = GTK_WIDGET (gtk_label_new (NULL)); // "RUN"));
const char *str = " RUN\n STOP";
const char *format = "<span style=\"oblique\">\%s</span>";
char *markup;
markup = g_markup_printf_escaped (format, str);
gtk_label_set_markup (GTK_LABEL (RUN_Label), markup); // Sets the labels text and attributes from markup.
g_free (markup);
gtk_label_set_max_width_chars (GTK_LABEL(RUN_Label), 12);
gtk_label_set_wrap (GTK_LABEL(RUN_Label), TRUE);
gtk_label_set_xalign (GTK_LABEL(RUN_Label), 0.5); // xalign value, between 0 and 1
gtk_label_set_yalign (GTK_LABEL(RUN_Label), 0.5);
gtk_label_set_selectable (GTK_LABEL(RUN_Label), FALSE); // default = FALSE
gtk_label_set_single_line_mode (GTK_LABEL(RUN_Label), TRUE); // default = TRUE
//
gtk_box_append (RUN_STOP_box, RUN_Label);
return RUN_STOP_box;
}
GtkBox *get_STEP_by_STEP_box(){
GtkBox *STEP_by_STEP_box = GTK_BOX(gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
GtkWidget *STEP_by_STEP_Label = GTK_WIDGET (gtk_label_new ("ONE\nSTEP"));
gtk_box_append (STEP_by_STEP_box, STEP_by_STEP_Label);
return STEP_by_STEP_box;
}
GtkBox *get_CONTROL_box(){
GtkBox *CONTROL_box = GTK_BOX(gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
gtk_box_append (CONTROL_box, GTK_WIDGET (get_RUN_STOP_box()));
gtk_box_append (CONTROL_box, GTK_WIDGET (get_scroll_speed()));
gtk_box_append (CONTROL_box, GTK_WIDGET (get_STEP_by_STEP_box()));
return CONTROL_box;
}
*/

158
Makefile
View File

@ -1,24 +1,158 @@
all: Getting_Started_with_GTK .PHONY: run clean install all
.DELETE_ON_ERROR: $(BINDIR)/Getting_Started_with_GTK
.DEFAULT_GOAL: all
NTHREADS= $(shell nproc)
CC=gcc
CFLAGS=`pkg-config --cflags gtk4 gl glib-2.0 libxml-2.0`
LDFLAGS=`pkg-config --libs gtk4 gl glib-2.0 libxml-2.0` -lGL -lGLU -lm -lepoxy -lX11 -lGLEW
WARNINGS = -Wall WARNINGS = -Wall
DEBUG = -ggdb -fno-omit-frame-pointer DEBUG = -ggdb -fno-omit-frame-pointer #-fdiagnostics-color=always -fsanitize=bounds -fstack-check
OPTIMIZE = -O2 OPTIMIZE = -O3
BINDIR=bin
BUILDDIR=build
SRCDIR=src
Getting_Started_with_GTK: Makefile main.c sources = $(shell find . -maxdepth 1 -type f -name "*.c")
$(CC) -o $@ $(WARNINGS) $(DEBUG) $(OPTIMIZE) main.c objects = $(patsubst %.c,%.o,$(sources))
dependencies = $(patsubst %.c,%.d,$(sources))
clean: all: myprogram
rm -f Getting_Started_with_GTK
-include $(dependencies)
myprogram: $(objects)
$(CC) $(LDFLAGS) $(WARNINGS) $(DEBUG) $(OPTIMIZE) $^ -o $@
%.o: %.c Makefile
$(CC) $(CFLAGS) $(WARNINGS) $(DEBUG) $(OPTIMIZE) -c $< -o $@
%.d: %.c Makefile
$(CC) $(CFLAGS) -MM -MT $(@:%.d=%.o) -MF $@ $<
# Builder will call this to install the application before running.
install: install:
echo "Installing is not supported" echo "Installing is not supported"
# Builder uses this target to run your application. run: myprogram
run: ./myprogram
./main
# gcc $( pkg-config --cflags gtk4 ) -o main main.c $( pkg-config --libs gtk4 ) clean:
rm -f myprogram
rm -f *.o
rm -f *.d
# /!\ erreur fatale: GL/glu.h <?>
# gcc -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -g -Wall -Wextra
# -std=c99 -lm *.c -o formattage `pkg-config --cflags --libs glib-2.0`
#------------------------------------------------------------------------------#
# 'make' has an implicit rule for updating a .o file #
# from a correspondingly named .c file #
# using a cc -c command. #
# Implicit rules are listed and applied in a predefined order (C before P...) #
# Predefined implicit rules are implemented in make as suffix rules #
# The default suffix list is: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p,... #
# Rules whose suffixes fail to be on the list are disabled. #
# You can define your own implicit rules by writing pattern rules. #
#------------------------------------------------------------------------------#
# If there are many implicit rules with the same target pattern,
# the rule that actually applies is the one whose prerequisites exist or can be made
# ex: a .o can be made from a .c (C compiler) or a .p (Pascal compiler)
# Variables allow a text string to be defined once
# and substituted in multiple places later.
# (see Chapter 6 [How to Use Variables], page 65)
#------------------------------------------------------------------------------#
# To study : how can the following commands be modified ? #
#------------------------------------------------------------------------------#
#SHELL = /bin/sh
#.SUFFIXES:
#.SUFFIXES: .c .o .h # is .h useful ?
#.PHONY = run
#.PHONY = clean
#.PHONY: Makefile
#CC=gcc
#CFLAGS=`pkg-config --cflags gtk4 --libs gtk4`
#WARNINGS = -Wall
#DEBUG = -ggdb -fno-omit-frame-pointer
#OPTIMIZE = -O2
# in exec.o:
# $(WARNINGS) $(DEBUG) $(OPTIMIZE) < ne sont pas indispensables
# si le $@ est supprimé, main.cest modifié
#all:
# exec
#install:
# echo "Installing is not supported"
#------------------------------------------------------------------------------#
# Personnal notes & links #
#------------------------------------------------------------------------------#
# gcc $( pkg-config --cflags gtk4 ) -o exec main.c $( pkg-config --libs gtk4 )
# https://www.gnu.org/software/make/manual/
# Makefiles contain five kinds of things:
# explicit rules, implicit rules, variable definitions, directives and comments.
# Variables automatiques --------------------------------------------------
# $@ fait référence à la cible de la règle (au nom de la cible).
# $< fait référence à la première dépendance.
# $? fait référence aux noms de touess les dépendances plus récentes que la cible.
# = les fichiers qui ont été modifiés après la compilation de code la plus récente
# $^ fait référence aux noms de touess les dépendances avec des espaces entre eux.
# Variables implicites -------------------------------------------------
# VPATH Équivalent utilitaire de la variable PATH de Bash. Vide par défaut.
# Les chemins sont séparés par le signe deux-points (:).
# CC Le programme pour compiler des fichiers C.
# La valeur par défaut est cc. (Habituellement, cc pointe vers gcc.)
# CPP Le programme qui exécute le préprocesseur C.
# La valeur par défaut est $ (CC) -E.
# LEX Le programme qui transforme les grammaires lexicales en code source.
# La valeur par défaut est lex. (Vous devriez remplacer cela par flex.)
# LINT Le programme qui lint votre code source. La valeur par défaut est lint.
# RM La commande pour supprimer un fichier. La valeur par défaut est rm -f.
# CFLAGS Contient tous les indicateurs du compilateur C (cc).
# CPPFLAGS tous les indicateurs du préprocesseur C.
# .PHONY Spécifie des cibles qui ne ressemblent pas au nom d'un fichier.
# Un exemple est la cible "make clean" ; où clean est une valeur de .PHONY
# Syntaxe de Base
# Règles : Une règle se compose d'une cible, des dépendances et des commandes.
# Elle est généralement structurée comme suit :
# cible: dépendances
# commande
#
# La cible (target) est le fichier à générer,
# les dépendances (prerequisites) sont les fichiers requis pour construire la cible
# et les commandes (recipe) sont les instructions exécutées pour créer la cible.
#
# A simple makefile consists of “rules” with the following shape:
# target ... : prerequisites ...
# recipe
# ...
# A target is usually the name of a file that is generated by a program;
# examples of targets are executable or object files.
# A target can also be the name of an action to carry out, such as clean
# accessoirement : https://blog.stephane-robert.info/docs/makefile/ & /docs/task/

View File

@ -1,132 +0,0 @@
##
## Gem-graph OpenGL experiments
##
## Desc: Makefile
##
## Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
## Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
##
## This file is part of Gem-graph.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU Affero General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Affero General Public License for more details.
##
## You should have received a copy of the GNU Affero General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
##
.PHONY: all clean install run build_system
.DELETE_ON_ERROR: $(BINDIR)/gem-graph-client
.DEFAULT_GOAL := all
#
# Color codes
#
CL='\033[0;32m'
CL2='\033[1;36m'
CL3='\033[0m'
NC='\033[1;37m'
#
# Variables & constants
#
NTHREADS= $(shell nproc)
CC=gcc
WARNINGS= -Wall
DEBUG= -ggdb -fno-omit-frame-pointer -fdiagnostics-color=always -fsanitize=bounds -fstack-check
#-fsanitize=address \
#-fsanitize=pointer-compare -fsanitize=pointer-subtract \
#-fsanitize=leak -fsanitize=undefined -fsanitize=null -fsanitize=bounds
OPTIMIZE= -O3
INCLUDE= $(shell pkg-config --cflags glib-2.0 libxml-2.0 gtk4)
LIBS= $(shell pkg-config --libs glib-2.0 libxml-2.0 gtk4) -lGL -lGLU -lm -lepoxy -lX11 -lGLEW
BINDIR=bin
BUILDDIR=build
SRCDIR=src
#vpath %.c $(SRCDIR)
SOURCES= $(shell find $(SRCDIR) -type f -name "*.c")
BUILDBINS=$(patsubst %.c,$(BUILDDIR)/%.o,$(SOURCES))
BUILDDEPS=$(patsubst %.c,$(BUILDDIR)/%.d,$(SOURCES))
-include /etc/os-release
#
# Directories
#
$(BUILDDIR):
@mkdir -p $@
@echo -e ${CL2}[$@] ${CL}folder generated.${CL3}
$(BINDIR):
@mkdir -p $@
@echo -e ${CL2}[$@] ${CL}folder generated.${CL3}
#
# Dependencies
#
-include $(BUILDDEPS)
$(BUILDDIR)/%.d: %.c | $(BUILDDIR)
@mkdir -p $(shell dirname $@)
@$(CC) -MM -MT $(@:%.d=%.o) -MF $@ $<
@echo -e ${CL2}[$@] ${CL}dependencies generated.${CL3}
#
# Compilation
#
$(BINDIR)/gem-graph-client: $(BUILDBINS) | $(BINDIR)
@$(CC) -o $@ $(WARNINGS) $(DEBUG) $(OPTIMIZE) $^ $(INCLUDE) $(LIBS)
@echo -e ${CL2}[$@] ${CL}built.${CL3}
$(BUILDDIR)/%.o: %.c | $(BUILDDIR)
@mkdir -p $(shell dirname $@)
@$(CC) $(WARNINGS) $(DEBUG) $(OPTIMIZE) $(INCLUDE) -c $< -o $@
@echo -e ${CL2}[$@] ${CL}compiled.${CL3}
#
# Virtual recipes
#
clean:
@rm -rf $(BINDIR)
@rm -rf $(BUILDDIR)
@echo -e ${CL2}[$@] ${CL}done.${CL3}
install:
echo "Installing is not supported"
build_system:
@echo -e ${CL2}[$@] ${CL}building...${CL3}
@make $(BINDIR)/gem-graph-client -j $(NTHREADS)
@echo -e ${CL2}[$@] ${CL}done.${CL3}
run: build_system
@echo -e ${CL2}[$@] ${CL}executing...${CL3}
@$(BINDIR)/gem-graph-client
@echo -e ${CL2}[$@] ${CL}done.${CL3}
debug: build_system
@echo -e ${CL2}[$@] ${CL}executing...${CL3}
@gdb $(BINDIR)/gem-graph-client
@echo -e ${CL2}[$@] ${CL}done.${CL3}
valgrind: build_system
@echo -e ${CL2}[$@] ${CL}executing...${CL3}
@valgrind $(BINDIR)/gem-graph-client
@echo -e ${CL2}[$@] ${CL}done.${CL3}
all: build_system
@echo -e ${CL2}[$@] ${CL}done.${CL3}

79
automaton.c Normal file
View File

@ -0,0 +1,79 @@
#include <gtk-4.0/gtk/gtk.h>
#include <assert.h>
#include "callback.h"
#include "automaton.h"
/******************************************************************************/
/* S T A T E S */
/******************************************************************************/
static int choice_EXEC_EDIT = EXEC;
static int choice_STATE_RULES_DATA = STATE;
/******************************************************************************/
/* T R A N S I T I O N S */
/******************************************************************************/
static void debug_printing (int prescribed, int sub_automaton);
void set_EXEC_EDIT (int prescribed) {
if (choice_EXEC_EDIT != prescribed) {
debug_printing (prescribed, 0); // EXEC_EDIT is sub_automaton 0
choice_EXEC_EDIT = prescribed;
}
}
void set_STATE_RULES_DATA (int prescribed) {
if (choice_STATE_RULES_DATA != prescribed) {
debug_printing (prescribed, 1); // STATE_RULES_DATA is sub_automaton 1
choice_STATE_RULES_DATA = prescribed;
}
}
/******************************************************************************/
/* G E T T E R S & D E B U G G E R S */
/******************************************************************************/
int get_EXEC_EDIT () {return choice_EXEC_EDIT;}
int get_STATE_RULES_DATA () {return choice_STATE_RULES_DATA;}
static char *get_str_EXEC_EDIT (int value) {
switch (value) {
case (EXEC) : return "EXEC";
case (EDIT) : return "EDIT";
default : printf("default in automaton.get_EXEC_EDIT ()\n"); return NULL;
}
}
static char *get_str_STATE_RULES_DATA (int value) {
switch (value) {
case (STATE) : return "STATE";
case (RULES) : return "RULES";
case (DATA) : return "DATA";
default : printf("default in automaton.get_STATE_RULES_DATA ()\n"); return NULL;
}
}
static void debug_printing (int prescribed, int sub_automaton) {
switch (sub_automaton) { // sub_automaton 0 is EXEC_EDIT and
// sub_automaton 1 is STATE_RULES_DATA
case (0) : printf("switch > %5s X %5s <> %5s X %5s\n",
get_str_EXEC_EDIT (choice_EXEC_EDIT),
get_str_STATE_RULES_DATA (choice_STATE_RULES_DATA),
get_str_EXEC_EDIT (prescribed),
get_str_STATE_RULES_DATA (choice_STATE_RULES_DATA));
break;
case (1) : printf("switch > %5s X %5s <> %5s X %5s\n",
get_str_EXEC_EDIT (choice_EXEC_EDIT),
get_str_STATE_RULES_DATA (choice_STATE_RULES_DATA),
get_str_EXEC_EDIT (choice_EXEC_EDIT),
get_str_STATE_RULES_DATA (prescribed));
break;
default : printf("default in automaton.debug_printing()\n");
}
}

16
automaton.h Normal file
View File

@ -0,0 +1,16 @@
#include <gtk-4.0/gtk/gtk.h>
#include <assert.h>
enum choice_EXEC_EDIT { EXEC, EDIT };
enum choice_STATE_RULES_DATA { STATE, RULES, DATA };
// MEASURE, OBSERVE, INTERPRET, HELP, CONFIGURE }; ?
void set_EXEC_EDIT (int prescribed);
void set_STATE_RULES_DATA (int prescribed);
int get_EXEC_EDIT ();
int get_STATE_RULES_DATA ();
// char *get_str_EXEC_EDIT (int value);
// char *get_str_STATE_RULES_DATA (int value);

91
base.h Normal file
View File

@ -0,0 +1,91 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: Base header
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib-2.0/glib.h>
//#define G_APPLICATION_DEFAULT_FLAGS 0
enum { X_AXIS, Y_AXIS, Z_AXIS, N_AXIS }; // < used by : graph_area.h
enum { HOME_MODE, RUN_MODE, EDIT_MODE, PRESENTATION_MODE, N_MODE }; // Gem-graph modes
struct arrow_t { uint load; uint site; uint x; uint y; uint z; }; // describes an arrow
static inline char *read_file(char *filename); // < used by : init.c
/* I'm standing on Earth (or any spinning spheroid) and looking towards its North pole, then :
X - X = EAST - WEST = rouge - cyan
Y - Y = ZENITH - NADIR = vert - magenta (fuschia)
Z - Z = NORTH - SOUTH = bleu - jaune */
#define EAST 0 // + x rouge
#define WEST 1 // - x cyan
#define ZENITH 2 // + y vert
#define NADIR 3 // - y magenta
#define SOUTH 4 // + z bleu
#define NORTH 5 // - z jaune
/*
* char *read_file(char *filename) reads a file from filename into a provided buffer
*
* @param filename, file name
* contents, target ptr
*
* @return void
*/
static inline char *read_file(char *filename)
{
int fd;
int filesize;
char *contents;
fd = open(filename, O_RDONLY);
if(fd < 0) {
printf("Couldn't read file: %s\n",filename);
return NULL;
}
filesize = lseek(fd, 0, SEEK_END) + 1 ;
contents = g_malloc(filesize * sizeof(char));
assert (contents);
lseek(fd, 0, SEEK_SET);
read(fd,contents,filesize);
contents[filesize-1] = '\0';
close(fd);
return contents;
}

219
callback.c Normal file
View File

@ -0,0 +1,219 @@
#include <stdio.h>
#include <gtk-4.0/gtk/gtk.h>
#include "callback.h"
#include "contain.h"
#include "tree.h"
#include "contain.h"
#include "dialog.h"
#include "texts.h"
#include "automaton.h"
#include "parsing.h"
#include "graph_area.h"
/******************************************************************************/
/* W I N D O W S A C T I V A T I O N */
/******************************************************************************/
static GtkWindow *main_window, *dialog_window;
void on_main_window_activation (GtkApplication *app, gpointer no_user_data)
{
main_window = GTK_WINDOW (gtk_application_window_new (app));
main_window_design (main_window);
g_signal_connect (app, "activate", G_CALLBACK (on_dialog_window_activation), main_window);
}
void on_dialog_window_activation (GtkApplication *app, gpointer no_user_data)
{
dialog_window = GTK_WINDOW (gtk_application_window_new (app));
dialog_window_design (main_window, dialog_window);
}
void on_auto_notification (const char *message)
{
/* Ignored (2024-06-06) because I don't know how to get "main_window" easily
if (window->toast_revealer == NULL) {
g_printerr("Can't find app->toast_overlay !\n");
return;
}
if (window->toast_text == NULL) {
g_printerr("Can't find app->toast_overlay !\n");
return;
}
gtk_label_set_label(window->toast_text, message);
gtk_revealer_set_reveal_child(window->toast_revealer, true);
*/
g_printerr("%s\n", message);
}
/******************************************************************************/
/* T R E E */
/******************************************************************************/
void on_user_tree_expander_toggled (GtkExpander *expander, gpointer user_data)
{
GtkTreeListRow *row = GTK_TREE_LIST_ROW (user_data);
gboolean is_expanded = gtk_tree_list_row_get_expanded(row);
gtk_tree_list_row_set_expanded (row, !is_expanded);
}
void on_bind_user_tree_factory (GtkSignalListItemFactory *factory, GObject* object, gpointer user_data)
{
GtkListItem *list_item = GTK_LIST_ITEM (object); assert (list_item);
GtkTreeListRow *row = gtk_list_item_get_item (list_item); assert (row); // if (row != NULL) {...} ?
const gchar *text = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_tree_list_row_get_item (row)));
GtkWidget *expander = gtk_list_item_get_child (list_item);
gtk_expander_set_label (GTK_EXPANDER (expander), text);
g_signal_handlers_disconnect_by_func(expander, G_CALLBACK (on_user_tree_expander_toggled), row);
g_signal_connect(expander, "activate", G_CALLBACK (on_user_tree_expander_toggled), row);
gtk_widget_set_margin_start(expander, gtk_tree_list_row_get_depth(row) * 20);
}
/******************************************************************************/
/* G L A R E A */
/******************************************************************************/
gboolean on_glarea_render(GtkGLArea *area, GdkGLContext *context)
{
// Check if the widget is a glarea
if(gtk_gl_area_get_error(area) != NULL) {
on_auto_notification("An OpenGL error occured !");
return false;
}
if (ui_render_stack(gtk_widget_get_parent(GTK_WIDGET(area))) == false) {
on_auto_notification("Failed to render corresponding graphic stack !");
return false;
}
return true;
}
/* We need to set up our state when we realize the GtkGLArea widget */
void on_glarea_realize(GtkWidget *widget)
{
GError *internal_error = NULL;
// Make the GL context current to be able to call the GL API
gtk_gl_area_make_current(GTK_GL_AREA(widget));
// Check if the widget is a glarea
if(gtk_gl_area_get_error(GTK_GL_AREA(widget)) != NULL) {
on_auto_notification("An OpenGL error occured !");
return;
}
// Link graphical stack to widget
if (ui_init_graphic_stack(gtk_widget_get_parent(widget),
internal_error) == false) {
on_auto_notification(
"Failed to link the graphic stack to widgets !");
return;
}
gtk_gl_area_set_auto_render(GTK_GL_AREA(widget), true);
}
/* We should tear down the state when unrealizing */
void on_glarea_unrealize(GtkWidget *widget)
{
GError *internal_error = NULL;
// Make the GL context current to be able to call the GL API
gtk_gl_area_make_current(GTK_GL_AREA(widget));
// Check if the widget is a glarea
if(gtk_gl_area_get_error(GTK_GL_AREA(widget)) != NULL) {
on_auto_notification("An OpenGL error occured !");
return;
}
// Destroy graphic stack
if (ui_shutdown_graphic_stack(gtk_widget_get_parent(widget),
internal_error) == false) {
on_auto_notification(
"Failed to shutdown the graphic stack !");
return;
}
}
void on_axis_value_change(GtkAdjustment *adjustment, gpointer data)
{
GtkWidget *slider = gtk_widget_get_parent(GTK_WIDGET(data));
GtkWidget *container_widget = gtk_widget_get_parent(GTK_WIDGET(slider));
const gchar *label_text = gtk_label_get_label(GTK_LABEL(data));
// THANKS ASCIIIII/Unicode/Whateverrr !
int axis = label_text[0] - 'X';
g_assert(axis >= 0 && axis < N_AXIS);
/* Update the rotation angle */
ui_update_axis_stack(container_widget,
axis,
gtk_adjustment_get_value(adjustment));
/* Update the contents of the GL drawing area */
}
/******************************************************************************/
/* B U T T O N S */
/******************************************************************************/
void on_toggle_EXEC_EDIT (GtkWidget *toggled_button, gpointer user_data) {
if (get_EXEC_EDIT ()) {
gtk_button_set_icon_name (GTK_BUTTON (toggled_button), "power-profile-balanced-rtl-symbolic");
set_EXEC_EDIT (EXEC);
} else {
gtk_button_set_icon_name (GTK_BUTTON (toggled_button), "text-editor-symbolic");
set_EXEC_EDIT (EDIT);
}
switch (get_STATE_RULES_DATA()) {
case (STATE) : gtk_window_set_child (main_window, GTK_WIDGET (get_window_child_STATE())); break;
case (RULES) : gtk_window_set_child (main_window, GTK_WIDGET (get_window_child_RULES())); break;
case (DATA) : gtk_window_set_child (main_window, GTK_WIDGET (get_window_child_DATA())); break;
default : printf("default in callback.on_toggle_STATE_RULES_DATA()\n");
}
}
void on_toggle_STATE_RULES_DATA (GtkWidget *toggled_button, gpointer user_data) {
const char *toggled_button_name = gtk_check_button_get_label (GTK_CHECK_BUTTON (toggled_button));
int is_active = gtk_check_button_get_active (GTK_CHECK_BUTTON (toggled_button));
if (! strcmp (toggled_button_name, "state")) set_STATE_RULES_DATA (STATE);
if (! strcmp (toggled_button_name, "rules")) set_STATE_RULES_DATA (RULES);
if (! strcmp (toggled_button_name, "data analysis")) set_STATE_RULES_DATA (DATA);
if (is_active)
switch (get_STATE_RULES_DATA()) {
case (STATE) : gtk_window_set_child (main_window, GTK_WIDGET (get_window_child_STATE())); break;
case (RULES) : gtk_window_set_child (main_window, GTK_WIDGET (get_window_child_RULES())); break;
case (DATA) : gtk_window_set_child (main_window, GTK_WIDGET (get_window_child_DATA())); break;
default : printf("default in callback.on_toggle_STATE_RULES_DATA()\n");
}
}
void on_SAVE_CURRENT_MODEL_BEFORE_EDITING (GtkWidget *btt_SAVE_CURRENT_MODEL, gpointer data) {
gtk_widget_set_sensitive (GTK_WIDGET (data), TRUE);
printf ("callback.c (line 201) - SAVE_CURRENT_MODEL_BEFORE_EDITING\n");
}
void on_DISCARD_CURRENT_MODEL_AND_START_EDITING (GtkWidget *btt_SAVE_CURRENT_MODEL, gpointer data) {
gtk_window_close (GTK_WINDOW (data));
printf ("callback.c (line 206) - DISCARD_CURRENT_MODEL_AND_START_EDITING\n");
}
void on_WRITE_CURRENT_MODEL (GtkWidget *btt_WRITE_CURRENT_MODEL, gpointer data) {
gtk_window_close (GTK_WINDOW (data));
printf ("callback.c (line 211) - WRITE_CURRENT_MODEL\n");
}

27
callback.h Normal file
View File

@ -0,0 +1,27 @@
#include <gtk-4.0/gtk/gtk.h>
void on_main_window_activation (GtkApplication *app, gpointer user_data);
void on_dialog_window_activation (GtkApplication *app, gpointer user_data);
void on_auto_notification (const char *message);
void on_user_tree_expander_toggled (GtkExpander *expander, gpointer user_data);
void on_bind_user_tree_factory (GtkSignalListItemFactory *factory, GObject* object, gpointer user_data);
gboolean on_glarea_render (GtkGLArea *area, GdkGLContext *context);
void on_glarea_realize (GtkWidget *widget);
void on_glarea_unrealize (GtkWidget *widget);
void on_axis_value_change (GtkAdjustment *adjustment, gpointer data);
void on_toggle_EXEC_EDIT (GtkWidget *btt_XOR_EXEC_EDIT, gpointer user_data);
void on_toggle_MODEL_RUN_STOP (GtkWidget *btt_MODEL_RUN_STOP, gpointer data);
void on_open_STATE (GtkWidget *btt_open_STATE, gpointer data);
void on_open_RULES (GtkWidget *btt_open_RULES, gpointer data);
void on_open_DATA (GtkWidget *btt_open_DATA, gpointer data);
void on_SAVE_CURRENT_MODEL_BEFORE_EDITING (GtkWidget *btt_SAVE_CURRENT_MODEL, gpointer data);
void on_DISCARD_CURRENT_MODEL_AND_START_EDITING (GtkWidget *btt_SAVE_CURRENT_MODEL, gpointer data);
void on_WRITE_CURRENT_MODEL (GtkWidget *btt_WRITE_CURRENT_MODEL, gpointer data);
void on_toggle_STATE_RULES_DATA (GtkWidget *btt, gpointer user_data);

426
contain.c Normal file
View File

@ -0,0 +1,426 @@
#include <stdio.h>
#include <gtk-4.0/gtk/gtk.h>
#include "graph_area.h"
#include "callback.h"
#include "automaton.h"
#include "display.h"
#include "tree.h"
#include "texts.h"
// https://blog.gtk.org/2020/09/08/on-list-models/ < TODO
// https://docs.gtk.org/gtk4/visual_index.html < widgets gallery
GtkFrame *get_frame_with_label(){ // EN ATTENDANT DE SAVOIR UTILISER : GtkTextTagTable , GtkTextBuffer
GtkFrame *space_specif = GTK_FRAME(gtk_frame_new ("Space (run / edit) specifications"));
GtkWidget *any_Label = GTK_WIDGET (gtk_label_new (get_space_run_edit_specif()));
gtk_frame_set_child (GTK_FRAME (space_specif), GTK_WIDGET (any_Label));
return space_specif;
}
GtkWidget *get_edit_rules_page_new(){
GtkPaned *hpaned = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_HORIZONTAL));
GtkWidget *arbre_des_règles = gtk_frame_new ("Arbre des règles");
GtkWidget *édition_de_la_règle_sélectionnée = gtk_frame_new ("Édition de la règle sélectionnée");
gtk_paned_set_start_child (hpaned, GTK_WIDGET (arbre_des_règles));
gtk_paned_set_end_child (hpaned, GTK_WIDGET (édition_de_la_règle_sélectionnée));
// gtk_widget_set_size_request (GTK_WIDGET (hpaned), W, H);
gtk_paned_set_wide_handle (hpaned, TRUE);
return GTK_WIDGET (hpaned);
}
GtkWidget *get_edit_measures_page_new(){
GtkWidget *measures_grid = gtk_grid_new();
return measures_grid;
}
GtkWidget *get_edit_results_page_new(){
GtkWidget *xxx_grid = gtk_grid_new();
return xxx_grid;
}
GtkWidget *get_edit_discuss_page_new(){
GtkWidget *xxx_grid = gtk_grid_new();
return xxx_grid;
}
GtkWidget *get_edit_help_page_new(){
GtkWidget *edit_help_grid = gtk_grid_new();
gtk_grid_attach (GTK_GRID(edit_help_grid), GTK_WIDGET(get_frame_with_label()), 0, 0, 1, 1);
return edit_help_grid;
}
GtkWidget *get_measures_page_new(){
GtkWidget *measures_grid = gtk_grid_new();
gtk_grid_attach (GTK_GRID (measures_grid), gtk_button_new_with_label ("movements"), 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (measures_grid), gtk_button_new_with_label ("transports"), 1, 0, 1, 1);
gtk_grid_attach (GTK_GRID (measures_grid), gtk_button_new_with_label ("transformations"), 2, 0, 1, 1);
gtk_grid_attach (GTK_GRID (measures_grid), gtk_button_new_with_label ("objects"), 0, 1, 1, 1);
gtk_grid_attach (GTK_GRID (measures_grid), gtk_button_new_with_label ("situations"), 1, 1, 1, 1);
return measures_grid;
}
GtkWidget *get_results_page_new(){
GtkWidget *results_grid = gtk_grid_new();
gtk_grid_attach (GTK_GRID(results_grid), gtk_button_new_with_label ("Repartitions"), 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID(results_grid), gtk_button_new_with_label ("Correlations"), 0, 1, 1, 1);
gtk_grid_attach (GTK_GRID(results_grid), gtk_button_new_with_label ("Evolutions"), 0, 2, 1, 1);
return results_grid;
}
GtkWidget *get_discuss_page_new(){
GtkWidget *discuss_grid = gtk_grid_new();
gtk_grid_attach (GTK_GRID (discuss_grid), gtk_button_new_with_label ("Interpretations"), 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (discuss_grid), gtk_button_new_with_label ("Discussions"), 0, 1, 1, 1);
return discuss_grid;
}
GtkWidget *get_help_page_new(){
GtkWidget *run_help_grid = gtk_grid_new();
gtk_grid_attach (GTK_GRID(run_help_grid), GTK_WIDGET(get_frame_with_label()), 0, 0, 1, 1);
return run_help_grid;
}
GtkWidget *get_edit_space_page_new(){
GtkWidget *space_grid = gtk_grid_new();
gtk_grid_attach (GTK_GRID(space_grid), get_image_ALL_SPACE(), 0, 0, 1, 3);
gtk_grid_attach (GTK_GRID(space_grid), get_OBJECTS_and_SITUATIONS(), 0, 4, 1, 1);
gtk_grid_attach (GTK_GRID(space_grid), GTK_WIDGET (get_XYZ_box()), 1, 0, 1, 2);
gtk_grid_attach (GTK_GRID(space_grid), GTK_WIDGET (get_ZOOM_box()), 1, 2, 1, 2);
gtk_grid_attach (GTK_GRID(space_grid), GTK_WIDGET (get_edit_TOOL_box()), 1, 3, 1, 2);
gtk_widget_set_size_request (space_grid, W, H);
return space_grid;
}
//------------------------------------------------------------------------------
GtkWidget *get_selected_rules_vpaned_new(){
GtkPaned *V_selected_1_vs_2 = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_VERTICAL));
GtkBox *up_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2));
gtk_box_append (up_box, GTK_WIDGET (get_image_GLUTAMATE()));
gtk_box_append (up_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
gtk_box_append (up_box, GTK_WIDGET (get_image_GLUTAMINE()));
GtkBox *bottom_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2));
gtk_box_append (bottom_box, GTK_WIDGET (get_image_ATP()));
gtk_box_append (bottom_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
gtk_box_append (bottom_box, GTK_WIDGET (get_image_AMP()));
gtk_paned_set_start_child (V_selected_1_vs_2, GTK_WIDGET (up_box));
gtk_paned_set_end_child (V_selected_1_vs_2, GTK_WIDGET (bottom_box));
return GTK_WIDGET (V_selected_1_vs_2);
}
GtkWidget *get_TIME_EXEC_controls_box(){
GtkBox *top_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2));
gtk_box_append (top_box, GTK_WIDGET (get_ELAPSED_TIME_ProgressBar()));
gtk_box_append (top_box, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
gtk_box_append (top_box, GTK_WIDGET (get_RUN_STOP_box()));
return GTK_WIDGET (top_box);
}
GtkWidget *get_SPACE_VIEW_box(){
GtkBox *right_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 2));
gtk_box_append (right_box, GTK_WIDGET (get_XYZ_box()));
gtk_box_append (right_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (right_box, GTK_WIDGET (get_ZOOM_box()));
GtkBox *middle_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2));
gtk_box_append (middle_box, GTK_WIDGET (get_image_ALL_SPACE()));
// ui_setup_glarea (0, GTK_WIDGET (middle_box));
gtk_box_append (middle_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
gtk_box_append (middle_box, GTK_WIDGET (right_box));
return GTK_WIDGET (middle_box);
}
GtkWidget *get_SPACE_EDIT_controls_box() {
GtkWidget *label_ad_hoc = gtk_label_new ("_____________\n\
SPACE EDIT\n controls\n_____________");
return GTK_WIDGET (label_ad_hoc);
}
static void icons_for_fun (GtkHeaderBar *header_bar);
static GtkButton *btt_open_STATE;
static GtkButton *btt_open_RULES;
static GtkButton *btt_open_DATA;
GtkButton *get_GtkButton (char *btt_name) {
if (strcmp (btt_name, "state")) return btt_open_STATE;
if (strcmp (btt_name, "rules")) return btt_open_RULES;
if (strcmp (btt_name, "data analysis")) return btt_open_DATA;
return NULL;
}
void set_check_button_active (GtkButton *button, int active){
const char *lab = gtk_button_get_label (button);
if (strcmp (lab, "state")) printf("set_check_button_active > %s\n", lab);
}
void window_header_bar (GtkWindow *window, char *title){
GtkWidget *header_bar = GTK_WIDGET (gtk_header_bar_new ());
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header_bar), gtk_label_new (title));
gtk_window_set_titlebar (window, header_bar);
gpointer no_local_data = NULL;
GtkButton *btt_XOR_EXEC_EDIT = GTK_BUTTON (gtk_toggle_button_new ());
gtk_button_set_icon_name (btt_XOR_EXEC_EDIT, "system-run-symbolic");
gtk_button_set_icon_name (btt_XOR_EXEC_EDIT, "process-stop-symbolic");
gtk_button_set_icon_name (btt_XOR_EXEC_EDIT, "power-profile-balanced-rtl-symbolic");
g_signal_connect (btt_XOR_EXEC_EDIT, "clicked", G_CALLBACK (on_toggle_EXEC_EDIT), no_local_data);
GtkWidget *any_Label = GTK_WIDGET (gtk_label_new (" | "));
GtkCheckButton *group_STATE_RULES_DATA = GTK_CHECK_BUTTON (gtk_check_button_new ());
btt_open_STATE = GTK_BUTTON (gtk_check_button_new_with_label ("state"));
g_signal_connect (btt_open_STATE, "toggled", G_CALLBACK (on_toggle_STATE_RULES_DATA), no_local_data);
gtk_check_button_set_group (GTK_CHECK_BUTTON (btt_open_STATE), group_STATE_RULES_DATA);
btt_open_RULES = GTK_BUTTON (gtk_check_button_new_with_label ("rules"));
g_signal_connect (btt_open_RULES, "toggled", G_CALLBACK (on_toggle_STATE_RULES_DATA), no_local_data);
gtk_check_button_set_group (GTK_CHECK_BUTTON (btt_open_RULES), group_STATE_RULES_DATA);
btt_open_DATA = GTK_BUTTON (gtk_check_button_new_with_label ("data analysis"));
g_signal_connect (btt_open_DATA, "toggled", G_CALLBACK (on_toggle_STATE_RULES_DATA), no_local_data);
gtk_check_button_set_group (GTK_CHECK_BUTTON (btt_open_DATA), group_STATE_RULES_DATA);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_XOR_EXEC_EDIT));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (any_Label));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_open_STATE));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_open_RULES));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header_bar), GTK_WIDGET (btt_open_DATA));
icons_for_fun (GTK_HEADER_BAR (header_bar)); // https://iconduck.com/sets/adwaita-icon-theme
// https://iconduck.com/sets/carbon-icons < pas mal ...
// https://thenounproject.com/icon/train-134324/
// ma préférée : Transport Steam Engine Icon mais : [ process icon ] semble un bon choix...
}
void main_window_design (GtkWindow *main_window){
window_header_bar (main_window,
"E coli (with permission from David S. Goodsell, 2009)");
gtk_check_button_set_active (GTK_CHECK_BUTTON (btt_open_STATE), TRUE);
gtk_window_present (GTK_WINDOW (main_window));
}
GtkWidget *get_window_child_STATE() {
if (0) printf("contain.get_window_child_STATE (line 235)\n");
GtkBox *page_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 2));
gtk_box_append (page_box, GTK_WIDGET (get_OBJECTS_and_SITUATIONS()));
gtk_box_append (page_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (page_box, GTK_WIDGET (get_SPACE_VIEW_box()));
gtk_box_append (page_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
if (get_EXEC_EDIT ()) gtk_box_append (page_box, GTK_WIDGET (get_SPACE_EDIT_controls_box()));
else gtk_box_append (page_box, GTK_WIDGET (get_TIME_EXEC_controls_box()));
return GTK_WIDGET (page_box);
}
GtkWidget *get_window_child_RULES(){
if (0) printf("contain.get_window_child_RULES (line 246)\n");
GtkPaned *H_tree_vs_selected = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_HORIZONTAL));
// GtkWidget *arbre_des_règles = gtk_frame_new ("Arbre des règles");
// GtkWidget *édition_de_la_règle_sélectionnée_n_1 = gtk_frame_new ("Inspection");
gtk_paned_set_start_child (H_tree_vs_selected, GTK_WIDGET (get_rules_tree_hpaned_new()));
gtk_paned_set_end_child (H_tree_vs_selected, GTK_WIDGET (get_selected_rules_vpaned_new()));
gtk_paned_set_position (H_tree_vs_selected, 400); // WARNING : c'est une position "absolue"
gtk_paned_set_wide_handle (H_tree_vs_selected, TRUE);
return GTK_WIDGET (H_tree_vs_selected);
}
GtkWidget *get_window_child_DATA (){
if (0) printf("contain.get_window_child_DATA (line 259)\n");
GtkBox *data_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 32));
GtkWidget* frame_rule_effect = gtk_frame_new ("rule effect\n-----------");
gtk_frame_set_label_align (GTK_FRAME (frame_rule_effect), 0.5);
GtkBox *rule_effect_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_rule_effect), GTK_WIDGET (rule_effect_box));
GtkWidget* frame_rule_topic = gtk_frame_new ("rule topic\n----------");
gtk_frame_set_label_align (GTK_FRAME (frame_rule_topic), 0.5);
GtkBox *rule_topic_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_rule_topic), GTK_WIDGET (rule_topic_box));
GtkWidget* frame_data_type = gtk_frame_new ("data type\n----------");
gtk_frame_set_label_align (GTK_FRAME (frame_data_type), 0.5);
GtkBox *data_type_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_data_type), GTK_WIDGET (data_type_box));
GtkWidget* frame_interpretations = gtk_frame_new ("interpretation\n---------------");
gtk_frame_set_label_align (GTK_FRAME (frame_interpretations), 0.5);
GtkBox *interpretations_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_interpretations), GTK_WIDGET (interpretations_box));
GtkWidget* frame_discussions = gtk_frame_new ("discussion\n------------");
gtk_frame_set_label_align (GTK_FRAME (frame_discussions), 0.5);
GtkBox *discussions_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_discussions), GTK_WIDGET (discussions_box));
GtkWidget* frame_separator = gtk_frame_new ("\n");
GtkWidget* frame_game = gtk_frame_new ("game\n------");
gtk_frame_set_label_align (GTK_FRAME (frame_game), 0.5);
GtkBox *game_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_game), GTK_WIDGET (game_box));
GtkWidget* frame_help = gtk_frame_new ("help\n-----");
gtk_frame_set_label_align (GTK_FRAME (frame_help), 0.5);
GtkBox *help_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 8));
gtk_frame_set_child (GTK_FRAME (frame_help), GTK_WIDGET (help_box));
gtk_box_append (data_box, GTK_WIDGET (frame_rule_effect));
gtk_box_append (data_box, GTK_WIDGET (frame_rule_topic));
gtk_box_append (data_box, GTK_WIDGET (frame_data_type));
gtk_box_append (data_box, GTK_WIDGET (frame_interpretations));
gtk_box_append (data_box, GTK_WIDGET (frame_discussions));
gtk_box_append (data_box, GTK_WIDGET (frame_separator));
gtk_box_append (data_box, GTK_WIDGET (frame_game));
gtk_box_append (data_box, GTK_WIDGET (frame_help));
gtk_box_append (rule_effect_box, gtk_button_new_with_label ("movement"));
gtk_box_append (rule_effect_box, gtk_button_new_with_label ("transport"));
gtk_box_append (rule_effect_box, gtk_button_new_with_label ("transformation"));
gtk_box_append (rule_topic_box, gtk_button_new_with_label ("objects"));
gtk_box_append (rule_topic_box, gtk_button_new_with_label ("situations"));
gtk_box_append (rule_topic_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (rule_topic_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (rule_topic_box, gtk_button_new_with_label ("accuracy"));
gtk_box_append (rule_topic_box, gtk_button_new_with_label ("pattern recognition"));
gtk_box_append (data_type_box, gtk_button_new_with_label ("repartitions"));
gtk_box_append (data_type_box, gtk_button_new_with_label ("evolutions"));
gtk_box_append (data_type_box, gtk_button_new_with_label ("correlations"));
gtk_box_append (interpretations_box, gtk_button_new_with_label ("stochastic"));
gtk_box_append (interpretations_box, gtk_button_new_with_label ("deterministic"));
gtk_box_append (interpretations_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (interpretations_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (interpretations_box, gtk_button_new_with_label ("physical"));
gtk_box_append (interpretations_box, gtk_button_new_with_label ("chemical"));
gtk_box_append (interpretations_box, gtk_button_new_with_label ("biological"));
gtk_box_append (interpretations_box, gtk_button_new_with_label ("social"));
gtk_box_append (interpretations_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (discussions_box, gtk_button_new_with_label ("context"));
gtk_box_append (discussions_box, gtk_button_new_with_label ("methodology"));
gtk_box_append (discussions_box, gtk_button_new_with_label ("comparisons"));
gtk_box_append (discussions_box, gtk_button_new_with_label ("to improve"));
gtk_box_append (discussions_box, gtk_button_new_with_label ("summary"));
gtk_box_append (game_box, gtk_button_new_with_label ("single player"));
gtk_box_append (game_box, gtk_button_new_with_label ("multiple players"));
gtk_box_append (game_box, gtk_button_new_with_label ("edition facilities"));
gtk_box_append (help_box, gtk_button_new_with_label ("modelization"));
gtk_box_append (help_box, gtk_button_new_with_label ("measurements"));
gtk_box_append (help_box, gtk_button_new_with_label ("results"));
gtk_box_append (help_box, gtk_button_new_with_label ("data analysis"));
gtk_box_append (help_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (help_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (help_box, gtk_button_new_with_label ("preferences"));
//SWITCH_TO (DATA);
return GTK_WIDGET (data_box);
}
static void icons_for_fun (GtkHeaderBar *header_bar)
{
GtkButton *go_home = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (go_home, "go-home-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (go_home));
GtkButton *user_trash = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (user_trash, "user-trash-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (user_trash));
GtkButton *help_biblio = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (help_biblio, "accessories-dictionary-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (help_biblio));
GtkButton *help_doc = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (help_doc, "emblem-documents-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (help_doc));
GtkButton *help_about = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (help_about, "help-about-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (help_about));
GtkButton *help_faq = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (help_faq, "help-faq-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (help_faq));
GtkButton *terminal = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (terminal, "utilities-terminal-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (terminal));
GtkButton *search = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (search, "folder-saved-search-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (search));
GtkButton *preferences_desktop_appearance = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (preferences_desktop_appearance, "preferences-desktop-appearance-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (preferences_desktop_appearance));
GtkButton *preferences_system = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (preferences_system, "preferences-system-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (preferences_system));
GtkButton *document_properties = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (document_properties, "document-properties-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (document_properties));
GtkButton *text_edit = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (text_edit, "text-editor-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (text_edit));
GtkButton *applications_utilities = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (applications_utilities, "applications-utilities-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (applications_utilities));
GtkButton *open_menu = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (open_menu, "open-menu-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (open_menu));
GtkButton *power_max = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (power_max, "power-profile-performance-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (power_max));
GtkButton *power_middle = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (power_middle, "power-profile-balanced-rtl-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (power_middle));
GtkButton *power_low = GTK_BUTTON (gtk_button_new ());
gtk_button_set_icon_name (power_low, "power-profile-power-saver-symbolic");
gtk_header_bar_pack_end (header_bar, GTK_WIDGET (power_low));
}

44
contain.h Normal file
View File

@ -0,0 +1,44 @@
//******************************************************************************/
/* */
/* E coli by David S. Goodsell (2009) */
/* --- */
/* Let this freeze frame guide us towards the model */
/* that alone can account for the phenomenon ! */
/* */
/******************************************************************************/
#include <gtk-4.0/gtk/gtk.h>
#define W 1920
#define H 960
#define W_IMAGE W - 320
#define H_IMAGE H - 126
#define H_STYLES_PANE 30
#define W_IMAGE_LOCAL W / 16
#define H_IMAGE_LOCAL H / 16
/*
G_BEGIN_DECLS
#define MY_TYPE_WINDOW (my_window_get_type())
G_DECLARE_FINAL_TYPE (MyWindow, my_window, MY, WINDOW, GtkApplicationWindow)
G_END_DECLS
G_BEGIN_DECLS
#define MY_TYPE_APPLICATION (my_application_get_type())
G_DECLARE_FINAL_TYPE (MyApplication, my_application, MY, APPLICATION, GtkApplication)
MyApplication *my_application_new (const char *application_id, GApplicationFlags flags);
G_END_DECLS
*/
void main_window_design (GtkWindow *main_window);
void set_check_button_active (GtkButton *button, int active);
void two_notebooks_in_two_panes (GtkWindow *window);
GtkFrame *get_frame_with_label();
GtkWidget *get_selected_rules_vpaned_new();
GtkWidget *get_TIME_EXEC_controls_box();
GtkWidget *get_SPACE_EDIT_controls_box();
GtkButton *get_GtkButton (char *btt_name);
GtkWidget *get_window_child_STATE();
GtkWidget *get_window_child_RULES();
GtkWidget *get_window_child_DATA();

37
dialog.c Normal file
View File

@ -0,0 +1,37 @@
#include "callback.h"
void dialog_window_design (GtkWindow *main_window, GtkWindow *dialog_window){
char *title = " Save the current model before modifying it? ";
GtkWidget *header_bar = GTK_WIDGET (gtk_header_bar_new ());
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header_bar), gtk_label_new (title));
gtk_window_set_titlebar (dialog_window, header_bar);
GtkWidget *dialog_window_grid = gtk_grid_new ();
const char *txt = " SAVE CURRENT MODEL ";
GtkButton *action_save_current_model = GTK_BUTTON (gtk_button_new_with_label (txt));
gtk_widget_set_sensitive (GTK_WIDGET (action_save_current_model), FALSE);
g_signal_connect (action_save_current_model, "clicked",
G_CALLBACK (on_WRITE_CURRENT_MODEL), dialog_window);
GtkButton *click_yes = GTK_BUTTON (gtk_button_new_with_label ("YES"));
g_signal_connect (click_yes, "clicked",
G_CALLBACK (on_SAVE_CURRENT_MODEL_BEFORE_EDITING), action_save_current_model);
GtkButton *click_no = GTK_BUTTON (gtk_button_new_with_label ("NO"));
g_signal_connect (click_no, "clicked",
G_CALLBACK (on_DISCARD_CURRENT_MODEL_AND_START_EDITING), dialog_window);
gtk_grid_attach (GTK_GRID (dialog_window_grid), GTK_WIDGET (click_yes), 0, 0, 1, 1) ;
gtk_grid_attach (GTK_GRID (dialog_window_grid), GTK_WIDGET (click_no), 1, 0, 1, 1) ;
gtk_grid_attach (GTK_GRID (dialog_window_grid), GTK_WIDGET (action_save_current_model), 0, 2, 2, 1) ;
gtk_window_set_child (GTK_WINDOW (dialog_window), GTK_WIDGET (dialog_window_grid));
gtk_window_set_transient_for (GTK_WINDOW (dialog_window), GTK_WINDOW (main_window));
gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog_window), TRUE);
gtk_window_set_deletable (GTK_WINDOW (dialog_window), FALSE); // FALSE
gtk_window_set_modal (GTK_WINDOW (dialog_window), TRUE);
// gtk_window_present (GTK_WINDOW (dialog_window)); see button...
}

2
dialog.h Normal file
View File

@ -0,0 +1,2 @@
void dialog_window_design (GtkWindow *main_window, GtkWindow *dialog_window);

118
dimers random walk.xml Normal file
View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<gem-graph-model version="0.2.1">
<identity>
<name>Modèle de test</name>
<owner>Léontine Patinette</owner>
<owner_id>2</owner_id>
<date>1630000000</date>
<version>1.0</version>
<g_ref id="Cause" date="1630000000" author="toujours" lang="en">Ref</g_ref>
</identity>
<parameters id="texte" date="0" author="Léontine Trottine.">
<simulation>
<max_thread>0</max_thread>
<max_cycles>9</max_cycles>
</simulation>
<space-param>
<!-- loop_on_zero="true" anything moved before zero reenters at the end of space-->
<!-- loop_on_zero="false" anything moved before zero is lost-->
<!-- loop_on_max="true" anything moved beyond max reenters at the zero of space-->
<!-- loop_on_max="false" anything moved beyond max is lost-->
<dimension x="29"/>
<!-- Site_multiplicity = number of sites in a space unit. -->
<!-- Each site points towards a neighbouring space unit. -->
<!-- Several arrows can be stacked in the same site. -->
<site_multiplicity>3</site_multiplicity>
</space-param>
</parameters>
<!-- Model objects definition -->
<objects id="only dimers in this model" date="1630000000" author="inanimés,... âme ?">
<object id="a dimer" date="1630000000" author="Alphonse">
<arrow site="1" weight="1" x="0"/>
<arrow site="2" weight="1" x="1"/>
</object>
</objects>
<!-- Saved space description (initial space is sequence 0) -->
<savedstates id="texte" date="1630000000" author="Qui courrait dans l'herbe'">
<state id="initial" date="1630000000" author="Une souris verte">
<arrow site="0" weight="1" x="0"/>
<arrow site="1" weight="1" x="1"/>
<arrow site="0" weight="1" x="10"/>
<arrow site="1" weight="1" x="11"/>
<arrow site="0" weight="1" x="20"/>
<arrow site="1" weight="1" x="21"/>
<!-- Three dimers 1-1 are drawn in the global space
at locations (0,1) (10,11) and (20,21) -->
</state>
</savedstates>
<!-- Model transitions definition (rules) -->
<!-- In this version : <xs:sequence minOccurs="0" maxOccurs="unbounded">-->
<!-- Transitions should be edited by hand and written in a 'human-readable' format -->
<conditions id="random walk of dimers" date="1630000000" author="Zazard le lézard !">
<condition site="1" weight="1" node_id="1" parent="0" x="0"/>
<condition site="2" weight="1" node_id="2" parent="1" x="1"/>
<!-- as soon as conditions 1 and 2 are satisfied, a dimer is identified at atation (0,1). -->
<condition site="1" weight="0" node_id="3" parent="2" x="2"/>
<!-- as soon as condition 3 is satisfied,
the neighbouring space unit to East of the dimer is empty
and the dimer identified by conditions (1,2) can be moved to East. -->
<condition site="2" weight="0" node_id="4" parent="2" x="-1"/>
<!-- as soon as condition 4 is satisfied,
the neighbouring space unit to West of the dimer is empty
and the dimer identified by conditions (1,2) can be moved to West. -->
</conditions>
<transitions>
<transition id="move_a_dimer_to_east" date="1630000000" author="Pas moi..."
parent="3" probability="1">
<arrow site="1" weight="0" x="0"/>
<arrow site="2" weight="0" x="1"/>
<arrow site="1" weight="1" x="1"/>
<arrow site="2" weight="1" x="2"/>
</transition>
<transition id="move_a_dimer_to_west" date="1630000000" author="Ni moi !"
parent="4" probability="1">
<arrow site="1" weight="0" x="0"/>
<arrow site="2" weight="0" x="1"/>
<arrow site="2" weight="1" x="0"/>
<arrow site="1" weight="1" x="1"/>
</transition>
</transitions>
</gem-graph-model>

280
display.c Normal file
View File

@ -0,0 +1,280 @@
#include <stdio.h>
#include <gtk-4.0/gtk/gtk.h>
#include "contain.h"
#include "tree.h"
#include "texts.h"
//------------------------------------------------------------------------------
GtkWidget *get_image_ALL_SPACE(){
GtkWidget *image;
// forget > GTK_WIDGET(get_scrolled_gl_area());
// Use GtkImage if you want to display a fixed-size icon
// and GtkPicture if you want to display a (maybe) scaled picture.
image = gtk_image_new_from_file("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/aXoris.png");
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/gg sketch.png");
image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/E coli (Goodsell) 2.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE, H_IMAGE);
return image;
}
GtkWidget *get_image_GLUTAMATE(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/glutamate.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_GLUTAMINE(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/glutamine.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_HISTIDINE(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/histidine.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_HISTAMINE(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/histamine.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_PHENYLALANINE(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/phénylalanine.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_DOPAMINE(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/dopamine.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_ATP(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/ATP.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_image_AMP(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/AMP.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
GtkWidget *get_user_tree(){
GtkWidget *image = gtk_picture_new_for_filename ("/home/jean/01/Gtk4/Getting_Started_with_GTK/image/arbre utilisateur.png");
gtk_widget_set_size_request (GTK_WIDGET (image), W_IMAGE_LOCAL, H_IMAGE_LOCAL);
return image;
}
//------------------------------------------------------------------------------
// TODO cliquer sur "RUN" --> affiche "STOP" (et inversement)
static GtkWidget *get_scroll_speed(){
GtkAdjustment *speed_adjust = gtk_adjustment_new (100, 0, 100, 1, 0, 0);
GtkWidget *scroll_speed = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, speed_adjust);
gtk_widget_set_size_request (GTK_WIDGET (scroll_speed), 120, 2);
return scroll_speed;
}
static GtkBox *get_UNDO_SPEED_box(){
GtkBox *SPEED_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
gtk_box_append (SPEED_box, GTK_WIDGET(gtk_label_new ("< UNDO <\n")));
gtk_box_append (SPEED_box, get_scroll_speed());
return SPEED_box;
}
static GtkBox *get_DO_SPEED_box(){
GtkBox *SPEED_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
gtk_box_append (SPEED_box, GTK_WIDGET(gtk_label_new ("> DO >\n")));
gtk_box_append (SPEED_box, get_scroll_speed());
return SPEED_box;
}
GtkBox *get_RUN_STOP_box(){
GtkBox *RUN_STOP_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20));
gtk_box_append (RUN_STOP_box, GTK_WIDGET (get_UNDO_SPEED_box()));
gtk_box_append (RUN_STOP_box, GTK_WIDGET(gtk_label_new (" STEP\n(show active rule) ")));
gtk_box_append (RUN_STOP_box, GTK_WIDGET (get_DO_SPEED_box()));
gtk_box_append (RUN_STOP_box, GTK_WIDGET(gtk_label_new (" R U N\n S T O P")));
return RUN_STOP_box;
}
//------------------------------------------------------------------------------
GtkBox *get_ZOOM_box(){
GtkBox *ZOOM_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
GtkWidget *ZOOM_Label = GTK_WIDGET (gtk_label_new (\
"\n TOOLS\n ---\n zoom\n ---\n space\n struct.\n\
---\n arrows\n struct.\n ---\n orient\n state\n in space\n"));
gtk_widget_set_size_request (GTK_WIDGET (ZOOM_box), 10, 80);
gtk_box_append (ZOOM_box, ZOOM_Label);
return ZOOM_box;
}
//------------------------------------------------------------------------------
GtkBox *get_edit_TOOL_box(){
GtkBox *TOOL_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
GtkWidget *ZOOM_Label = GTK_WIDGET (gtk_label_new ("TOOLS\n ---\n(space\nstruct.)"));
gtk_widget_set_size_request (GTK_WIDGET (TOOL_box), 10, 120);
gtk_box_append (TOOL_box, ZOOM_Label);
return TOOL_box;
}
//------------------------------------------------------------------------------
GtkBox *get_XYZ_box(){
GtkBox *XYZ_labels_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 2)); // spacing = 2
GtkBox *XYZ_scrollbar_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2)); // spacing = 2q
// GtkWidget *scale_X = gtk_scale_button_new (0, 360, 10, NULL); < à étudier
// (double min, double max, double step, const char** icons)
GtkAdjustment *X_adjust = gtk_adjustment_new (0, 0, 380, 1, 0, 0);
GtkAdjustment *Y_adjust = gtk_adjustment_new (0, 0, 380, 1, 0, 0);
GtkAdjustment *Z_adjust = gtk_adjustment_new (0, 0, 380, 1, 0, 0);
GtkWidget *scroll_X = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, X_adjust);
GtkWidget *scroll_Y = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, Y_adjust);
GtkWidget *scroll_Z = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, Z_adjust);
gtk_widget_set_size_request (GTK_WIDGET (scroll_X), 1, 500);
gtk_box_append (XYZ_scrollbar_box, GTK_WIDGET (gtk_label_new (" "))); // AD HOC (pour "centrer")
gtk_box_append (XYZ_scrollbar_box, scroll_X);
gtk_box_append (XYZ_scrollbar_box, scroll_Y);
gtk_box_append (XYZ_scrollbar_box, scroll_Z);
gtk_box_append (XYZ_labels_box, GTK_WIDGET (gtk_label_new ("\nX Y Z")));
gtk_box_append (XYZ_labels_box, GTK_WIDGET (XYZ_scrollbar_box));
gtk_box_append (XYZ_labels_box, GTK_WIDGET (gtk_label_new ("")));
return XYZ_labels_box;
}
//------------------------------------------------------------------------------
GtkProgressBar *get_ELAPSED_TIME_ProgressBar(){ // To rename : DO - UNDO - REDO ?
GtkProgressBar *buffer = GTK_PROGRESS_BAR (gtk_progress_bar_new ());
gtk_progress_bar_set_text (buffer,\
"\n<--- [buffer] (simulation extensive time) --->\n\
supports DO - UNDO - REDO functions\n");
gtk_progress_bar_set_show_text (buffer, TRUE);
gtk_widget_set_size_request (GTK_WIDGET (buffer), W - 560, 0);
return buffer;
}
//------------------------------------------------------------------------------
// Chaque label "objet" ou "situation" sera remplacé par un curseur "transparence" (vertical)
static GtkBox *get_objects_box(){
GtkBox *objects_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
GtkAdjustment *adjust = gtk_adjustment_new (0, 0, 255, 1, 0, 0);
if (0) for (int i = 0; i < 10; i++)
gtk_box_append (objects_box, gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjust));
char string[7];
for (int i = 0; i < 16; i++){
sprintf(string, "[%d] ", i);
if (0) printf("%s\n", string); // répété deux fois ! pourquoi ?
gtk_box_append (objects_box, GTK_WIDGET (gtk_label_new (string)));
}
gtk_box_append (objects_box, GTK_WIDGET (gtk_label_new (" membrane ")));
gtk_box_append (objects_box, GTK_WIDGET (gtk_label_new (" co-enzyme A ")));
gtk_box_append (objects_box, GTK_WIDGET (gtk_label_new (" ribosome ")));
gtk_box_append (objects_box, GTK_WIDGET (gtk_label_new (" ATP synthase ")));
return objects_box;
}
static GtkBox *get_situations_box(){
GtkBox *situations_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0));
char string[7];
for (int i = 0; i < 64; i++){
sprintf(string, "[%d] ", i);
if (0) printf("%s\n", string); // répété deux fois ! pourquoi ?
gtk_box_append (situations_box, GTK_WIDGET (gtk_label_new (string)));
}
gtk_box_append (situations_box, GTK_WIDGET (gtk_label_new (" transcription ")));
gtk_box_append (situations_box, GTK_WIDGET (gtk_label_new (" transport Na/K ")));
gtk_box_append (situations_box, GTK_WIDGET (gtk_label_new (" ubiquitination ")));
gtk_box_append (situations_box, GTK_WIDGET (gtk_label_new (" rotation moteur flagellaire ")));
return situations_box;
}
static GtkWidget *get_frame_objects(){
GtkWidget *scroll = gtk_scrolled_window_new ();
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
GtkWidget *frame_objects = gtk_frame_new (" Objects"); // defines each class of object transparence
gtk_widget_set_size_request (frame_objects, 0, H_STYLES_PANE); // < utile seulement pour la largeur min/max
gtk_frame_set_child (GTK_FRAME (frame_objects), GTK_WIDGET (get_objects_box()));
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroll), frame_objects);
return scroll;
}
static GtkWidget *get_frame_situations(){
GtkWidget *scroll = gtk_scrolled_window_new ();
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
GtkWidget *frame_situations = gtk_frame_new (" Situations"); // facilitates each situation identification
gtk_widget_set_size_request (GTK_WIDGET (frame_situations), 0, H_STYLES_PANE); // < utile seulement pour la largeur min/max
gtk_frame_set_child (GTK_FRAME (frame_situations), GTK_WIDGET (get_situations_box()));
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroll), frame_situations);
return scroll;
}
GtkWidget *get_OBJECTS_and_SITUATIONS(){
GtkWidget *objects_and_situations_horizontal_pane = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
gtk_paned_set_start_child (GTK_PANED(objects_and_situations_horizontal_pane), GTK_WIDGET (get_frame_objects()));
gtk_paned_set_end_child (GTK_PANED(objects_and_situations_horizontal_pane), GTK_WIDGET (get_frame_situations()));
return objects_and_situations_horizontal_pane;
}
GtkBox *get_rules_comparator_new(){
GtkBox *comparator = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 2));
gtk_box_append (comparator, GTK_WIDGET (get_image_ATP()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (comparator, GTK_WIDGET (get_image_AMP()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (comparator, GTK_WIDGET (get_image_GLUTAMATE()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (comparator, GTK_WIDGET (get_image_GLUTAMINE()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (comparator, GTK_WIDGET (get_image_HISTIDINE()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (comparator, GTK_WIDGET (get_image_PHENYLALANINE()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
gtk_box_append (comparator, GTK_WIDGET (get_image_DOPAMINE()));
gtk_box_append (comparator, GTK_WIDGET(gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)));
return comparator;
}
GtkWidget *get_rules_tree_hpaned_new(){
GtkPaned *H_tree_vs_comparison = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_HORIZONTAL));
// GtkWidget *arbre_des_règles = gtk_frame_new ("Arbre");
// GtkWidget *comparaison_des_règles_sélectionnées = gtk_frame_new ("Sélection");
gtk_paned_set_start_child (H_tree_vs_comparison, GTK_WIDGET (get_user_rules_tree()));
gtk_paned_set_end_child (H_tree_vs_comparison, GTK_WIDGET (get_rules_comparator_new()));
gtk_paned_set_position (H_tree_vs_comparison, 300);
gtk_paned_set_wide_handle (H_tree_vs_comparison, TRUE);
gtk_paned_set_shrink_start_child (H_tree_vs_comparison, FALSE);
gtk_paned_set_shrink_end_child (H_tree_vs_comparison, FALSE);
return GTK_WIDGET (H_tree_vs_comparison);
}
GtkWidget *get_rules_page_new(){
GtkPaned *H_tree_vs_selected = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_HORIZONTAL));
// GtkWidget *arbre_des_règles = gtk_frame_new ("Arbre des règles");
// GtkWidget *édition_de_la_règle_sélectionnée_n_1 = gtk_frame_new ("Inspection");
gtk_paned_set_start_child (H_tree_vs_selected, GTK_WIDGET (get_rules_tree_hpaned_new()));
gtk_paned_set_end_child (H_tree_vs_selected, GTK_WIDGET (get_selected_rules_vpaned_new()));
gtk_paned_set_position (H_tree_vs_selected, 600); // WARNING : c'est une position "absolue"
gtk_paned_set_wide_handle (H_tree_vs_selected, TRUE);
// gtk_widget_set_size_request (GTK_WIDGET (H_tree_vs_selected), W, H); // inutile... ?
return GTK_WIDGET (H_tree_vs_selected);
}

38
display.h Normal file
View File

@ -0,0 +1,38 @@
/******************************************************************************/
/* */
/* E coli by David S. Goodsell (2009) */
/* --- */
/* Let this freeze frame guide us towards the model */
/* that alone can account for the phenomenon ! */
/* */
/******************************************************************************/
GtkWidget *get_text_view();
GtkFrame *get_frame_with_label();
GtkWidget *get_rules_page_new();
GtkBox *get_rules_user_tree_new();
GtkWidget *get_image_ALL_SPACE();
GtkWidget *get_image_GLUTAMATE();
GtkWidget *get_image_GLUTAMINE();
GtkWidget *get_image_HISTIDINE();
GtkWidget *get_image_HISTAMINE();
GtkWidget *get_image_PHENYLALANINE();
GtkWidget *get_image_DOPAMINE();
GtkWidget *get_image_ATP();
GtkWidget *get_image_AMP();
GtkWidget *get_rules_tree_hpaned_new();
GtkProgressBar *get_ELAPSED_TIME_ProgressBar();
GtkBox *get_RUN_STOP_box();
GtkBox *get_ZOOM_box();
GtkBox *get_edit_TOOL_box();
GtkBox *get_XYZ_box();
GtkWidget *get_OBJECTS_and_SITUATIONS();
GtkBox *get_ELAPSED_TIME_box();
GtkButton *get_btt_run_xor_edit();
void window_bar(GtkWindow *window, char *title);

207
draw.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Writes values to describe a vertex at (x,y,z) intoq the vertex buffer
*
* @param coords GLfloat(x,y,z)
*
* @return void
*/
#include <stdlib.h>
#include <time.h>
#include <cglm/cglm.h>
#include "base.h"
//#include "ui.h"
#include "graph_area.h"
void graphics_draw_vertex (const int stack_id,
GLfloat x,
GLfloat y,
GLfloat z)
{
//g_printerr("stack_id is %d\n", stack_id);
//g_printerr("stack_id is %d\n", stack_id);
//g_printerr("graphic_stack is at %p\n", graphic_stack);
//g_printerr("graphic_stack[stack_id] is at %p\n", graphic_stack + stack_id);
volatile struct graphic_stack_t *stack = &graphic_stack[stack_id];
//g_printerr("Currently stack->buffer_vertex_origin @ %p\n", stack->buffer_vertex_origin);
//assert (stack->buffer_vertex_origin);
stack->buffer_vertex_origin =
g_realloc (stack->buffer_vertex_origin,
(stack->buffer_vertex_size + 3) * sizeof(GLfloat));
//print_stack(stack_id);
stack->buffer_vertex_origin[stack->buffer_vertex_size + 0] = x;
stack->buffer_vertex_origin[stack->buffer_vertex_size + 1] = y;
stack->buffer_vertex_origin[stack->buffer_vertex_size + 2] = z;
stack->buffer_vertex_size += 3;
}
/*
* Writes values to describe a color (r,g,b) into the color buffer
*
* @param color GLfloat(r,g,b)
*
* @return void
*/
void graphics_draw_color (const int stack_id,
GLfloat r,
GLfloat g,
GLfloat b)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
stack->buffer_colors_origin = g_realloc (stack->buffer_colors_origin,
(stack->buffer_colors_size + 3) * sizeof(GLfloat));
assert (stack->buffer_colors_origin);
stack->buffer_colors_origin[stack->buffer_colors_size + 0] = r;
stack->buffer_colors_origin[stack->buffer_colors_size + 1] = g;
stack->buffer_colors_origin[stack->buffer_colors_size + 2] = b;
stack->buffer_colors_size += 3;
}
/*
* Writes values to describe a line from a to b into the line buffer
*
* @param coords GLuint (a,b)
*
* @return void
*/
void graphics_draw_line (const int stack_id,
GLuint a,
GLuint b)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
stack->buffer_lines_origin = g_realloc (stack->buffer_lines_origin,
(stack->buffer_lines_size + 2) * sizeof(GLuint));
assert (stack->buffer_lines_origin);
stack->buffer_lines_origin[stack->buffer_lines_size + 0] = a;
stack->buffer_lines_origin[stack->buffer_lines_size + 1] = b;
stack->buffer_lines_size += 2;
}
/*
* Writes values to describe an (a,b,c) plan (triangle) into the plan buffer
*
* @param coords GLuint (a,b,c)
*
* @return void
*/
void graphics_draw_plan (const int stack_id,
GLuint a,
GLuint b,
GLuint c)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
stack->buffer_plans_origin = g_realloc (stack->buffer_plans_origin,
(stack->buffer_plans_size + 3) * sizeof(GLuint));
assert (stack->buffer_plans_origin);
stack->buffer_plans_origin[stack->buffer_plans_size + 0] = a;
stack->buffer_plans_origin[stack->buffer_plans_size + 1] = b;
stack->buffer_plans_origin[stack->buffer_plans_size + 2] = c;
stack->buffer_plans_size += 3;
}
/*
* Draws the current buffer to a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return void
*/
void graphics_draw(const int stack_id)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
g_printerr("[debug] graphics_draw() started\n");
print_stack(stack_id);
GLint cur_viewport[4];
glGetIntegerv(GL_VIEWPORT, cur_viewport);
mat4 m = GLM_MAT4_IDENTITY_INIT;
glm_rotate_x(m, glm_rad(stack->rotation_angles[X_AXIS]), m);
glm_rotate_y(m, glm_rad(stack->rotation_angles[Y_AXIS]), m);
glm_rotate_z(m, glm_rad(stack->rotation_angles[Z_AXIS]), m);
mat4 v = GLM_MAT4_IDENTITY_INIT; // XXX define zoom and translations here ?
mat4 p = GLM_MAT4_IDENTITY_INIT;
glm_ortho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, +1.0f, p);
glm_ortho_default((float)cur_viewport[2] / (float)cur_viewport[3], p);
glm_perspective_default((float)cur_viewport[2] / (float)cur_viewport[3], p);
/* Use our shaders */
glUseProgram(stack->program);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Update the "mvp" matrix we use in the shader */
glUniformMatrix4fv(stack->m, 1, GL_FALSE, (float *)m);
glUniformMatrix4fv(stack->v, 1, GL_FALSE, (float *)v);
glUniformMatrix4fv(stack->p, 1, GL_FALSE, (float *)p);
/* Use the vertices in our buffer */
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, stack->position_buffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,(void*)0);
// couleurs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, stack->color_buffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0,(void*)0);
glEnable(GL_DEPTH_TEST);
glDrawElements(GL_LINES, stack->buffer_lines_size, GL_UNSIGNED_INT, stack->buffer_lines_origin);
glDrawElements(GL_TRIANGLES, stack->buffer_plans_size, GL_UNSIGNED_INT, stack->buffer_plans_origin);
/* We finished using the buffers and program */
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
glFlush();
g_printerr("[debug] graphics_draw() ended\n");
}

332
graph_area.c Normal file
View File

@ -0,0 +1,332 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: User interface functions
*
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <gtk-4.0/gtk/gtk.h>
#include <glib-2.0/glib.h>
#include "contain.h"
#include "graph_area.h"
#include "callback.h"
struct stack_index_t {
long stack_id;
void *container_widget;
void *gl_area;
};
static struct stack_index_t *stack_index = NULL;
size_t stack_index_size = 0;
int set_arrow (int stack_id, // 2024-06-27 DEBUG !
int arrows_nb,
int space_X,
int space_Y,
int space_Z,
int requested_weight,
int site,
int arrow_x,
int arrow_y,
int arrow_z) {
printf("graph_area.c > int set_arrow (...) 2024-06-27 DEBUG\n");
return 0;
} // 2024-06-27 DEBUG !
/*
* Look for stack entry and returns stack_id
*
* @params container_widget, generally the GtkBox that contains the GLArea
*
* @returns stack_id
*/
long ui_get_graphic_stack(void *container_widget)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
if (stack_index[i].container_widget == (void *)container_widget) {
return stack_index[i].stack_id;
}
}
return -1;
}
/*
* Look for stack entry and returns stack_id
*
* @params container_widget, generally the GtkBox that contains the GLArea
*
* @returns stack_id
*/
long ui_is_graphic_stack_ready(void *container_widget)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
if (stack_index[i].container_widget == (void *)container_widget) {
return stack_index[i].stack_id;
}
}
return -1;
}
/*
* Look for stack entry and initializes OpenGL for it
*
* @params container_widget, generally the GtkBox that contains the GLArea
*
* @returns bool, true if success
*/
bool ui_init_graphic_stack(void *container_widget, GError *error_buffer)
{
g_printerr("[debug] ui_init_graphic_stack()\n");
g_printerr("[debug] ui_init_graphic_stack() : target is %p\n", container_widget);
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
g_printerr("[debug] ui_init_graphic_stack() : i is %d\n", i);
g_printerr("[debug] ui_init_graphic_stack() : target would be %p\n",
stack_index[i].container_widget);
if (stack_index[i].container_widget == (void *)container_widget) {
stack_index[i].stack_id = graphics_init(&error_buffer);
g_printerr("[debug] ui_init_graphic_stack() : stack_id is %ld\n",
stack_index[i].stack_id);
if (stack_index[i].stack_id >= 0)
return true;
else
return false;
}
}
return false;
}
/*
* Look for stack entry and shutdowns OpenGL for it
*
* @params container_widget, generally the GtkBox that contains the GLArea
*
* @returns bool, true if success
*/
bool ui_shutdown_graphic_stack(void *container_widget, GError *error_buffer)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
if (stack_index[i].container_widget == (void *)container_widget) {
if (graphics_shutdown(stack_index[i].stack_id,
&error_buffer) == false) {
return false;
}
stack_index[i].stack_id = 0;
return true;
}
}
return false;
}
void ui_clean_stack_index(void)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
stack_index[i].stack_id = 0;
}
return;
}
/*
* Look for stack entry and triggers OpenGL for drawing
*
* @params container_widget, generally the GtkBox that contains the GLArea
*
* @returns bool, true if success
*/
bool ui_render_stack(GtkWidget *container_widget)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
if (stack_index[i].container_widget == (void *)container_widget) {
graphics_draw (stack_index[i].stack_id);
return true;
}
}
return false;
}
//void graphics_draw(const int stack_id) {printf("graph_area.c > void graphics_draw(const int stack_id) (161)\n");}
/*
* Look for stack entry and triggers OpenGL for drawing
*
* @params container_widget, generally the GtkBox that contains the GLArea
*
* @returns bool, true if success
*/
bool ui_update_axis_stack(GtkWidget *container_widget, int axis, int value)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
if (stack_index[i].container_widget == (void *)container_widget) {
graphic_stack[stack_index[i].stack_id].rotation_angles[axis] = value;
gtk_widget_queue_draw((GtkWidget*)(stack_index[i].gl_area));
return true;
}
}
return false;
}
/*
* Look for every stack entry and shutdowns OpenGL for it
*
* @params void
*
* @returns bool, true if success
*/
void ui_shutdown_all_graphic_stacks(void)
{
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
graphics_shutdown(stack_index[i].stack_id, NULL);
}
return;
}
/*
* Creates a slider widget
*
* @params axis, meaning which axis we're building (for label)
*
* @returns GtkWidget*, pointer to the new widget
*/
GtkWidget *create_axis_slider(int axis)
{
GtkWidget *box, *label, *slider;
GtkAdjustment *adj;
const char *text;
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
switch (axis) {
case X_AXIS:
text = "X";
break;
case Y_AXIS:
text = "Y";
break;
case Z_AXIS:
text = "Z";
break;
default:
g_assert_not_reached();
}
label = gtk_label_new(text);
gtk_box_append(GTK_BOX(box), label);
gtk_widget_set_visible (label, TRUE);
adj = gtk_adjustment_new(0.0, 0.0, 360.0, 1.0, 12.0, 0.0);
g_signal_connect (adj, "value-changed", G_CALLBACK(on_axis_value_change), (gpointer) label);
slider = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, adj);
gtk_box_append(GTK_BOX(box), slider);
gtk_widget_set_hexpand(slider, TRUE);
gtk_widget_set_visible (slider, TRUE);
gtk_widget_set_visible (box, TRUE);
return box;
}
/*
* Creates GLArea and indexes it
*
* @params target_mode, meaning which ui_stack we're on
* target_widget, meaning the box that will host the GLArea
*
* @returns bool, true if success
*/
bool ui_setup_glarea(int target_mode, GtkWidget *target_widget)
{
GtkWidget *gl_area;
g_printerr("[debug] ui_setup_glarea()\n");
assert(target_widget);
g_printerr("[debug] ui_setup_glarea() : target is %p\n", target_widget);
if (stack_index == NULL) {
stack_index = g_malloc(sizeof(struct stack_index_t));
stack_index_size = 1;
} else {
// look for stack_index entry
for (int i = 0; i < stack_index_size; i++) {
if (stack_index[i].container_widget == (void *)target_widget) {
return false;
}
}
// create entry
stack_index =
g_realloc(stack_index,
++stack_index_size * sizeof(struct stack_index_t));
}
gl_area = GTK_WIDGET(gtk_gl_area_new());
assert(gl_area);
gtk_widget_set_size_request(gl_area, 1000, 1000);
gtk_gl_area_set_auto_render(GTK_GL_AREA(gl_area), true);
gtk_widget_set_hexpand(gl_area, TRUE);
gtk_widget_set_vexpand(gl_area, TRUE);
gtk_widget_set_halign(gl_area, GTK_ALIGN_CENTER);
gtk_widget_set_valign(gl_area, GTK_ALIGN_CENTER);
// The main "draw" call for GtkGLArea
g_signal_connect(GTK_GL_AREA(gl_area), "render", G_CALLBACK(on_glarea_render), NULL);
g_signal_connect(gl_area, "realize", G_CALLBACK(on_glarea_realize), NULL);
g_signal_connect(gl_area, "unrealize", G_CALLBACK(on_glarea_unrealize), NULL);
stack_index[stack_index_size-1].container_widget =
(void*)target_widget;
stack_index[stack_index_size-1].gl_area = (void*)gl_area;
g_printerr("[debug] ui_setup_glarea() : set target to %p\n", target_widget);
g_printerr("[debug] ui_setup_glarea() : stack_index (@0x%p) had %ld elements\n",
stack_index,
stack_index_size);
gtk_box_append (GTK_BOX (target_widget), gl_area);
gtk_widget_set_visible (GTK_WIDGET (gl_area), TRUE);
// Create sliders
for(int i = 0; i < N_AXIS; i++)
gtk_box_append(GTK_BOX(target_widget), create_axis_slider(i));
return true;
}

328
graph_area.h Normal file
View File

@ -0,0 +1,328 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: OpenGL utils header
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <unistd.h>
#include <gtk-4.0/gtk/gtk.h>
#include <glib-2.0/glib.h>
#include <stdbool.h>
#include <epoxy/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <cglm/cglm.h>
#include "base.h"
//#include "draw.c"
// #define VERTEX_SHADER_FILE "src/graphics/shaders/shader.vert"
// #define FRAG_SHADER_FILE "src/graphics/shaders/shader.frag"
#define VERTEX_SHADER_FILE "shader.vert"
#define FRAG_SHADER_FILE "shader.frag"
#define GL_TARGET_MAJOR_VERSION 0
#define GL_TARGET_MINOR_VERSION 4
/*
* Structure describing a gl_area and its parameters, used to create a table
* of Gem-graph client current gl_areas
*/
struct graphic_stack_t {
int id;
int mode;
float rotation_angles[N_AXIS]; // Rotation angles on each axis
GLuint vao; // init_buffers
GLuint position_buffer; // shutdown, draw
GLuint color_buffer; // shutdown, draw
GLuint program; // shutdown, init_shaders, draw
GLuint m; // init_shaders, draw
GLuint v; // init_shaders, draw
GLuint p; // init_shaders, draw
struct arrow_t *arrows_ptr;
long arrows_nb;
GLfloat *buffer_vertex_origin;
GLfloat *buffer_colors_origin;
GLuint *buffer_lines_origin;
GLuint *buffer_plans_origin;
long buffer_vertex_size;
long buffer_colors_size;
long buffer_lines_size;
long buffer_plans_size;
long buffer_vertex_0_arrow;
long buffer_colors_0_arrow;
long buffer_lines_0_arrow;
long buffer_plans_0_arrow;
};
bool ui_render_stack(GtkWidget *container_widget);
bool ui_setup_glarea(int target_mode, GtkWidget *target_widget);
/*
* Dynamic array of ptrs to dynamically allocated gl_area_entry
*/
extern struct graphic_stack_t *graphic_stack;
/*
* Initializes a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if initialized
*/
int graphics_init(void *error_buffer);
/*
* Draws the current buffer to a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return void
*/
void graphics_draw(const int stack_id);
/*
* Shutdowns a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if success
*/
bool graphics_shutdown(const int stack_id, void *error_buffer);
/*
* Initializes the shaders of a gl_area and link them to a program
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if initialized
*/
bool graphics_init_shaders(const int stack_id);
bool ui_init_graphic_stack(void *container_widget, GError *error_buffer);
bool ui_shutdown_graphic_stack(void *container_widget, GError *error_buffer);
bool ui_update_axis_stack(GtkWidget *container_widget, int axis, int value);
/* Initializes the buffer of a gl_area
* Calls according to the user preferences
* @param gl_area, ptr to the gl_area widget
* @return void
*/
void graphics_init_buffers(const int stack_id);
/*
* Draws a vertex (x, y, z)
* if (console) prints (x, y, z) values to console
*
* @param GLfloat x, GLfloat y, GLfloat z
*
* @return void
*/
void graphics_draw_vertex (const int stack_id,
GLfloat x,
GLfloat y,
GLfloat z);
/*
* Draws the color (r, g, b) associated to a vertex
* if (console) prints (r, g, b) values to console
*
* @param GLfloat r, GLfloat g, GLfloat b
*
* @return void
*/
void graphics_draw_color (const int stack_id, GLfloat r, GLfloat g, GLfloat b);
/*
* Writes values to describe a line from a to b into the line buffer
*
* @param coords GLuint (a,b)
*
* @return void
*/
void graphics_draw_line (const int stack_id, GLuint a, GLuint b);
/*
* Writes values to describe an (a,b,c) plan (triangle) into the plan buffer
*
* @param coords GLuint (a,b,c)
*
* @return void
*/
void graphics_draw_plan (const int stack_id, GLuint a, GLuint b, GLuint c);
/*
* Created and compile a shader
*
* @param type, shader type
* src, source code of shader
*
* @return shader id
*/
static inline GLuint create_shader(const int stack_id, int type, const char *src)
{
GLuint shader;
int status;
shader = glCreateShader(type);
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE) {
int log_len;
char *buffer;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc(log_len + 1);
assert (buffer);
glGetShaderInfoLog(shader, log_len, NULL, buffer);
g_warning("Compile failure in %s shader:\n%s",
type == GL_VERTEX_SHADER ? "vertex" : "fragment",
buffer);
g_free(buffer);
glDeleteShader(shader);
return 0;
}
return shader;
}
static inline void print_stack(int stack_id)
{
static int n = 0;
printf("\n[n=%d]***************", n);
printf("id = %d\tmode = %d\n",
graphic_stack[stack_id].id,
graphic_stack[stack_id].mode);
printf("rotation_angles = ");
for (int i = 0; i < N_AXIS; i++) {
printf("%f\t", graphic_stack[stack_id].rotation_angles[i]); // Rotation angles on each axis
}
printf("\n");
printf("vao = %d\n", graphic_stack[stack_id].vao);
printf("position_buffer = %d\n", graphic_stack[stack_id].position_buffer);
printf("color_buffer = %d\n", graphic_stack[stack_id].color_buffer);
printf("program = %d\n", graphic_stack[stack_id].program);
printf("m = %d\n", graphic_stack[stack_id].m);
printf("v = %d\n", graphic_stack[stack_id].v);
printf("p = %d\n", graphic_stack[stack_id].p);
printf("arrows_ptr = %p\n", graphic_stack[stack_id].arrows_ptr);
printf("arrows_nb = %ld\n", graphic_stack[stack_id].arrows_nb);
printf("buffer_vertex_origin = %p\n", graphic_stack[stack_id].buffer_vertex_origin);
printf("buffer_colors_origin = %p\n", graphic_stack[stack_id].buffer_colors_origin);
printf("buffer_lines_origin = %p\n", graphic_stack[stack_id].buffer_lines_origin);
printf("buffer_plans_origin = %p\n", graphic_stack[stack_id].buffer_plans_origin);
printf("buffer_vertex_size = %ld\n", graphic_stack[stack_id].buffer_vertex_size);
printf("buffer_colors_size = %ld\n", graphic_stack[stack_id].buffer_colors_size);
printf("buffer_lines_size = %ld\n", graphic_stack[stack_id].buffer_lines_size);
printf("buffer_plans_size = %ld\n", graphic_stack[stack_id].buffer_plans_size);
printf("buffer_vertex_0_arrow = %ld\n", graphic_stack[stack_id].buffer_vertex_0_arrow);
printf("buffer_colors_0_arrow = %ld\n", graphic_stack[stack_id].buffer_colors_0_arrow);
printf("buffer_lines_0_arrow = %ld\n", graphic_stack[stack_id].buffer_lines_0_arrow);
printf("buffer_plans_0_arrow = %ld\n", graphic_stack[stack_id].buffer_plans_0_arrow);
printf("********************\n");
n++;
}
void graphics_model_setup (const int stack_id);
int draw_one_arrow_vertex (const int stack_id,
int space_X,
int space_Y,
int space_Z,
int weight,
int site,
int x,
int y,
int z);
int draw_one_arrow_line(const int stack_id,
int offset_vertex);
/*
* Writes grid ridges to vertex and color buffers
*
* @param coords long (x,y,z), step_x, step_y, step_z
*
* @return void
*/
int draw_space_ridges_vertex (const int stack_id,
long offset_vertex,
long x,
long y,
long z);
int draw_space_ridges_lines (const int stack_id);
/*
* Writes grid lines on space faces
*
* @param coords long (x,y,z)
*
* @return void
*/
long draw_grids_on_space_faces_vertex (const int stack_id,
long x,
long y,
long z);
long draw_grids_on_space_faces_lines (const int stack_id,
long offset_vertex,
long x,
long y,
long z);
int set_arrow (int stack_id,
int arrows_nb,
int space_X,
int space_Y,
int space_Z,
int requested_weight,
int site,
int arrow_x,
int arrow_y,
int arrow_z);

323
graph_stack.c Normal file
View File

@ -0,0 +1,323 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <time.h>
#include "contain.h"
#include "graph_area.h"
#include "parsing.h"
#define TEST 0
struct graphic_stack_t *graphic_stack = NULL;
size_t graphic_stack_size = 0;
int *free_stack_slot = NULL;
size_t free_stack_slot_size = 0;
/*
* Prints verbose human-readable debug messages
*
* @param source, XXX
* type, XXX
* id, XXX
* severity, XXX
* length, XXX
* msg, XXX
* data, XXX
*
* @return void
*/
static void graphics_debug_callback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length,
const GLchar *msg, const void *data)
{
const char *errsource;
const char *errtype;
const char *errseverity;
const GLubyte *string;
GLenum code;
switch (source) {
case GL_DEBUG_SOURCE_API: errsource = "API"; break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: errsource = "WINDOW SYSTEM"; break;
case GL_DEBUG_SOURCE_SHADER_COMPILER: errsource = "SHADER COMPILER"; break;
case GL_DEBUG_SOURCE_THIRD_PARTY: errsource = "THIRD PARTY"; break;
case GL_DEBUG_SOURCE_APPLICATION: errsource = "APPLICATION"; break;
case GL_DEBUG_SOURCE_OTHER: errsource = "UNKNOWN"; break;
default: errsource = "UNKNOWN"; break;
}
switch (type) {
case GL_DEBUG_TYPE_ERROR: errtype = "ERROR"; break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: errtype = "DEPRECATED BEHAVIOR";break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: errtype = "UNDEFINED BEHAVIOR"; break;
case GL_DEBUG_TYPE_PORTABILITY: errtype = "PORTABILITY"; break;
case GL_DEBUG_TYPE_PERFORMANCE: errtype = "PERFORMANCE"; break;
case GL_DEBUG_TYPE_OTHER: errtype = "OTHER"; break;
case GL_DEBUG_TYPE_MARKER: errtype = "MARKER"; break;
default: errtype = "UNKNOWN"; break;
}
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH: errseverity = "CRITICAL"; break;
case GL_DEBUG_SEVERITY_MEDIUM: errseverity = "ERROR"; break;
case GL_DEBUG_SEVERITY_LOW: errseverity = "WARNING"; break;
case GL_DEBUG_SEVERITY_NOTIFICATION: errseverity = "INFO"; break;
default: errseverity = "UNKNOWN"; break;
}
code = glGetError();
string = gluErrorString(code);
g_printerr("[%s] %s (%s) from %s: %s\n",
errseverity, string, errtype, errsource, msg);
}
/* -------------------------------------------------------------------------- */
/*
* Initializes graphical stack
*
* @param gl_area, ptr to the gl_area widget
*
* @return id if initialized
*/
int graphics_init(void *error_buffer)
{
int cur_id = 0;
struct graphic_stack_t *stack;
g_printerr("[debug] graphics_init()\n");
if (graphic_stack == NULL) {
graphic_stack = g_malloc0(sizeof(struct graphic_stack_t));
graphic_stack_size = 1;
g_printerr("[debug] graphics_init(): init graphic_stack @ %p\n", graphic_stack);
} else {
// Check if there are free slots
if (free_stack_slot_size) {
// We get the last free slot registered
cur_id = free_stack_slot[free_stack_slot_size-1];
// Unregister it (ofc)
free_stack_slot = g_realloc(free_stack_slot,
free_stack_slot_size-- *
sizeof(int));
} else {
cur_id = graphic_stack_size;
graphic_stack = g_realloc(graphic_stack,
++graphic_stack_size *
sizeof(struct graphic_stack_t));
}
}
memset(&graphic_stack[cur_id], 0, sizeof(struct graphic_stack_t));
g_printerr("[debug] graphics_init() : graphic_stack (@0x%p) has %ld elements\n",
graphic_stack,
graphic_stack_size);
stack = &graphic_stack[cur_id];
stack->id = cur_id;
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glEnable(GL_MULTISAMPLE);
if (!graphics_init_shaders(cur_id)) return -1;
print_stack(cur_id);
graphics_init_buffers(cur_id);
glDebugMessageCallback(graphics_debug_callback, NULL);
//print_stack(cur_id);
return cur_id;
}
/*
* Shutdowns a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if success
*/
bool graphics_shutdown(const int id, void *error_buffer)
{
struct graphic_stack_t *stack;
if (id >= graphic_stack_size ||
graphic_stack_size == 0 ||
graphic_stack == NULL)
return false;
stack = &graphic_stack[id];
//XXX
free(stack->arrows_ptr);
stack->arrows_ptr = NULL;
stack->arrows_nb = 0;
glDeleteBuffers(1, &stack->position_buffer);
glDeleteBuffers(1, &stack->color_buffer);
glDeleteProgram(stack->program);
g_free(stack->buffer_vertex_origin);
g_free(stack->buffer_colors_origin);
g_free(stack->buffer_lines_origin);
g_free(stack->buffer_plans_origin);
if (graphic_stack_size == 1) {
free(graphic_stack);
graphic_stack = NULL;
graphic_stack_size = 0;
} else {
memset(&graphic_stack[id], 0, sizeof(struct graphic_stack_t));
free_stack_slot = g_realloc(free_stack_slot,
++free_stack_slot_size *
sizeof(int));
free_stack_slot[free_stack_slot_size-1] = id;
}
return true;
}
/* TODO
* #pragma omp parallel schedule(static, 12)
* void __attribute__((optimize("no-unroll-loops"))) main_test_graphics (void) {}
*
// assert : space dimensions (x,y,z) > 0
// assert : arrows localization within space and sites
// assert : no more than one arrow per address
// notify : weights are replaced, NOT added (could be !)
*
* Init space and arrows (= initial state)
* and allows ulterior creations, suppressions or modifications of the arrows[] array
*
* draws the space()
* triggers set_arrows() that modifies the list () and draws arrows
*
* Initialisation du générateur pseudo-aléatoire
* Attention, les vertex centraux de chaque unité d'espace (cube)
* peuvent être redondants (max 6)
*/
void graphics_model_setup (const int stack_id)
{
/*------------------------------------------------------------------------*/
/* I N I T I A L D A T A S P E C I F I C A T I O N */
/*------------------------------------------------------------------------*/
struct graphic_stack_t *stack = &graphic_stack[stack_id];
char dimension;
long space_X;
long space_Y;
long space_Z;
long announced_arrows_nb;
int density_max;
char multiplicity;
dimension = model_get_dim();
g_print("[GRAPH DEBUG] dim = %d\n", dimension);
space_X = 1;
space_Y = 1;
space_Z = 1;
switch(dimension) {
case 3:
space_Z = model_get_dim_value("z");
;
case 2:
space_Y = model_get_dim_value("y");
;
// even in 1D, we must be able to see a grid (or not !)
if (!space_Y)
space_Y = 1;
case 1:
space_X = model_get_dim_value("x");
;
if (!space_X)
space_X = 1;
default:
break;
}
g_print("[GRAPH DEBUG] x = %ld\n", space_X);
g_print("[GRAPH DEBUG] y = %ld\n", space_Y);
g_print("[GRAPH DEBUG] z = %ld\n", space_Z);
density_max = space_X * space_Y * space_Z;
stack->arrows_nb = 0;
multiplicity = model_get_multiplicity();
g_print("[GRAPH DEBUG] site_multiplicity = %d, density_max = %d\n", multiplicity, density_max);
/*------------------------------------------------------------------------*/
/* S P A C E D R A W I N G */
/*------------------------------------------------------------------------*/
draw_space_ridges_vertex (stack_id, stack->buffer_vertex_size, space_X, space_Y, space_Z);
draw_space_ridges_lines (stack_id);
draw_grids_on_space_faces_vertex (stack_id, space_X, space_Y, space_Z);
draw_grids_on_space_faces_lines (stack_id, stack->buffer_lines_size, space_X, space_Y, space_Z);
stack->buffer_vertex_0_arrow = stack->buffer_vertex_size;
stack->buffer_colors_0_arrow = stack->buffer_colors_size;
stack->buffer_lines_0_arrow = stack->buffer_lines_size;
/*------------------------------------------------------------------------*/
/* A R R O W S D R A W I N G */
/*------------------------------------------------------------------------*/
char state_id[30] = {0};
struct arrow_t arrow = {0};
assert(model_get_next_state((char *)&state_id));
g_print("[GRAPH DEBUG] first state is = %s\n", state_id);
announced_arrows_nb = model_get_state_arrows_count(state_id);
g_print("[GRAPH DEBUG] announced_arrows_nb is = %ld\n", announced_arrows_nb);
while (model_get_next_arrow(&arrow, (char *)&state_id, dimension)) {
g_print("[GRAPH DEBUG] cur arrow has x = %d\n", arrow.x);
stack->arrows_nb = set_arrow (stack_id, stack->arrows_nb, space_X, space_Y, space_Z, arrow.load, arrow.site, arrow.x, arrow.y, arrow.z);
}
if (stack->arrows_nb != announced_arrows_nb)
g_printerr("ARGH : not all arrows have been parsed !\n");
}

314
graphics.h Normal file
View File

@ -0,0 +1,314 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: OpenGL utils header
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "base.h"
#include <unistd.h>
#include <stdbool.h>
#include <epoxy/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <cglm/cglm.h>
#define VERTEX_SHADER_FILE "src/graphics/shaders/shader.vert"
#define FRAG_SHADER_FILE "src/graphics/shaders/shader.frag"
#define GL_TARGET_MAJOR_VERSION 0
#define GL_TARGET_MINOR_VERSION 4
/*
* Structure describing a gl_area and its parameters, used to create a table
* of Gem-graph client current gl_areas
*/
struct graphic_stack_t {
int id;
int mode;
float rotation_angles[N_AXIS]; // Rotation angles on each axis
GLuint vao; // init_buffers
GLuint position_buffer; // shutdown, draw
GLuint color_buffer; // shutdown, draw
GLuint program; // shutdown, init_shaders, draw
GLuint m; // init_shaders, draw
GLuint v; // init_shaders, draw
GLuint p; // init_shaders, draw
struct arrow_t *arrows_ptr;
long arrows_nb;
GLfloat *buffer_vertex_origin;
GLfloat *buffer_colors_origin;
GLuint *buffer_lines_origin;
GLuint *buffer_plans_origin;
long buffer_vertex_size;
long buffer_colors_size;
long buffer_lines_size;
long buffer_plans_size;
long buffer_vertex_0_arrow;
long buffer_colors_0_arrow;
long buffer_lines_0_arrow;
long buffer_plans_0_arrow;
};
/*
* Dynamic array of ptrs to dynamically allocated gl_area_entry
*/
extern struct graphic_stack_t *graphic_stack;
/*
* Initializes a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if initialized
*/
int graphics_init(void *error_buffer);
/*
* Draws the current buffer to a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return void
*/
//void graphics_draw(const int stack_id);
/*
* Shutdowns a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if success
*/
bool graphics_shutdown(const int stack_id, void *error_buffer);
/*
* Initializes the shaders of a gl_area and link them to a program
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if initialized
*/
bool graphics_init_shaders(const int stack_id);
/* Initializes the buffer of a gl_area
* Calls according to the user preferences
* @param gl_area, ptr to the gl_area widget
* @return void
*/
void graphics_init_buffers(const int stack_id);
/*
* Draws a vertex (x, y, z)
* if (console) prints (x, y, z) values to console
*
* @param GLfloat x, GLfloat y, GLfloat z
*
* @return void
*/
void graphics_draw_vertex (const int stack_id,
GLfloat x,
GLfloat y,
GLfloat z);
/*
* Draws the color (r, g, b) associated to a vertex
* if (console) prints (r, g, b) values to console
*
* @param GLfloat r, GLfloat g, GLfloat b
*
* @return void
*/
void graphics_draw_color (const int stack_id, GLfloat r, GLfloat g, GLfloat b);
/*
* Writes values to describe a line from a to b into the line buffer
*
* @param coords GLuint (a,b)
*
* @return void
*/
void graphics_draw_line (const int stack_id, GLuint a, GLuint b);
/*
* Writes values to describe an (a,b,c) plan (triangle) into the plan buffer
*
* @param coords GLuint (a,b,c)
*
* @return void
*/
void graphics_draw_plan (const int stack_id, GLuint a, GLuint b, GLuint c);
/*
* Created and compile a shader
*
* @param type, shader type
* src, source code of shader
*
* @return shader id
*/
static inline GLuint create_shader(const int stack_id, int type, const char *src)
{
GLuint shader;
int status;
shader = glCreateShader(type);
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE) {
int log_len;
char *buffer;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc(log_len + 1);
assert (buffer);
glGetShaderInfoLog(shader, log_len, NULL, buffer);
g_warning("Compile failure in %s shader:\n%s",
type == GL_VERTEX_SHADER ? "vertex" : "fragment",
buffer);
g_free(buffer);
glDeleteShader(shader);
return 0;
}
return shader;
}
static inline void print_stack(int stack_id)
{
static int n = 0;
printf("\n[n=%d]***************", n);
printf("id = %d\tmode = %d\n",
graphic_stack[stack_id].id,
graphic_stack[stack_id].mode);
printf("rotation_angles = ");
for (int i = 0; i < N_AXIS; i++) {
printf("%f\t", graphic_stack[stack_id].rotation_angles[i]); // Rotation angles on each axis
}
printf("\n");
printf("vao = %d\n", graphic_stack[stack_id].vao);
printf("position_buffer = %d\n", graphic_stack[stack_id].position_buffer);
printf("color_buffer = %d\n", graphic_stack[stack_id].color_buffer);
printf("program = %d\n", graphic_stack[stack_id].program);
printf("m = %d\n", graphic_stack[stack_id].m);
printf("v = %d\n", graphic_stack[stack_id].v);
printf("p = %d\n", graphic_stack[stack_id].p);
printf("arrows_ptr = %p\n", graphic_stack[stack_id].arrows_ptr);
printf("arrows_nb = %ld\n", graphic_stack[stack_id].arrows_nb);
printf("buffer_vertex_origin = %p\n", graphic_stack[stack_id].buffer_vertex_origin);
printf("buffer_colors_origin = %p\n", graphic_stack[stack_id].buffer_colors_origin);
printf("buffer_lines_origin = %p\n", graphic_stack[stack_id].buffer_lines_origin);
printf("buffer_plans_origin = %p\n", graphic_stack[stack_id].buffer_plans_origin);
printf("buffer_vertex_size = %ld\n", graphic_stack[stack_id].buffer_vertex_size);
printf("buffer_colors_size = %ld\n", graphic_stack[stack_id].buffer_colors_size);
printf("buffer_lines_size = %ld\n", graphic_stack[stack_id].buffer_lines_size);
printf("buffer_plans_size = %ld\n", graphic_stack[stack_id].buffer_plans_size);
printf("buffer_vertex_0_arrow = %ld\n", graphic_stack[stack_id].buffer_vertex_0_arrow);
printf("buffer_colors_0_arrow = %ld\n", graphic_stack[stack_id].buffer_colors_0_arrow);
printf("buffer_lines_0_arrow = %ld\n", graphic_stack[stack_id].buffer_lines_0_arrow);
printf("buffer_plans_0_arrow = %ld\n", graphic_stack[stack_id].buffer_plans_0_arrow);
printf("********************\n");
n++;
}
void graphics_model_setup (const int stack_id);
int draw_one_arrow_vertex (const int stack_id,
int space_X,
int space_Y,
int space_Z,
int weight,
int site,
int x,
int y,
int z);
int draw_one_arrow_line(const int stack_id,
int offset_vertex);
/*
* Writes grid ridges to vertex and color buffers
*
* @param coords long (x,y,z), step_x, step_y, step_z
*
* @return void
*/
int draw_space_ridges_vertex (const int stack_id,
long offset_vertex,
long x,
long y,
long z);
int draw_space_ridges_lines (const int stack_id);
/*
* Writes grid lines on space faces
*
* @param coords long (x,y,z)
*
* @return void
*/
long draw_grids_on_space_faces_vertex (const int stack_id,
long x,
long y,
long z);
long draw_grids_on_space_faces_lines (const int stack_id,
long offset_vertex,
long x,
long y,
long z);
int set_arrow (int stack_id,
int arrows_nb,
int space_X,
int space_Y,
int space_Z,
int requested_weight,
int site,
int arrow_x,
int arrow_y,
int arrow_z);

162
grid.c Normal file
View File

@ -0,0 +1,162 @@
/*
* Gem-graph
*
* Desc: OpenGL grid functions
*
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <time.h>
#include "base.h"
//#include "ui.h"
#include "graphics.h"
int draw_space_ridges_vertex (const int stack_id,
long offset_vertex,
long x,
long y,
long z)
{
GLfloat max = fmax(x, y); max = fmax(max, z);
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex - y / max, - z / max);
graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex - y / max, - z / max);
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex + y / max, - z / max);
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex - y / max, + z / max);
graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex + y / max, - z / max);
graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex - y / max, + z / max);
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex + y / max, + z / max);
graphics_draw_vertex (stack_id, offset_vertex + x / max, + y / max, + z / max);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
return 8;
}
int draw_space_ridges_lines (const int stack_id)
{
graphics_draw_line (stack_id, 0, 1); graphics_draw_line (stack_id, 7, 4);
graphics_draw_line (stack_id, 0, 2); graphics_draw_line (stack_id, 7, 5);
graphics_draw_line (stack_id, 0, 3); graphics_draw_line (stack_id, 7, 6);
graphics_draw_line (stack_id, 1, 4); graphics_draw_line (stack_id, 2, 4);
graphics_draw_line (stack_id, 1, 5); graphics_draw_line (stack_id, 3, 5);
graphics_draw_line (stack_id, 2, 6); graphics_draw_line (stack_id, 3, 6);
return 12;
}
long draw_grids_on_space_faces_vertex (const int stack_id,
long x,
long y,
long z)
{
float i, max = fmax(x, y); max = fmax(max, z);
for (i = 1; i < x; i++) {
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, - y / max, - z / max);
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, - y / max, z / max);
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, y / max, z / max);
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, y / max, - z / max);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
}
/* offset_vertex += (x - 1) * 4; */ /* offset_colors += (x - 1) * 4; */
for (i = 1; i < y; i++) {
graphics_draw_vertex (stack_id, - x / max, (2 * i / y - 1) * y / max, - z / max);
graphics_draw_vertex (stack_id, - x / max, (2 * i / y - 1) * y / max, z / max);
graphics_draw_vertex (stack_id, x / max, (2 * i / y - 1) * y / max, z / max);
graphics_draw_vertex (stack_id, x / max, (2 * i / y - 1) * y / max, - z / max);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
}
/* offset_vertex += (y - 1) * 4; */ /* offset_colors += (y - 1) * 4; */
for (i = 1; i < z; i++) {
graphics_draw_vertex (stack_id, - x / max, - y / max, (2 * i / z - 1) * z / max);
graphics_draw_vertex (stack_id, - x / max, y / max, (2 * i / z - 1) * z / max);
graphics_draw_vertex (stack_id, x / max, y / max, (2 * i / z - 1) * z / max);
graphics_draw_vertex (stack_id, x / max, - y / max, (2 * i / z - 1) * z / max);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
}
return (x + y + z - 3) * 3;
}
long draw_grids_on_space_faces_lines (const int stack_id,
long offset_vertex,
long x,
long y,
long z)
{
offset_vertex = offset_vertex / 3;
for (int i = 0; i < x - 1; i ++) {
graphics_draw_line (stack_id, offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2);
graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3);
}
offset_vertex += (x - 1) * 4;
for (int i = 0; i < y - 1; i ++) {
graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3);
graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0);
}
offset_vertex += (y - 1) * 4;
for (int i = 0; i < z - 1; i ++) {
graphics_draw_line (stack_id, offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1);
graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0);
}
return (x + y + z - 3) * 4;
}

BIN
image/AMP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

BIN
image/ATP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
image/E coli (Goodsell).png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
image/aXoris.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
image/catécholamines.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
image/dopamine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

BIN
image/glutamate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
image/glutamine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
image/hb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB

BIN
image/insuline Zn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

BIN
image/insuline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
image/phénylalanine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

191
init.c Normal file
View File

@ -0,0 +1,191 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include <stdlib.h>
#include <time.h>
#include "base.h"
#include "contain.h" // instead of "ui.h"
#include "graph_area.h"
/* Initializes the buffer of a gl_area
* Calls according to the user preferences
* @param gl_area, ptr to the gl_area widget
* @return void
*/
void graphics_init_buffers(const int stack_id)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
//XXX
graphics_model_setup(stack_id);
GLuint vao, vertex_buffer, color_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER,
stack->buffer_vertex_size *
sizeof(stack->buffer_vertex_origin[0]),
stack->buffer_vertex_origin,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// colors
glGenBuffers(1, &color_buffer);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glBufferData(GL_ARRAY_BUFFER, stack->buffer_colors_size *
sizeof(stack->buffer_colors_origin[0]),
stack->buffer_colors_origin,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// We only use one VAO, so we always keep it bound
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
stack->vao = vao;
stack->position_buffer = vertex_buffer;
stack->color_buffer = color_buffer;
}
/*
* Initializes the shaders of a gl_area and link them to a program
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if initialized
*/
bool graphics_init_shaders(const int stack_id)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
char *vertex_shader;
char *fragment_shader;
int status;
GLuint vertex = 0, fragment; // 2024-06-05 j'initialise vertex à 0 (au pif !)
GLuint program = 0;
GLuint m = 0;
GLuint v = 0;
GLuint p = 0;
// Load vertex shader file
vertex_shader = read_file(VERTEX_SHADER_FILE);
if (vertex_shader == NULL)
return false;
vertex = create_shader(stack_id, GL_VERTEX_SHADER, vertex_shader);
if(vertex == 0) {
stack->program = 0;
g_free(vertex_shader);
return false;
}
// Load fragment shader file
fragment_shader = read_file(FRAG_SHADER_FILE);
if (fragment_shader == NULL)
return false;
fragment = create_shader(stack_id, GL_FRAGMENT_SHADER, fragment_shader);
if(fragment == 0) {
glDeleteShader(vertex);
stack->program = 0;
g_free(vertex_shader);
g_free(fragment_shader);
return false;
}
// Link shaders to program
program = glCreateProgram();
printf("\n------------------------------------------------------------------------------------------\n");
printf("[debug] graphics_init_shaders() : program = %d, vertex = %d, fragment = %d\n\
exec > ** (myprogram:-----): WARNING ** : --:--:--:---: Linking failure: (address)\n",
program, vertex, fragment);
/* (myprogram:11732): WARNING **: 10:37:34.233: v plusieurs 'run' successifs
* (myprogram:11883): WARNING **: 10:38:22.979: glLinkProgram(program); < commenté
* (myprogram:11953): WARNING **: 10:38:46.170:
* (myprogram:12034): WARNING **: 10:39:14.709:
* (myprogram:12182): WARNING **: 10:40:49.788:
* > probablement la même adresse dans la librairie 'mesa' d'OpenGL (?) */
glAttachShader(program, vertex);
glAttachShader(program, fragment);
printf("Failed to link the graphic stack to widgets ! <> see init.c graphics_init_shaders()\n");
printf("the error in not : vertex shader lacks `main' but : failed to link... (comment line 140)\n");
// https://registry.khronos.org/OpenGL-Refpages/gl4/html/glLinkProgram.xhtml
// glLinkProgram(program); // Linking failure: (address)
printf("------------------------------------------------------------------------------------------\n");
glGetProgramiv(program, GL_LINK_STATUS, &status); // Linking failure: (address)
if(status == GL_FALSE) {
int log_len;
char *buffer;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc(log_len + 1);
assert(buffer);
glGetProgramInfoLog(program, log_len, NULL, buffer);
g_warning("Linking failure:\n%s", buffer);
g_free(buffer);
glDeleteProgram(program);
program = 0;
glDeleteShader(vertex);
glDeleteShader(fragment);
g_free(vertex_shader);
g_free(fragment_shader);
return false;
}
/* Get the location of the "mvp" uniform */
m = glGetUniformLocation(program, "model_matrix");
v = glGetUniformLocation(program, "view_matrix");
p = glGetUniformLocation(program, "projection_matrix");
glDetachShader(program, vertex);
glDetachShader(program, fragment);
glDeleteShader(vertex);
glDeleteShader(fragment);
stack->program = program;
stack->m = m;
stack->v = v;
stack->p = p;
g_free(vertex_shader);
g_free(fragment_shader);
return true;
}

175
init.c.todo Normal file
View File

@ -0,0 +1,175 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include <stdlib.h>
#include <time.h>
#include "base.h"
#include "contain.h" // instead of "ui.h"
#include "graph_area.h"
/* Initializes the buffer of a gl_area
* Calls according to the user preferences
* @param gl_area, ptr to the gl_area widget
* @return void
*/
void graphics_init_buffers(const int stack_id)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
//XXX
graphics_model_setup(stack_id);
GLuint vao, vertex_buffer, color_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER,
stack->buffer_vertex_size *
sizeof(stack->buffer_vertex_origin[0]),
stack->buffer_vertex_origin,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// colors
glGenBuffers(1, &color_buffer);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glBufferData(GL_ARRAY_BUFFER, stack->buffer_colors_size *
sizeof(stack->buffer_colors_origin[0]),
stack->buffer_colors_origin,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// We only use one VAO, so we always keep it bound
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
stack->vao = vao;
stack->position_buffer = vertex_buffer;
stack->color_buffer = color_buffer;
}
/*
* Initializes the shaders of a gl_area and link them to a program
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if initialized
*/
bool graphics_init_shaders(const int stack_id)
{
struct graphic_stack_t *stack = &graphic_stack[stack_id];
char *vertex_shader;
char *fragment_shader;
int status;
GLuint vertex = 0, fragment; // 2024-06-05 j'initialise vertex à 0 (au pif !)
GLuint program = 0;
GLuint m = 0;
GLuint v = 0;
GLuint p = 0;
// Load vertex shader file
vertex_shader = read_file(VERTEX_SHADER_FILE);
if (vertex_shader == NULL)
return false;
vertex = create_shader(stack_id, GL_VERTEX_SHADER, vertex_shader);
if(vertex == 0) {
stack->program = 0;
g_free(vertex_shader);
return false;
}
// Load fragment shader file
fragment_shader = read_file(FRAG_SHADER_FILE);
if (fragment_shader == NULL)
return false;
fragment = create_shader(stack_id, GL_FRAGMENT_SHADER, fragment_shader);
if(fragment == 0) {
glDeleteShader(vertex);
stack->program = 0;
g_free(vertex_shader);
g_free(fragment_shader);
return false;
}
// Link shaders to program
program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(status == GL_FALSE) {
int log_len;
char *buffer;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc(log_len + 1);
assert(buffer);
glGetProgramInfoLog(program, log_len, NULL, buffer);
g_warning("Linking failure:\n%s", buffer);
g_free(buffer);
glDeleteProgram(program);
program = 0;
glDeleteShader(vertex);
glDeleteShader(fragment);
g_free(vertex_shader);
g_free(fragment_shader);
return false;
}
/* Get the location of the "mvp" uniform */
m = glGetUniformLocation(program, "model_matrix");
v = glGetUniformLocation(program, "view_matrix");
p = glGetUniformLocation(program, "projection_matrix");
glDetachShader(program, vertex);
glDetachShader(program, fragment);
glDeleteShader(vertex);
glDeleteShader(fragment);
stack->program = program;
stack->m = m;
stack->v = v;
stack->p = p;
g_free(vertex_shader);
g_free(fragment_shader);
return true;
}

BIN
main

Binary file not shown.

77
main.c Executable file → Normal file
View File

@ -1,73 +1,26 @@
/* main.c /******************************************************************************/
* /* */
* Copyright 2024 Jean /* E coli by David S. Goodsell (2009) */
* /* --- */
* This program is free software: you can redistribute it and/or modify /* Let this freeze frame guide us towards the model */
* it under the terms of the GNU General Public License as published by /* that alone can account for the phenomenon ! */
* the Free Software Foundation, either version 3 of the License, or /* */
* (at your option) any later version. /******************************************************************************/
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <gtk/gtk.h> #include "callback.h"
static void int main (int argc, char **argv)
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
gtk_window_set_child (GTK_WINDOW (window), box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_box_append (GTK_BOX (box), button);
gtk_window_present (GTK_WINDOW (window));
}
int
main (int argc,
char **argv)
{ {
GtkApplication *app; GtkApplication *app;
int status; int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS); app = gtk_application_new ("org.jean.GTK4_GG_hack", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); g_signal_connect (app, "activate", G_CALLBACK (on_main_window_activation), NULL);
g_signal_connect (app, "activate", G_CALLBACK (on_dialog_window_activation), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv); status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app); g_object_unref (app);
printf("in contain.get_SPACE_VIEW_box() (line 138) > ui_setup_glarea (0, GTK_WIDGET (middle_box)); < commented 2024/06/27 > TODO\n");
return status; return status;
} }

30
manifest.scm Normal file
View File

@ -0,0 +1,30 @@
;;
;; Dépendances sous GNU Guix
;;
(specifications->manifest
(list
"bash"
"coreutils"
"gcc-toolchain"
"pkg-config"
"valgrind"
"findutils"
"gdb"
"make"
"gtk"
"libxml2"
"glu"
"glew"
"glfw"
"cglm"
"libepoxy"
"pango@1.90.0"
"xorgproto"
"glib"
"mesa-headers"
"mesa"
"libadwaita"
)
)

481
parsing.c Normal file
View File

@ -0,0 +1,481 @@
/*
* Gem-graph client
*
* Desc: Model parsing functions
*
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
* Copyright (C) 2024 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <limits.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xmlreader.h> // http://xmlsoft.org/examples/#parse1.c
// https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/general.html
#include "base.h"
#define READ_SITE 1 << 0
#define READ_WEIGHT 1 << 1
#define READ_X 1 << 2
#define READ_Y 1 << 3
#define READ_Z 1 << 4
#define SUCCESSFUL_READ_ARROW_X (READ_SITE | READ_WEIGHT | READ_X)
#define SUCCESSFUL_READ_ARROW_XY (READ_SITE | READ_WEIGHT | READ_X | READ_Y)
#define SUCCESSFUL_READ_ARROW_XYZ (READ_SITE | READ_WEIGHT | READ_X | READ_Y | READ_Z)
static xmlDocPtr model;
static xmlHashTablePtr model_hashtable;
bool model_init(const char *content, size_t length, const char *basename)
{
xmlNode *node;
/*
* this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared
* library used.
*/
LIBXML_TEST_VERSION
model = xmlReadMemory(content, length, basename, NULL, 0);
if (model == NULL ) {
return false;
}
node = xmlDocGetRootElement(model);
if (node == NULL) {
g_printerr("Empty XML model !\n");
xmlFreeDoc(model);
return false;
}
if (xmlStrcmp(node->name, (xmlChar *) "gem-graph-model")) {
g_printerr("document of the wrong type, root node != gem-graph-model\n");
xmlFreeDoc(model);
return false;
}
model_hashtable = xmlHashCreate(0);
if (model_hashtable == NULL) {
g_printerr("Can't create model hash table !\n");
xmlFreeDoc(model);
return false;
}
return true;
}
bool model_shutdown(void)
{
xmlFreeDoc(model);
xmlHashFree(model_hashtable, NULL);
// Cleanup function for the XML library
xmlCleanupParser();
// This is to debug memory for regression tests
xmlMemoryDump();
return true;
}
/******************************************************************************/
static inline xmlNodePtr getNextChild(xmlNodePtr node, xmlChar *last)
{
while (node != NULL && xmlStrcmp(node->name, last)) {
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name);
node = node->next;
}
return node;
}
static inline xmlChar* splitStrAtSlash(xmlChar *toSplit)
{
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
return toSplit;
}
static inline xmlChar* getFirstTag(xmlChar *path)
{
xmlChar *preop = path;
path = (xmlChar *)xmlStrchr(path, '/');
path = xmlStrsub (path, 1, xmlStrlen(path));
//printf("%s = %s + / + %s\n", preop, xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1), path);
return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1);
}
static inline xmlChar* getLastTag(xmlChar *path)
{
while ((ulong)xmlStrchr (path, '/'))
path = splitStrAtSlash((xmlChar *)path);
// //printf("last tag in the path = <%s>\n", path);
return path; // which is no more the given path but only its last tag !
}
/******************************************************************************/
static xmlNodePtr model_get_node(xmlChar *path)
{
xmlNodePtr node;
xmlChar *extrait;
xmlChar *reste, *last;
// Lookup for node from path in hash table
node = xmlHashLookup(model_hashtable, path);
// Found a node in hash table
if (node) {
return node;
// no node found in hash table
} else {
reste = path;
last = getLastTag(reste);
node = xmlDocGetRootElement(model);
while (xmlStrchr (reste, '/')) {
extrait = getFirstTag(reste);
reste = splitStrAtSlash((xmlChar *)reste);
node = node->xmlChildrenNode;
node = getNextChild(node, extrait);
}
if(node && xmlStrcmp(node->name, last)) {
node = node->xmlChildrenNode;
while (node && xmlStrcmp(node->name, last)) {
node = node->next;
}
xmlHashAddEntry (model_hashtable, path, node);
}
return node;
}
return NULL;
}
/******************************************************************************/
static inline long model_get_node_long_attrib(xmlNodePtr node, char *id)
{
xmlAttr *attribute;
xmlChar* value;
long ret_value;
if (node && node->properties) {
attribute = node->properties;
while(attribute && attribute->name && attribute->children) {
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
value = xmlNodeListGetString(node->doc, attribute->children, 1);
ret_value = strtol((char *)value, NULL, 0);
xmlFree(value);
return ret_value;
}
attribute = attribute->next;
}
}
return 0;
}
static inline bool model_get_node_str_attrib(xmlNodePtr node,
char *id,
char *dest)
{
xmlAttr *attribute;
xmlChar* value;
if (node && node->properties) {
attribute = node->properties;
while(attribute && attribute->name && attribute->children) {
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
value = xmlNodeListGetString(node->doc, attribute->children, 1);
strcpy(dest, (char *)value);
xmlFree(value);
return true;
}
attribute = attribute->next;
}
}
return false;
}
/******************************************************************************/
char model_get_dim(void)
{
// xmlAttr *attribute;
// xmlChar* value;
xmlNodePtr node = model_get_node(
(xmlChar *)"parameters/space-param/dimension");
if (xmlHasProp (node, (xmlChar *) "z")) return 3;
if (xmlHasProp (node, (xmlChar *) "y")) return 2;
if (xmlHasProp (node, (xmlChar *) "x")) return 1;
return 0;
}
long model_get_dim_value(const char *axis)
{
// xmlAttr *attribute;
// xmlChar *value;
// long ret_value;
xmlNodePtr node = model_get_node(
(xmlChar *)"parameters/space-param/dimension");
return model_get_node_long_attrib(node, (char *)axis);
}
char model_get_multiplicity(void)
{
// xmlAttr *attribute;
// xmlChar* value;
xmlNodePtr node = model_get_node(
(xmlChar *)"parameters/space-param/site_multiplicity");
if (node->children)
if (node->children->content)
return (char)strtol((char *)node->children->content, NULL, 0);
return 0;
}
bool model_get_next_state(char *new_state_id)
{
static xmlNodePtr cur_node = NULL;
// xmlAttr *attribute;
// xmlChar *value;
if (cur_node == NULL) {
// Get first state
cur_node = model_get_node((xmlChar *)"savedstates/state");
} else {
// Get next state
if (cur_node->next)
cur_node = cur_node->next;
else
return false;
}
// Lookup in properties
if (model_get_node_str_attrib(cur_node, "id", new_state_id))
return true;
cur_node = NULL;
return false;
}
long model_get_state_arrows_count(const char *state_id)
{
xmlNodePtr cur_node = NULL;
// xmlAttr *attribute;
long value = 0;
bool found = false;
char temp_char[25];
// uint check = 0; // bit field checker
//printf("NEW CALL : cur_node = %p\n", cur_node);
assert(state_id);
// Get first state node
cur_node = model_get_node((xmlChar *)"savedstates/state");
// Lookup in properties
while (cur_node && cur_node->properties) {
// attribute = cur_node->properties; < usage ?
// Look for the id attribute
if (model_get_node_str_attrib(cur_node, "id", (char *)&temp_char)) {
if (!xmlStrcmp((const xmlChar *)temp_char, (const xmlChar *)state_id)) {
found = true;
break;
}
}
cur_node = cur_node->next;
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return -1;
}
// Count arrows
if (cur_node->children) {
cur_node = cur_node->children;
while (cur_node) {
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow"))
value++;
cur_node = cur_node->next;
}
} else {
return -1;
}
return value;
}
bool model_get_next_arrow(struct arrow_t *new_arrow,
const char *state_id,
char dimension)
{
static xmlNodePtr cur_node = NULL;
xmlAttr *attribute;
xmlChar *value;
bool found = false;
char temp_char[25];
uint check = 0; // bit field checker
//printf("NEW CALL : cur_node = %p\n", cur_node);
assert(new_arrow);
assert(state_id);
if (cur_node == NULL) {
// Get first state node
cur_node = model_get_node((xmlChar *)"savedstates/state");
// Lookup in properties
while (cur_node && cur_node->properties) {
attribute = cur_node->properties;
// Look for the id attribute
if (model_get_node_str_attrib(cur_node, "id", (char *)&temp_char)) {
if (!xmlStrcmp((xmlChar *)temp_char, (const xmlChar *)state_id)) {
found = true;
break;
}
}
cur_node = cur_node->next;
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return false;
}
// Get first arrow
if (cur_node->children) {
cur_node = cur_node->children;
found = false;
while (cur_node && cur_node->name) {
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
found = true;
break;
}
cur_node = cur_node->next;
}
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return false;
}
} else {
// Get next arrow
found = false;
while (cur_node->next) {
cur_node = cur_node->next;
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
found = true;
break;
}
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return false;
}
}
//printf("DURING CALL : cur_node = %p\n", cur_node);
//printf("DURING CALL : cur_node->name = %s\n", cur_node->name);
// Lookup in properties
if (cur_node && cur_node->properties) {
attribute = cur_node->properties;
while(attribute && attribute->name && attribute->children) {
//printf("attr name : %s\n", attribute->name);
if (!xmlStrcmp(attribute->name, (const xmlChar *)"site")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_arrow->site = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_SITE;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"weight")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_arrow->load = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_WEIGHT;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"x")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_arrow->x = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_X;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"y")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_arrow->y = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_Y;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"z")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_arrow->z = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_Z;
}
attribute = attribute->next;
}
switch(dimension) {
case 3:
return (bool)(check & SUCCESSFUL_READ_ARROW_XYZ);
case 2:
return (bool)(check & SUCCESSFUL_READ_ARROW_XY);
case 1:
return (bool)(check & SUCCESSFUL_READ_ARROW_X);
}
}
cur_node = NULL;
return false;
}

43
parsing.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: Model parsing header
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <unistd.h>
#include "base.h"
bool model_init(const char *content, size_t length, const char *basename);
bool model_shutdown(void);
char model_get_dim(void);
long model_get_dim_value(const char *axis);
char model_get_multiplicity(void);
bool model_get_next_state(char *new_state_id);
bool model_get_next_arrow(struct arrow_t *new_arrow,
const char *state_id,
char dimension);
long model_get_state_arrows_count(const char *state_id);
bool model_get_next_arrow(struct arrow_t *new_arrow,
const char *state_id,
char dimension);

9
shader.frag Normal file
View File

@ -0,0 +1,9 @@
#version 330 core
in vec4 color;
out vec4 out_frag_color;
void main(void)
{
out_frag_color = color;
}

20
shader.vert Normal file
View File

@ -0,0 +1,20 @@
#version 330 core
uniform mat4 projection_matrix;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
layout(location=0) in vec3 in_position;
layout(location=1) in vec3 in_color;
out vec4 color;
void main(void)
{
float zoom = 1.1f, chrominance = 1, luminance = 1;
gl_Position =
projection_matrix * view_matrix * model_matrix * vec4(in_position, zoom);
color = vec4 (chrominance * in_color.rgb, luminance);
}
// https://learnopengl.com/Getting-started/Shaders

48
texts.c Normal file
View File

@ -0,0 +1,48 @@
/******************************************************************************/
/* */
/* E coli by David S. Goodsell (2009) */
/* --- */
/* Let this freeze frame guide us towards the model */
/* that alone can account for the phenomenon ! */
/* */
/******************************************************************************/
char *get_space_run_edit_specif(){ return "\n\
>>> Dans : [space_page - mode RUN] doivent être : ------------------------------------------------------\n\n\
(1) les commandes de mouvement:\n\
- run/stop, slow down/speed up, step by step, do/undo/redo\n\
+ le buffer [elapsed time] qui montre le temps de simulation écoulé\n\n\
(2) les commandes qui modifient la perception de l'espace (la caméra)\n\
- son orientation (X,Y,Z),\n\
+ l'orientation (X,Y,Z) de l'état dans l'espace (six possibilités),\n\
+ le zoom,\n\
+ les paramètres qui définissent la perspective (distances oeil/écran, écran/objet virtuel) \n\n\
(3) les commandes qui modifient les apparences des objets et des situations d'intérêt\n\
(+/- transparents, colorés, etc.)\n\n\
(4) les commandes qui modifient l'apparence de l'espace (grilles, +/- surfaces, aspect des flèches, etc.)\n\n\
(0) NB >>> AUCUNE COMMANDE NE DOIT PERMETTRE D'ÉDITER L'ESPACE ! <<<\n\n\n\
>>> Dans : [space_page - mode EDIT] doivent être : ------------------------------------------------------\n\n\
(1) les commandes qui modifient la perception de l'espace (la caméra)\n\
- son orientation (X,Y,Z),\n\
+ l'orientation (X,Y,Z) de l'état dans l'espace (six possibilités),\n\
+ le zoom,\n\
+ les paramètres qui définissent la perspective (distances oeil/écran, écran/objet virtuel) \n\n\
(2) les commandes qui modifient les apparences des objets et des situations d'intérêt\n\
(+/- transparents, colorés, etc.)\n\n\
(3) les commandes qui modifient l'apparence de l'espace (grilles, +/- surfaces, aspect des flèches, etc.)\n\n\
(4) les commandes d'édition locales (drag and drop une flèche)\n\
('faire de la place' pour insérer)\n\
(sélectionner pour déplacer ou enlever...)\n\
NB ces commandes doivent être graphiques et/ou accessibles par raccourcis ou en ligne\n\n\
(5) les commandes d'édition globales\n\
(ex: introduire, retirer, transformer +/-aléatoirement (n) objets dans l'espace)\n\n\n\
NB une action effectuée sur une zone d'intérêt devrait pouvoir être automatiquement appliquée\n\
à d'autres zones d'intérêt identifiées comme similaires\n\n\
(0) NB >>> AUCUNE COMMANDE NE DOIT PERMETTRE D'EXÉCUTER UN RUN ! <<<\n\n\n\
>>> L'objectif est que l'utilisateur ait accès à une organsisation aussi ergonomique que possible -----\n\n\
i.e : chaque utilisateur devrait disposer de 'préférences'\n\
c'est-à-dire avoir la possiblité de faire des choix ergonomiques personnalisés.\n\
";}
char *get_rules_run_edit_specif(){ return "\n\
";}

39
texts.h Normal file
View File

@ -0,0 +1,39 @@
char *get_space_run_edit_specif();
char *get_rules_run_edit_specif();
/*
>>> Dans : [space_page - mode RUN] doivent être : ------------------------------------------------------
(1) les commandes de mouvement:
- run/stop, slow down/speed up, step by step, do/undo/redo
+ le buffer [elapsed time] qui montre le temps de simulation écoulé
(2) les commandes qui modifient la perception de l'espace (la caméra)
- son orientation (X,Y,Z),
+ le zoom,
+ les paramètres qui définissent la perspective (distances oeil/écran, écran/objet virtuel)
(3) les commandes qui modifient les apparences des objets et des situations d'intérêt
(+/- transparents, colorés, etc.)
(4) les commandes qui modifient l'apparence de l'espace (grilles, +/- surfaces, aspect des flèches, etc.)
(0) NB >>> AUCUNE COMMANDE NE DOIT PERMETTRE D'ÉDITER L'ESPACE ! <<<
>>> Dans : [space_page - mode EDIT] doivent être : ------------------------------------------------------
(1) les commandes qui modifient la perception de l'espace (la caméra)
- son orientation (X,Y,Z),
+ le zoom,
+ les paramètres qui définissent la perspective (distances oeil/écran, écran/objet virtuel)
(2) les commandes qui modifient les apparences des objets et des situations d'intérêt
(+/- transparents, colorés, etc.)
(3) les commandes qui modifient l'apparence de l'espace (grilles, +/- surfaces, aspect des flèches, etc.)
(4) les commandes d'édition locales (drag and drop une flèche)
('faire de la place' pour insérer)
(sélectionner pour déplacer ou enlever...)
NB ces commandes doivent être graphiques et/ou accessibles par raccourcis ou en ligne
(5) les commandes d'édition globales
(ex: introduire, retirer, transformer +/-aléatoirement (n) objets dans l'espace)
NB une action effectuée sur une zone d'intérêt devrait pouvoir être automatiquement appliquée
à d'autres zones d'intérêt identifiées comme similaires
(0) NB >>> AUCUNE COMMANDE NE DOIT PERMETTRE D'EXÉCUTER UN RUN ! <<<
>>> L'objectif est que l'utilisateur ait accès à une organsisation aussi ergonomique que possible -----
i.e : chaque utilisateur devrait disposer de 'préférences'
c'est-à-dire avoir la possiblité de faire des choix ergonomiques personnalisés.
*/

135
tree.c Normal file
View File

@ -0,0 +1,135 @@
#include <stdio.h>
#include <gtk-4.0/gtk/gtk.h>
#include <assert.h>
#include "contain.h"
#include "texts.h"
#include "callback.h"
// https://docs.gtk.org/gtk4/visual_index.html < widgets gallery
// https://docs.gtk.org/gtk4/section-text-widget.html
// https://docs.gtk.org/gtk4/class.Widget.html#height-for-width-geometry-management
// GTK_ORIENTATION_VERTICAL GTK_ORIENTATION_HORIZONTAL
struct TreeNode_t {gchar *text; struct TreeNode_t *child, *next;};
static void add_child_node (struct TreeNode_t *parent, struct TreeNode_t *child){
if (parent->child) {
struct TreeNode_t *cur = parent->child;
while (cur && cur->next) {cur = cur->next;}
cur->next = child;
} else parent->child = child;
}
static struct TreeNode_t *create_user_tree_node (const gchar* text){
struct TreeNode_t *node = g_malloc0 (sizeof(struct TreeNode_t));
node->text = g_strdup (text);
node->child = NULL; // if (0) printf("create_user_tree_node %s\n", text);
return node;
}
static void let_us_create_a_complex_useless_and_expensive_tree (struct TreeNode_t *tree_root) {
struct TreeNode_t *a = create_user_tree_node("We, the people");add_child_node(tree_root, a);
struct TreeNode_t *b = create_user_tree_node("in Order to"); add_child_node(tree_root, b);
struct TreeNode_t *c = create_user_tree_node("do establish"); add_child_node(tree_root, c);
struct TreeNode_t *aa = create_user_tree_node("aware of"); add_child_node(a, aa);
struct TreeNode_t *aaa = create_user_tree_node("our rights"); add_child_node(aa, aaa);
struct TreeNode_t *aab = create_user_tree_node("our duties"); add_child_node(aa, aab);
struct TreeNode_t *aaaa = create_user_tree_node("read"); add_child_node(aaa, aaaa);
struct TreeNode_t *aaab = create_user_tree_node("write"); add_child_node(aaa, aaab);
struct TreeNode_t *aaac = create_user_tree_node("copy"); add_child_node(aaa, aaac);
struct TreeNode_t *aaad = create_user_tree_node("edit"); add_child_node(aaa, aaad);
struct TreeNode_t *aaaba= create_user_tree_node("code"); add_child_node(aaab, aaaba);
struct TreeNode_t *aaabb= create_user_tree_node("language"); add_child_node(aaab, aaabb);
struct TreeNode_t *aaabc= create_user_tree_node("any art..."); add_child_node(aaab, aaabc);
struct TreeNode_t *aaadb= create_user_tree_node("publish"); add_child_node(aaac, aaadb);
struct TreeNode_t *aaada= create_user_tree_node("create"); add_child_node(aaad, aaada);
struct TreeNode_t *aaba = create_user_tree_node("learn"); add_child_node(aab, aaba);
struct TreeNode_t *aabb = create_user_tree_node("help"); add_child_node(aab, aabb);
struct TreeNode_t *ba = create_user_tree_node("promote"); add_child_node(b, ba);
struct TreeNode_t *bb = create_user_tree_node("individual"); add_child_node(b, bb);
struct TreeNode_t *bc = create_user_tree_node("and common"); add_child_node(b, bc);
struct TreeNode_t *bca = create_user_tree_node("education"); add_child_node(bc, bca);
struct TreeNode_t *bcb = create_user_tree_node("mutual"); add_child_node(bc, bcb);
struct TreeNode_t *bcc = create_user_tree_node("support"); add_child_node(bc, bcc);
struct TreeNode_t *bcd = create_user_tree_node("health"); add_child_node(bc, bcd);
struct TreeNode_t *bcda = create_user_tree_node("mental"); add_child_node(bcd, bcda);
struct TreeNode_t *bcdb = create_user_tree_node("physical"); add_child_node(bcd, bcdb);
struct TreeNode_t *ca = create_user_tree_node("free"); add_child_node(c, ca);
struct TreeNode_t *cb = create_user_tree_node("code"); add_child_node(c, cb);
struct TreeNode_t *cc = create_user_tree_node("access"); add_child_node(c, cc);
}
void on_setup_user_tree_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data){
GtkWidget* expander = gtk_expander_new (NULL);
gtk_list_item_set_child (GTK_LIST_ITEM (object), expander);
if (0) printf("[on_setup_user_tree_factory] here is an expander\n");
}
static GListModel* get_user_tree_model_child (struct TreeNode_t *parent){
GtkStringList *list = NULL;
if (parent) {
if (0) printf("[get_user_tree_model_child] here is %s content : ", parent->text);
struct TreeNode_t *child = parent->child;
if (child) {list = gtk_string_list_new(NULL);}
while(child) {
gtk_string_list_append(list, child->text);
if (0) printf("%s ", child->text);
child = child->next;
}
} // else printf("hot.c GListModel* get_user_tree_model_child (struct TreeNode_t *parent) child = %d \n", parent);
if (0) printf("\n");
return G_LIST_MODEL(list);
}
GListModel* get_user_tree_model (GObject *item, gpointer root){
struct TreeNode_t *cur = (struct TreeNode_t *)root;
struct TreeNode_t *parent = root;
const gchar *string = gtk_string_object_get_string (GTK_STRING_OBJECT (item));
while (cur) {
if (strcmp(string, cur->text) == 0) break;
cur = cur->next;
if (cur == NULL) {cur = parent->child; parent = cur;}
}
if (0) printf("[get_user_user_tree_model] looked for %s in %s item\n", cur->text, string);
// ! WARNING ! TODO CUR EST L'ENFANT, MAINTENANT DONC, SI CUR EST UNE FEUILLE, JE N'ATTEINDRAI PAS SON ENFANT
return get_user_tree_model_child (cur);
}
GtkScrolledWindow *get_user_rules_tree ()
{
struct TreeNode_t *tree_root = create_user_tree_node("root");
let_us_create_a_complex_useless_and_expensive_tree (tree_root);
GtkStringList *model = gtk_string_list_new(NULL);
gtk_string_list_append (model, tree_root->text);
GtkSignalListItemFactory *factory = GTK_SIGNAL_LIST_ITEM_FACTORY (gtk_signal_list_item_factory_new());
g_signal_connect (factory, "setup", G_CALLBACK(on_setup_user_tree_factory), NULL);
g_signal_connect (factory, "bind", G_CALLBACK(on_bind_user_tree_factory), NULL);
GtkTreeListModel *tree_model = gtk_tree_list_model_new(
G_LIST_MODEL (model),
FALSE, // Passthrough - False in actual usage with dynamic children retrieval
TRUE, // FALSE, // autoexpand
(GtkTreeListModelCreateModelFunc) &get_user_tree_model,
tree_root,
NULL // (GDestroyNotify) free_user_tree_node
);
GtkSingleSelection *selection_model = gtk_single_selection_new (G_LIST_MODEL (tree_model));
gtk_single_selection_set_autoselect (selection_model, FALSE);
gtk_single_selection_set_can_unselect (selection_model, TRUE);
GtkWidget *list_view = gtk_list_view_new (GTK_SELECTION_MODEL (selection_model), GTK_LIST_ITEM_FACTORY (factory));
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new());
// Allocation height too small. Tried to allocate 1922x1030, but GtkNotebook 0x25cd4c0 needs at least 1922x1064.
// even if I remove (comment) the next line :
gtk_scrolled_window_set_child (scrolled_window, list_view);
gtk_scrolled_window_set_policy (scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (GTK_WIDGET (scrolled_window), TRUE);
gtk_widget_set_visible (GTK_WIDGET (scrolled_window), TRUE);
gtk_widget_set_visible (GTK_WIDGET (list_view), TRUE);
return scrolled_window;
}

40
tree.h Normal file
View File

@ -0,0 +1,40 @@
/******************************************************************************/
/* */
/* E coli by David S. Goodsell (2009) */
/* --- */
/* Let this freeze frame guide us towards the model */
/* that alone can account for the phenomenon ! */
/* */
/******************************************************************************/
#pragma once // < WTF !?
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib-2.0/glib.h>
#include <gtk-4.0/gtk/gtk.h>
//#include "cold.h"
#include "display.h"
#include "contain.h"
// https://blog.gtk.org/2020/09/08/on-list-models/ < TODO
GtkScrolledWindow *get_user_rules_tree ();
void set_run_edit_mode(int prescribed_mode);
int get_run_edit_mode();
GListModel* get_user_tree_model (GObject *item, gpointer root);
void on_setup_user_tree_factory (GtkSignalListItemFactory *factory,
GObject* object, gpointer user_data);