mirror of
https://github.com/jtheoof/swappy.git
synced 2024-11-12 18:48:15 +03:00
add: crosshair support
This commit is contained in:
parent
0b3e95a7cd
commit
243f201ec0
149
application.c
149
application.c
@ -26,17 +26,19 @@ static void tools_menu_button_clear_clicked_handler(
|
||||
static void tools_menu_button_brush_toggle_handler(GtkToggleButton *source,
|
||||
struct swappy_state *state) {
|
||||
printf("brush toggled: %d\n", gtk_toggle_button_get_active(source));
|
||||
bool is_active = gtk_toggle_button_get_active(source) == 1;
|
||||
state->is_mode_brush = is_active;
|
||||
state->is_mode_text = !is_active;
|
||||
state->mode = SWAPPY_PAINT_MODE_BRUSH;
|
||||
}
|
||||
|
||||
static void tools_menu_button_text_toggle_handler(GtkToggleButton *source,
|
||||
struct swappy_state *state) {
|
||||
printf("text toggled: %d\n", gtk_toggle_button_get_active(source));
|
||||
bool is_active = gtk_toggle_button_get_active(source) == 1;
|
||||
state->is_mode_brush = !is_active;
|
||||
state->is_mode_text = is_active;
|
||||
state->mode = SWAPPY_PAINT_MODE_TEXT;
|
||||
}
|
||||
|
||||
static void tools_menu_button_shape_toggle_handler(GtkToggleButton *source,
|
||||
struct swappy_state *state) {
|
||||
printf("shape toggled: %d\n", gtk_toggle_button_get_active(source));
|
||||
state->mode = SWAPPY_PAINT_MODE_RECTANGLE;
|
||||
}
|
||||
|
||||
static gboolean keypress_handler(GtkWidget *widget, GdkEventKey *event,
|
||||
@ -123,7 +125,11 @@ static void brush_add_point(struct swappy_state *state, double x, double y,
|
||||
static void draw_area_button_press_handler(GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
struct swappy_state *state) {
|
||||
if (state->is_mode_brush) {
|
||||
if (!(event->state & GDK_BUTTON1_MASK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->mode == SWAPPY_PAINT_MODE_BRUSH) {
|
||||
brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_FIRST);
|
||||
gtk_widget_queue_draw(state->area);
|
||||
}
|
||||
@ -132,7 +138,11 @@ static void draw_area_button_press_handler(GtkWidget *widget,
|
||||
static void draw_area_button_release_handler(GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
struct swappy_state *state) {
|
||||
if (state->is_mode_brush) {
|
||||
if (!(event->state & GDK_BUTTON1_MASK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->mode == SWAPPY_PAINT_MODE_BRUSH) {
|
||||
brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_LAST);
|
||||
gtk_widget_queue_draw(state->area);
|
||||
}
|
||||
@ -141,81 +151,32 @@ static void draw_area_button_release_handler(GtkWidget *widget,
|
||||
static void draw_area_motion_notify_handler(GtkWidget *widget,
|
||||
GdkEventMotion *event,
|
||||
struct swappy_state *state) {
|
||||
if (state->is_mode_brush) {
|
||||
brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_WITHIN);
|
||||
gtk_widget_queue_draw(state->area);
|
||||
GdkDisplay *display = gdk_display_get_default();
|
||||
GdkWindow *window = event->window;
|
||||
|
||||
if (state->mode == SWAPPY_PAINT_MODE_BRUSH) {
|
||||
GdkCursor *crosshair = gdk_cursor_new_for_display(display, GDK_CROSSHAIR);
|
||||
gdk_window_set_cursor(window, crosshair);
|
||||
|
||||
if (event->state & GDK_BUTTON1_MASK) {
|
||||
brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_WITHIN);
|
||||
gtk_widget_queue_draw(state->area);
|
||||
}
|
||||
} else {
|
||||
gdk_window_set_cursor(window, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void build_layout_drawing_area(struct swappy_state *state,
|
||||
GtkWidget *parent) {
|
||||
GtkWidget *area = gtk_drawing_area_new();
|
||||
state->area = area;
|
||||
|
||||
gtk_widget_set_size_request(area, state->width, state->height);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(parent), area);
|
||||
gtk_widget_add_events(area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK);
|
||||
|
||||
g_signal_connect(G_OBJECT(area), "draw", G_CALLBACK(draw_area_handler),
|
||||
state);
|
||||
g_signal_connect(G_OBJECT(area), "button-press-event",
|
||||
G_CALLBACK(draw_area_button_press_handler), state);
|
||||
g_signal_connect(G_OBJECT(area), "button-release-event",
|
||||
G_CALLBACK(draw_area_button_release_handler), state);
|
||||
g_signal_connect(G_OBJECT(area), "motion-notify-event",
|
||||
G_CALLBACK(draw_area_motion_notify_handler), state);
|
||||
}
|
||||
|
||||
static void build_layout_tools_menu(struct swappy_state *state,
|
||||
GtkWidget *parent) {
|
||||
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
|
||||
GtkWidget *brush = gtk_radio_button_new_with_label(NULL, "Brush");
|
||||
GtkWidget *text = gtk_radio_button_new_with_label_from_widget(
|
||||
GTK_RADIO_BUTTON(brush), "Text");
|
||||
GtkWidget *clear = gtk_button_new_with_label("Reset");
|
||||
|
||||
gtk_box_set_homogeneous(GTK_BOX(box), TRUE);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(box), brush);
|
||||
gtk_container_add(GTK_CONTAINER(box), text);
|
||||
gtk_container_add(GTK_CONTAINER(box), clear);
|
||||
gtk_container_add(GTK_CONTAINER(parent), box);
|
||||
|
||||
g_signal_connect(brush, "toggled",
|
||||
G_CALLBACK(tools_menu_button_brush_toggle_handler), state);
|
||||
g_signal_connect(text, "toggled",
|
||||
G_CALLBACK(tools_menu_button_text_toggle_handler), state);
|
||||
g_signal_connect(clear, "clicked",
|
||||
G_CALLBACK(tools_menu_button_clear_clicked_handler), state);
|
||||
}
|
||||
|
||||
static void build_layout(struct swappy_state *state) {
|
||||
return;
|
||||
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
|
||||
build_layout_tools_menu(state, vbox);
|
||||
build_layout_drawing_area(state, vbox);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(state->window), vbox);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(state->window), 2);
|
||||
|
||||
g_signal_connect(G_OBJECT(state->window), "key_press_event",
|
||||
G_CALLBACK(keypress_handler), state);
|
||||
|
||||
gtk_widget_show_all(GTK_WIDGET(state->window));
|
||||
}
|
||||
|
||||
static void print_hello(GtkWidget *widget, gpointer data) {
|
||||
g_print("Hello World\n");
|
||||
}
|
||||
|
||||
static bool build_ui(struct swappy_state *state) {
|
||||
GtkBuilder *builder;
|
||||
GObject *container;
|
||||
GObject *button;
|
||||
GObject *brush;
|
||||
GObject *text;
|
||||
GObject *shape;
|
||||
GtkWidget *area;
|
||||
GObject *clear;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Construct a GtkBuilder instance and load our UI description */
|
||||
builder = gtk_builder_new();
|
||||
if (gtk_builder_add_from_file(builder, "swappy.ui", &error) == 0) {
|
||||
@ -226,21 +187,38 @@ static bool build_ui(struct swappy_state *state) {
|
||||
|
||||
/* Connect signal handlers to the constructed widgets. */
|
||||
container = gtk_builder_get_object(builder, "container");
|
||||
brush = gtk_builder_get_object(builder, "brush");
|
||||
text = gtk_builder_get_object(builder, "text");
|
||||
shape = gtk_builder_get_object(builder, "shape");
|
||||
clear = gtk_builder_get_object(builder, "clear");
|
||||
area = GTK_WIDGET(gtk_builder_get_object(builder, "paint_area"));
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(state->window), GTK_WIDGET(container));
|
||||
|
||||
g_signal_connect(G_OBJECT(state->window), "key_press_event",
|
||||
G_CALLBACK(keypress_handler), state);
|
||||
g_signal_connect(brush, "toggled",
|
||||
G_CALLBACK(tools_menu_button_brush_toggle_handler), state);
|
||||
g_signal_connect(text, "toggled",
|
||||
G_CALLBACK(tools_menu_button_text_toggle_handler), state);
|
||||
g_signal_connect(shape, "toggled",
|
||||
G_CALLBACK(tools_menu_button_shape_toggle_handler), state);
|
||||
g_signal_connect(clear, "clicked",
|
||||
G_CALLBACK(tools_menu_button_clear_clicked_handler), state);
|
||||
|
||||
button = gtk_builder_get_object(builder, "button1");
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(print_hello), NULL);
|
||||
|
||||
button = gtk_builder_get_object(builder, "button2");
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(print_hello), NULL);
|
||||
|
||||
button = gtk_builder_get_object(builder, "quit");
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(gtk_main_quit), NULL);
|
||||
gtk_widget_set_size_request(area, state->width, state->height);
|
||||
gtk_widget_add_events(area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK);
|
||||
g_signal_connect(area, "draw", G_CALLBACK(draw_area_handler), state);
|
||||
g_signal_connect(area, "button-press-event",
|
||||
G_CALLBACK(draw_area_button_press_handler), state);
|
||||
g_signal_connect(area, "button-release-event",
|
||||
G_CALLBACK(draw_area_button_release_handler), state);
|
||||
g_signal_connect(area, "motion-notify-event",
|
||||
G_CALLBACK(draw_area_motion_notify_handler), state);
|
||||
|
||||
state->area = area;
|
||||
gtk_widget_show_all(GTK_WIDGET(state->window));
|
||||
|
||||
return true;
|
||||
@ -249,7 +227,7 @@ static bool build_ui(struct swappy_state *state) {
|
||||
static void application_activate(GtkApplication *app, void *data) {
|
||||
struct swappy_state *state = data;
|
||||
|
||||
// Create a normal GTK window however you like
|
||||
// Create a normal GTK vbox however you like
|
||||
GtkWindow *window = GTK_WINDOW(gtk_application_window_new(app));
|
||||
state->window = window;
|
||||
|
||||
@ -276,7 +254,6 @@ static void application_activate(GtkApplication *app, void *data) {
|
||||
|
||||
printf("window has sizes %dx%d\n", state->width, state->height);
|
||||
|
||||
build_layout(state);
|
||||
build_ui(state);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,12 @@ enum swappy_brush_point_kind {
|
||||
SWAPPY_BRUSH_POINT_LAST, /* A point at the end of brush batch */
|
||||
};
|
||||
|
||||
enum swappy_paint_mode_type {
|
||||
SWAPPY_PAINT_MODE_BRUSH = 0, /* Brush mode to draw arbitrary shapes */
|
||||
SWAPPY_PAINT_MODE_TEXT, /* Mode to draw texts */
|
||||
SWAPPY_PAINT_MODE_RECTANGLE, /* Rectangle shapes */
|
||||
};
|
||||
|
||||
struct swappy_brush_point {
|
||||
double x;
|
||||
double y;
|
||||
@ -40,8 +46,8 @@ struct swappy_state {
|
||||
struct zwlr_layer_surface_v1 *layer_surface;
|
||||
|
||||
bool should_exit;
|
||||
bool is_mode_brush;
|
||||
bool is_mode_text;
|
||||
|
||||
enum swappy_paint_mode_type mode;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
2
main.c
2
main.c
@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
state.argc = argc;
|
||||
state.argv = argv;
|
||||
state.is_mode_brush = true;
|
||||
state.mode = SWAPPY_PAINT_MODE_BRUSH;
|
||||
|
||||
sprintf(state.image, "%s", "/home/jattali/Desktop/sway.png");
|
||||
|
||||
|
147
swappy.ui
Normal file
147
swappy.ui
Normal file
@ -0,0 +1,147 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.0"/>
|
||||
<object class="GtkBox" id="container">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="container_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="paint_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="brush">
|
||||
<property name="label" translatable="yes">Brush</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">text</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="text">
|
||||
<property name="label" translatable="yes">Text</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">brush</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="shape">
|
||||
<property name="label" translatable="yes">Shape</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">brush</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="control_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="copy">
|
||||
<property name="label" translatable="yes">Copy</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="save">
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="clear">
|
||||
<property name="label" translatable="yes">Clear</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="paint_area">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
Loading…
Reference in New Issue
Block a user