Color selection working! Palette is next.
This commit is contained in:
parent
999d0a6f6a
commit
511bf72427
4 changed files with 244 additions and 66 deletions
|
@ -26,6 +26,8 @@ project(joeydev C)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
|
thirdparty/memwatch/memwatch.c
|
||||||
|
ui/generated/resources.c
|
||||||
src/main.c
|
src/main.c
|
||||||
src/utils.c
|
src/utils.c
|
||||||
src/joeydev.c
|
src/joeydev.c
|
||||||
|
@ -34,8 +36,7 @@ set(SOURCE_FILES
|
||||||
src/draw.c
|
src/draw.c
|
||||||
src/image.c
|
src/image.c
|
||||||
src/vecparse.c
|
src/vecparse.c
|
||||||
ui/generated/resources.c
|
src/color.c
|
||||||
thirdparty/memwatch/memwatch.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES})
|
add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES})
|
||||||
|
|
137
src/color.c
Normal file
137
src/color.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* JoeyDev
|
||||||
|
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ColorDialogDataS {
|
||||||
|
GtkWidget *buttons[16];
|
||||||
|
int selected;
|
||||||
|
} ColorDialogDataT;
|
||||||
|
|
||||||
|
|
||||||
|
static void addCss(GtkWidget *widget, char *css);
|
||||||
|
EVENT void colorClicked(GtkButton *widget, gpointer userData);
|
||||||
|
EVENT gboolean colorDialogClose(GtkWidget *object, GdkEvent *event, gpointer userData);
|
||||||
|
|
||||||
|
|
||||||
|
static void addCss(GtkWidget *widget, char *css) {
|
||||||
|
GtkCssProvider *provider;
|
||||||
|
GtkStyleContext *context;
|
||||||
|
|
||||||
|
provider = gtk_css_provider_new();
|
||||||
|
gtk_css_provider_load_from_data(provider, css, -1,NULL);
|
||||||
|
context = gtk_widget_get_style_context(widget);
|
||||||
|
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider),GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||||
|
g_object_unref(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EVENT void colorClicked(GtkButton *widget, gpointer userData) {
|
||||||
|
ColorDialogDataT *self = (ColorDialogDataT *)userData;
|
||||||
|
int i;
|
||||||
|
char *borderOn = "* { border-width: 3px; border-color: white; }";
|
||||||
|
char *borderOff = "* { border-width: 0px; }";
|
||||||
|
|
||||||
|
for (i=0; i<16; i++) {
|
||||||
|
if (widget == GTK_BUTTON(self->buttons[i])) {
|
||||||
|
if (self->selected >= 0) {
|
||||||
|
addCss(self->buttons[self->selected], borderOff);
|
||||||
|
}
|
||||||
|
self->selected = i;
|
||||||
|
addCss(self->buttons[self->selected], borderOn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EVENT gboolean colorDialogClose(GtkWidget *object, GdkEvent *event, gpointer userData) {
|
||||||
|
ColorDialogDataT *self = g_object_get_data(G_OBJECT(object), "colorData");
|
||||||
|
|
||||||
|
(void)event;
|
||||||
|
(void)userData;
|
||||||
|
|
||||||
|
DEL(self);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int color_dialog_get_selected(GtkWidget *colorDialog) {
|
||||||
|
ColorDialogDataT *self = g_object_get_data(G_OBJECT(colorDialog), "colorData");
|
||||||
|
|
||||||
|
return self->selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GtkWidget *color_dialog_new(GtkWidget *parent, ColorT colors[]) {
|
||||||
|
GtkWidget *dialog;
|
||||||
|
GtkWidget *contentArea;
|
||||||
|
GtkWidget *grid;
|
||||||
|
char temp[256];
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int i;
|
||||||
|
ColorDialogDataT *self;
|
||||||
|
|
||||||
|
self = NEW(ColorDialogDataT);
|
||||||
|
self->selected = -1;
|
||||||
|
|
||||||
|
grid = gtk_grid_new();
|
||||||
|
gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
|
||||||
|
gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
|
||||||
|
i = 0;
|
||||||
|
for (y=0; y<4; y++) {
|
||||||
|
for (x=0; x<4; x++) {
|
||||||
|
self->buttons[i] = gtk_button_new();
|
||||||
|
gtk_widget_set_hexpand(self->buttons[i], TRUE);
|
||||||
|
gtk_widget_set_vexpand(self->buttons[i], TRUE);
|
||||||
|
g_signal_connect(G_OBJECT(self->buttons[i]), "clicked", G_CALLBACK(colorClicked), self);
|
||||||
|
snprintf(temp, 256, "* { background-image:none; background-color: #%02x%02x%02x; }", colors[i].red, colors[i].green, colors[i].blue);
|
||||||
|
addCss(self->buttons[i], temp);
|
||||||
|
gtk_grid_attach(GTK_GRID (grid), self->buttons[i], x, y, 1, 1);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog = gtk_dialog_new_with_buttons("Color",
|
||||||
|
GTK_WINDOW(parent),
|
||||||
|
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||||
|
"_Cancel",
|
||||||
|
GTK_RESPONSE_CANCEL,
|
||||||
|
"_Select",
|
||||||
|
GTK_RESPONSE_OK,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(colorDialogClose), self);
|
||||||
|
g_object_set_data(G_OBJECT(dialog), "colorData", self);
|
||||||
|
gtk_widget_set_size_request(dialog, 320, 320);
|
||||||
|
contentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||||
|
gtk_container_add(GTK_CONTAINER(contentArea), grid);
|
||||||
|
|
||||||
|
gtk_widget_show_all(dialog);
|
||||||
|
|
||||||
|
return dialog;
|
||||||
|
}
|
41
src/color.h
Normal file
41
src/color.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* JoeyDev
|
||||||
|
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef COLOR_H
|
||||||
|
#define COLOR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ColorS {
|
||||||
|
unsigned char red;
|
||||||
|
unsigned char green;
|
||||||
|
unsigned char blue;
|
||||||
|
} ColorT;
|
||||||
|
|
||||||
|
|
||||||
|
int color_dialog_get_selected(GtkWidget *colorDialog);
|
||||||
|
GtkWidget *color_dialog_new(GtkWidget *parent, ColorT colors[]);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COLOR_H
|
87
src/vector.c
87
src/vector.c
|
@ -34,6 +34,7 @@
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "vecparse.h"
|
#include "vecparse.h"
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
|
||||||
#define VICTOR_VERSION "1.00"
|
#define VICTOR_VERSION "1.00"
|
||||||
|
@ -105,6 +106,7 @@ EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer use
|
||||||
EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *event, gpointer userData);
|
EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *event, gpointer userData);
|
||||||
EVENT void editorVectorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData);
|
EVENT void editorVectorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData);
|
||||||
EVENT void fileVectorTraceImageFileSet(GtkWidget *object, gpointer userData);
|
EVENT void fileVectorTraceImageFileSet(GtkWidget *object, gpointer userData);
|
||||||
|
static int findClosestPoint(VectorDataT *self, int x, int y);
|
||||||
static int getWord(VecByteCodeT *bytecode, int *index);
|
static int getWord(VecByteCodeT *bytecode, int *index);
|
||||||
static void insertCommand(VectorDataT *self, char *command);
|
static void insertCommand(VectorDataT *self, char *command);
|
||||||
static void insertText(VectorDataT *self, char *text);
|
static void insertText(VectorDataT *self, char *text);
|
||||||
|
@ -181,7 +183,8 @@ EVENT void drawVectorImageClick(GtkWidget *object, GdkEventButton *event, gpoint
|
||||||
|
|
||||||
switch (self->clickState) {
|
switch (self->clickState) {
|
||||||
case CLICK_NONE:
|
case CLICK_NONE:
|
||||||
// Do nothing.
|
// Highlight the closest point in editor.
|
||||||
|
findClosestPoint(self, x, y);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLICK_BOX_1:
|
case CLICK_BOX_1:
|
||||||
|
@ -340,12 +343,9 @@ EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer user
|
||||||
|
|
||||||
EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *event, gpointer userData) {
|
EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *event, gpointer userData) {
|
||||||
VectorDataT *self = (VectorDataT *)userData;
|
VectorDataT *self = (VectorDataT *)userData;
|
||||||
int closest = -1;
|
|
||||||
int distance = INT_MAX;
|
|
||||||
int x = (int)(event->x * 0.5);
|
int x = (int)(event->x * 0.5);
|
||||||
int y = (int)(event->y * 0.5);
|
int y = (int)(event->y * 0.5);
|
||||||
int temp;
|
int temp;
|
||||||
int i;
|
|
||||||
char buffer[8];
|
char buffer[8];
|
||||||
|
|
||||||
// If we're in a drawing action, bail out of this.
|
// If we're in a drawing action, bail out of this.
|
||||||
|
@ -354,26 +354,9 @@ EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *eve
|
||||||
// If they're holding the button down, update the point.
|
// If they're holding the button down, update the point.
|
||||||
if (event->state & GDK_BUTTON1_MASK) {
|
if (event->state & GDK_BUTTON1_MASK) {
|
||||||
|
|
||||||
// Find closest point to mouse pointer.
|
|
||||||
for (i = 0; i < arrlen(self->pointList); i++) {
|
|
||||||
temp = sqrt(pow(x - self->pointList[i]->x, 2) + pow(y - self->pointList[i]->y, 2));
|
|
||||||
if (temp < distance) {
|
|
||||||
closest = i;
|
|
||||||
distance = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did we find a point to edit?
|
|
||||||
if (closest >= 0) {
|
|
||||||
// Select first occurrence of it in the text editor.
|
|
||||||
snprintf(buffer, 8, "%d,%d", self->pointList[closest]->x, self->pointList[closest]->y);
|
|
||||||
SSM(SCI_TARGETWHOLEDOCUMENT, 0, 0);
|
|
||||||
SSM(SCI_SETSEARCHFLAGS, SCFIND_NONE, 0);
|
|
||||||
temp = SSM(SCI_SEARCHINTARGET, strlen(buffer), (sptr_t)buffer);
|
|
||||||
// Did we find it in the text?
|
// Did we find it in the text?
|
||||||
|
temp = findClosestPoint(self, x, y);
|
||||||
if (temp >= 0) {
|
if (temp >= 0) {
|
||||||
// Select the text.
|
|
||||||
SSM(SCI_SETSEL, temp, temp + strlen(buffer));
|
|
||||||
// Are these values sane?
|
// Are these values sane?
|
||||||
if (x < 0) x = 0;
|
if (x < 0) x = 0;
|
||||||
if (x > 319) x = 319;
|
if (x > 319) x = 319;
|
||||||
|
@ -383,7 +366,6 @@ EVENT gboolean drawVectorImageMotionEvent(GtkWidget *widget, GdkEventMotion *eve
|
||||||
SSM(SCI_REPLACETARGET, -1, (sptr_t)buffer);
|
SSM(SCI_REPLACETARGET, -1, (sptr_t)buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -465,6 +447,37 @@ EVENT void fileVectorTraceImageFileSet(GtkWidget *object, gpointer userData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int findClosestPoint(VectorDataT *self, int x, int y) {
|
||||||
|
int closest = -1;
|
||||||
|
int distance = INT_MAX;
|
||||||
|
int temp;
|
||||||
|
int i;
|
||||||
|
char buffer[8];
|
||||||
|
|
||||||
|
// Find closest point to mouse pointer.
|
||||||
|
for (i = 0; i < arrlen(self->pointList); i++) {
|
||||||
|
temp = sqrt(pow(x - self->pointList[i]->x, 2) + pow(y - self->pointList[i]->y, 2));
|
||||||
|
if (temp < distance) {
|
||||||
|
closest = i;
|
||||||
|
distance = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we find a point to edit?
|
||||||
|
if (closest >= 0) {
|
||||||
|
// Find first occurrence of it in the text editor.
|
||||||
|
snprintf(buffer, 8, "%d,%d", self->pointList[closest]->x, self->pointList[closest]->y);
|
||||||
|
SSM(SCI_TARGETWHOLEDOCUMENT, 0, 0);
|
||||||
|
SSM(SCI_SETSEARCHFLAGS, SCFIND_NONE, 0);
|
||||||
|
temp = SSM(SCI_SEARCHINTARGET, strlen(buffer), (sptr_t)buffer);
|
||||||
|
// Select the text.
|
||||||
|
SSM(SCI_SETSEL, temp, temp + strlen(buffer));
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int getWord(VecByteCodeT *bytecode, int *index) {
|
static int getWord(VecByteCodeT *bytecode, int *index) {
|
||||||
int word;
|
int word;
|
||||||
|
|
||||||
|
@ -1240,44 +1253,30 @@ EVENT void toolCircleClicked(GtkToolButton *object, gpointer userData) {
|
||||||
EVENT void toolColorClicked(GtkToolButton *object, gpointer userData) {
|
EVENT void toolColorClicked(GtkToolButton *object, gpointer userData) {
|
||||||
VectorDataT *self = (VectorDataT *)userData;
|
VectorDataT *self = (VectorDataT *)userData;
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GdkRGBA colors[16];
|
ColorT colors[16];
|
||||||
GdkRGBA selected;
|
|
||||||
char temp[4];
|
char temp[4];
|
||||||
int i;
|
int i;
|
||||||
unsigned char r;
|
|
||||||
unsigned char g;
|
|
||||||
unsigned char b;
|
|
||||||
double scale = 1.0/256.0;
|
|
||||||
|
|
||||||
(void)object;
|
(void)object;
|
||||||
|
|
||||||
// Load the current JoeyLib palette into the dialog.
|
// Load the current JoeyLib palette into the dialog.
|
||||||
for (i=0; i<16; i++) {
|
for (i=0; i<16; i++) {
|
||||||
jlPaletteGet(self->jlc, i, &r, &g, &b);
|
jlPaletteGet(self->jlc, i, &colors[i].red, &colors[i].green, &colors[i].blue);
|
||||||
colors[i].alpha = 1.0;
|
|
||||||
colors[i].red = (double)r * scale;
|
|
||||||
colors[i].green = (double)g * scale;
|
|
||||||
colors[i].blue = (double)b * scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the dialog.
|
// Build the dialog.
|
||||||
dialog = gtk_color_chooser_dialog_new("Color", GTK_WINDOW(self->windowData.window));
|
dialog = color_dialog_new(self->windowData.window, colors);
|
||||||
g_object_set (dialog, "show-editor", FALSE, NULL);
|
|
||||||
gtk_color_chooser_add_palette(GTK_COLOR_CHOOSER(dialog), GTK_ORIENTATION_HORIZONTAL, 4, 16, colors);
|
|
||||||
|
|
||||||
// Run the dialog.
|
// Run the dialog.
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL) {
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
|
||||||
// Figure out which color index they selected.
|
i = color_dialog_get_selected(dialog);
|
||||||
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &selected);
|
if (i >= 0) {
|
||||||
for (i=0; i<16; i++) {
|
|
||||||
if (colors[i].red == selected.red && colors[i].green == selected.green && colors[i].blue == selected.blue) {
|
|
||||||
// Write our selected color into the editor.
|
// Write our selected color into the editor.
|
||||||
snprintf(temp, 4, " %d", i);
|
snprintf(temp, 4, " %d", i);
|
||||||
insertCommand(self, "COLOR");
|
insertCommand(self, "color");
|
||||||
insertText(self, temp);
|
insertText(self, temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue