Skip to content

Commit 0416812

Browse files
authored
feat(ui): add transparency feature
* feat(ui): add transparency feature It is sometimes better if the drawing is not fully covering the picture but is semi-transparent. This patch adds a simple button to enable transparency. When this button is enabled, everything will be drawn with 50% alpha channel. * feat(ui): make transparency configurable This commit adds UI elements and config option for configuring the transparency value. The default value is 50% but it can be changed in the 5% - 95% range in 10% steps. * docs(readme): update README with transparency feature The previous commit added this info to the man page but README was not updated. Lets fix this.
1 parent 489c3ef commit 0416812

File tree

17 files changed

+409
-81
lines changed

17 files changed

+409
-81
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ early_exit=false
5353
fill_shape=false
5454
auto_save=false
5555
custom_color=rgba(193,125,17,1)
56+
transparent=false
57+
transparency=50
5658
```
5759

5860
- `save_dir` is where swappshots will be saved, can contain env variables, when it does not exist, swappy attempts to create it first, but does not abort if directory creation fails
@@ -66,6 +68,8 @@ custom_color=rgba(193,125,17,1)
6668
- `fill_shape` is used to toggle shape filling (for the rectangle and ellipsis tools) on or off upon startup
6769
- `auto_save` is used to toggle auto saving of final buffer to `save_dir` upon exit
6870
- `custom_color` is used to set a default value for the custom color
71+
- `transparency` is used to set transparency of everything that is drawn during startup
72+
- `transparent` is used to toggle transparency during startup
6973

7074

7175
## Keyboard Shortcuts
@@ -91,6 +95,7 @@ custom_color=rgba(193,125,17,1)
9195
- `Plus`: Increase Stroke Size
9296
- `Equal`: Reset Stroke Size
9397
- `f`: Toggle Shape Filling
98+
- `T`: Toggle Transparency
9499
- `k`: Clear Paints (cannot be undone)
95100

96101
<hr>

include/application.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,9 @@ void stroke_size_increase_handler(GtkWidget *widget,
5757
void text_size_decrease_handler(GtkWidget *widget, struct swappy_state *state);
5858
void text_size_reset_handler(GtkWidget *widget, struct swappy_state *state);
5959
void text_size_increase_handler(GtkWidget *widget, struct swappy_state *state);
60+
61+
void transparency_decrease_handler(GtkWidget *widget,
62+
struct swappy_state *state);
63+
void transparency_reset_handler(GtkWidget *widget, struct swappy_state *state);
64+
void transparency_increase_handler(GtkWidget *widget,
65+
struct swappy_state *state);

include/config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
#define CONFIG_LINE_SIZE_DEFAULT 5
44
#define CONFIG_TEXT_FONT_DEFAULT "sans-serif"
55
#define CONFIG_TEXT_SIZE_DEFAULT 20
6+
#define CONFIG_TRANSPARENCY_DEFAULT 50
67
#define CONFIG_SHOW_PANEL_DEFAULT false
78
#define CONFIG_SAVE_FILENAME_FORMAT_DEFAULT "swappy-%Y%m%d_%H%M%S.png"
89
#define CONFIG_PAINT_MODE_DEFAULT SWAPPY_PAINT_MODE_BRUSH
910
#define CONFIG_EARLY_EXIT_DEFAULT false
1011
#define CONFIG_FILL_SHAPE_DEFAULT false
1112
#define CONFIG_AUTO_SAVE_DEFAULT false
1213
#define CONFIG_CUSTOM_COLOR_DEFAULT "rgba(193,125,17,1)"
14+
#define CONFIG_TRANSPARENT_DEFAULT false
1315

1416
void config_load(struct swappy_state *state);
1517
void config_free(struct swappy_state *state);

include/swappy.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#define SWAPPY_TEXT_SIZE_MIN 10
1515
#define SWAPPY_TEXT_SIZE_MAX 50
1616

17+
#define SWAPPY_TRANSPARENCY_MIN 5
18+
#define SWAPPY_TRANSPARENCY_MAX 95
19+
1720
enum swappy_paint_type {
1821
SWAPPY_PAINT_MODE_BRUSH = 0, /* Brush mode to draw arbitrary shapes */
1922
SWAPPY_PAINT_MODE_TEXT, /* Mode to draw texts */
@@ -106,6 +109,7 @@ struct swappy_state_settings {
106109
double a;
107110
double w;
108111
double t;
112+
int32_t tr;
109113
};
110114

111115
struct swappy_state_ui {
@@ -137,8 +141,12 @@ struct swappy_state_ui {
137141

138142
GtkButton *line_size;
139143
GtkButton *text_size;
144+
GtkButton *transparency;
145+
GtkButton *transparency_plus;
146+
GtkButton *transparency_minus;
140147

141148
GtkToggleButton *fill_shape;
149+
GtkToggleButton *transparent;
142150
};
143151

144152
struct swappy_config {
@@ -147,9 +155,11 @@ struct swappy_config {
147155
char *save_filename_format;
148156
gint8 paint_mode;
149157
gboolean fill_shape;
158+
gboolean transparent;
150159
gboolean show_panel;
151160
guint32 line_size;
152161
guint32 text_size;
162+
guint32 transparency;
153163
char *text_font;
154164
gboolean early_exit;
155165
gboolean auto_save;

res/swappy.glade

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@
5757
<property name="can_focus">False</property>
5858
<property name="icon_name">zoom-out-symbolic</property>
5959
</object>
60+
<object class="GtkImage" id="zoom-out2">
61+
<property name="visible">True</property>
62+
<property name="can_focus">False</property>
63+
<property name="icon_name">zoom-out-symbolic</property>
64+
</object>
6065
<object class="GtkApplicationWindow" id="paint-window">
6166
<property name="visible">True</property>
6267
<property name="can_focus">False</property>
@@ -582,6 +587,76 @@
582587
<property name="position">4</property>
583588
</packing>
584589
</child>
590+
<child>
591+
<object class="GtkBox">
592+
<property name="visible">True</property>
593+
<property name="can-focus">False</property>
594+
<property name="margin-bottom">10</property>
595+
<property name="spacing">2</property>
596+
<property name="homogeneous">True</property>
597+
<child>
598+
<object class="GtkLabel">
599+
<property name="visible">True</property>
600+
<property name="can-focus">False</property>
601+
<property name="label" translatable="yes">Transparency</property>
602+
</object>
603+
<packing>
604+
<property name="expand">False</property>
605+
<property name="fill">True</property>
606+
<property name="position">0</property>
607+
</packing>
608+
</child>
609+
<child>
610+
<object class="GtkButton" id="transparency-minus-button">
611+
<property name="visible">True</property>
612+
<property name="can-focus">True</property>
613+
<property name="receives-default">True</property>
614+
<property name="image">zoom-out2</property>
615+
<property name="always-show-image">True</property>
616+
<signal name="clicked" handler="transparency_decrease_handler" swapped="no"/>
617+
</object>
618+
<packing>
619+
<property name="expand">False</property>
620+
<property name="fill">False</property>
621+
<property name="position">1</property>
622+
</packing>
623+
</child>
624+
<child>
625+
<object class="GtkButton" id="transparency-button">
626+
<property name="visible">True</property>
627+
<property name="can-focus">True</property>
628+
<property name="receives-default">True</property>
629+
<property name="always-show-image">True</property>
630+
<signal name="clicked" handler="transparency_reset_handler" swapped="no"/>
631+
</object>
632+
<packing>
633+
<property name="expand">False</property>
634+
<property name="fill">True</property>
635+
<property name="position">2</property>
636+
</packing>
637+
</child>
638+
<child>
639+
<object class="GtkButton" id="transparency-plus-button">
640+
<property name="visible">True</property>
641+
<property name="can-focus">True</property>
642+
<property name="receives-default">True</property>
643+
<property name="image">zoom-in2</property>
644+
<property name="always-show-image">True</property>
645+
<signal name="clicked" handler="transparency_increase_handler" swapped="no"/>
646+
</object>
647+
<packing>
648+
<property name="expand">False</property>
649+
<property name="fill">False</property>
650+
<property name="position">3</property>
651+
</packing>
652+
</child>
653+
</object>
654+
<packing>
655+
<property name="expand">False</property>
656+
<property name="fill">True</property>
657+
<property name="position">5</property>
658+
</packing>
659+
</child>
585660
<child>
586661
<object class="GtkBox">
587662
<property name="visible">True</property>
@@ -604,11 +679,28 @@
604679
<property name="position">1</property>
605680
</packing>
606681
</child>
682+
<child>
683+
<object class="GtkToggleButton" id="transparent-toggle-button">
684+
<property name="label" translatable="yes">Transparent</property>
685+
<property name="visible">True</property>
686+
<property name="can-focus">False</property>
687+
<property name="focus-on-click">False</property>
688+
<property name="receives-default">True</property>
689+
<property name="tooltip-text" translatable="yes">Toggle transparency</property>
690+
<property name="always-show-image">True</property>
691+
<signal name="toggled" handler="transparent_toggled_handler" swapped="no"/>
692+
</object>
693+
<packing>
694+
<property name="expand">False</property>
695+
<property name="fill">True</property>
696+
<property name="position">2</property>
697+
</packing>
698+
</child>
607699
</object>
608700
<packing>
609701
<property name="expand">False</property>
610702
<property name="fill">True</property>
611-
<property name="position">5</property>
703+
<property name="position">6</property>
612704
</packing>
613705
</child>
614706
</object>

src/application.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <glib-2.0/glib.h>
33
#include <glib/gstdio.h>
44
#include <gtk/gtk.h>
5+
#include <inttypes.h>
56
#include <stdio.h>
67
#include <time.h>
78

@@ -36,6 +37,13 @@ static void update_ui_text_size_widget(struct swappy_state *state) {
3637
gtk_button_set_label(button, label);
3738
}
3839

40+
static void update_ui_transparency_widget(struct swappy_state *state) {
41+
GtkButton *button = GTK_BUTTON(state->ui->transparency);
42+
char label[255];
43+
g_snprintf(label, 255, "%" PRId32, state->settings.tr);
44+
gtk_button_set_label(button, label);
45+
}
46+
3947
static void update_ui_panel_toggle_button(struct swappy_state *state) {
4048
GtkWidget *painting_box = GTK_WIDGET(state->ui->painting_box);
4149
GtkToggleButton *button = GTK_TOGGLE_BUTTON(state->ui->panel_toggle_button);
@@ -52,6 +60,16 @@ static void update_ui_fill_shape_toggle_button(struct swappy_state *state) {
5260
gtk_toggle_button_set_active(button, toggled);
5361
}
5462

63+
static void update_ui_transparent_toggle_button(struct swappy_state *state) {
64+
GtkToggleButton *button = GTK_TOGGLE_BUTTON(state->ui->transparent);
65+
gboolean toggled = state->config->transparent;
66+
67+
gtk_toggle_button_set_active(button, toggled);
68+
gtk_widget_set_sensitive(GTK_WIDGET(state->ui->transparency), toggled);
69+
gtk_widget_set_sensitive(GTK_WIDGET(state->ui->transparency_minus), toggled);
70+
gtk_widget_set_sensitive(GTK_WIDGET(state->ui->transparency_plus), toggled);
71+
}
72+
5573
void application_finish(struct swappy_state *state) {
5674
g_debug("application finishing, cleaning up");
5775
paint_free_all(state);
@@ -215,6 +233,38 @@ static void action_text_size_increase(struct swappy_state *state) {
215233
update_ui_text_size_widget(state);
216234
}
217235

236+
static void action_transparency_decrease(struct swappy_state *state) {
237+
state->settings.tr -= 10;
238+
239+
if (state->settings.tr < SWAPPY_TRANSPARENCY_MIN) {
240+
state->settings.tr = SWAPPY_TRANSPARENCY_MIN;
241+
} else {
242+
// ceil to 10
243+
state->settings.tr += 5;
244+
state->settings.tr /= 10;
245+
state->settings.tr *= 10;
246+
}
247+
248+
update_ui_transparency_widget(state);
249+
}
250+
static void action_transparency_reset(struct swappy_state *state) {
251+
state->settings.tr = state->config->transparency;
252+
update_ui_transparency_widget(state);
253+
}
254+
static void action_transparency_increase(struct swappy_state *state) {
255+
state->settings.tr += 10;
256+
257+
if (state->settings.tr > SWAPPY_TRANSPARENCY_MAX) {
258+
state->settings.tr = SWAPPY_TRANSPARENCY_MAX;
259+
} else {
260+
// floor to 10
261+
state->settings.tr /= 10;
262+
state->settings.tr *= 10;
263+
}
264+
265+
update_ui_transparency_widget(state);
266+
}
267+
218268
static void action_fill_shape_toggle(struct swappy_state *state,
219269
gboolean *toggled) {
220270
// Don't allow changing the state via a shortcut if the button can't be
@@ -227,6 +277,14 @@ static void action_fill_shape_toggle(struct swappy_state *state,
227277
update_ui_fill_shape_toggle_button(state);
228278
}
229279

280+
static void action_transparent_toggle(struct swappy_state *state,
281+
gboolean *toggled) {
282+
gboolean toggle = (toggled == NULL) ? !state->config->transparent : *toggled;
283+
state->config->transparent = toggle;
284+
285+
update_ui_transparent_toggle_button(state);
286+
}
287+
230288
static void save_state_to_file_or_folder(struct swappy_state *state,
231289
char *file) {
232290
GdkPixbuf *pixbuf = pixbuf_get_from_state(state);
@@ -437,6 +495,9 @@ void window_keypress_handler(GtkWidget *widget, GdkEventKey *event,
437495
case GDK_KEY_f:
438496
action_fill_shape_toggle(state, NULL);
439497
break;
498+
case GDK_KEY_T:
499+
action_transparent_toggle(state, NULL);
500+
break;
440501
default:
441502
break;
442503
}
@@ -641,12 +702,31 @@ void text_size_increase_handler(GtkWidget *widget, struct swappy_state *state) {
641702
action_text_size_increase(state);
642703
}
643704

705+
void transparency_decrease_handler(GtkWidget *widget,
706+
struct swappy_state *state) {
707+
action_transparency_decrease(state);
708+
}
709+
void transparency_reset_handler(GtkWidget *widget, struct swappy_state *state) {
710+
action_transparency_reset(state);
711+
}
712+
void transparency_increase_handler(GtkWidget *widget,
713+
struct swappy_state *state) {
714+
action_transparency_increase(state);
715+
}
716+
644717
void fill_shape_toggled_handler(GtkWidget *widget, struct swappy_state *state) {
645718
GtkToggleButton *button = GTK_TOGGLE_BUTTON(widget);
646719
gboolean toggled = gtk_toggle_button_get_active(button);
647720
action_fill_shape_toggle(state, &toggled);
648721
}
649722

723+
void transparent_toggled_handler(GtkWidget *widget,
724+
struct swappy_state *state) {
725+
GtkToggleButton *button = GTK_TOGGLE_BUTTON(widget);
726+
gboolean toggled = gtk_toggle_button_get_active(button);
727+
action_transparent_toggle(state, &toggled);
728+
}
729+
650730
static void compute_window_size_and_scaling_factor(struct swappy_state *state) {
651731
GdkRectangle workarea = {0};
652732
GdkDisplay *display = gdk_display_get_default();
@@ -783,12 +863,20 @@ static bool load_layout(struct swappy_state *state) {
783863
GTK_BUTTON(gtk_builder_get_object(builder, "stroke-size-button"));
784864
state->ui->text_size =
785865
GTK_BUTTON(gtk_builder_get_object(builder, "text-size-button"));
866+
state->ui->transparency =
867+
GTK_BUTTON(gtk_builder_get_object(builder, "transparency-button"));
868+
state->ui->transparency_plus =
869+
GTK_BUTTON(gtk_builder_get_object(builder, "transparency-plus-button"));
870+
state->ui->transparency_minus =
871+
GTK_BUTTON(gtk_builder_get_object(builder, "transparency-minus-button"));
786872

787873
state->ui->fill_shape = GTK_TOGGLE_BUTTON(
788874
gtk_builder_get_object(builder, "fill-shape-toggle-button"));
789875

790876
gdk_rgba_parse(&color, state->config->custom_color);
791877
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(state->ui->color), &color);
878+
state->ui->transparent = GTK_TOGGLE_BUTTON(
879+
gtk_builder_get_object(builder, "transparent-toggle-button"));
792880

793881
state->ui->brush = brush;
794882
state->ui->text = text;
@@ -859,9 +947,11 @@ static bool init_gtk_window(struct swappy_state *state) {
859947

860948
update_ui_stroke_size_widget(state);
861949
update_ui_text_size_widget(state);
950+
update_ui_transparency_widget(state);
862951
update_ui_undo_redo(state);
863952
update_ui_panel_toggle_button(state);
864953
update_ui_fill_shape_toggle_button(state);
954+
update_ui_transparent_toggle_button(state);
865955

866956
return true;
867957
}
@@ -881,6 +971,7 @@ static void init_settings(struct swappy_state *state) {
881971
state->settings.a = 1;
882972
state->settings.w = state->config->line_size;
883973
state->settings.t = state->config->text_size;
974+
state->settings.tr = state->config->transparency;
884975
state->mode = state->config->paint_mode;
885976
}
886977

0 commit comments

Comments
 (0)