diff --git a/CMakeLists.txt b/CMakeLists.txt
index 74da535..fa0b7bd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,8 @@ add_executable(yellownotes main.cpp
gtk-imports.h
gtkloader.h gtkloader.cpp
gtk-imports.c
- yellownotes.h yellownotes.cpp)
+ yellownotes.h yellownotes.cpp
+ tr.h tr.cpp)
include(GNUInstallDirs)
install(TARGETS yellownotes
diff --git a/color.png b/color.png
new file mode 100644
index 0000000..734c728
Binary files /dev/null and b/color.png differ
diff --git a/color.svg b/color.svg
new file mode 100644
index 0000000..ef6c734
--- /dev/null
+++ b/color.svg
@@ -0,0 +1,17 @@
+
+
\ No newline at end of file
diff --git a/delete.png b/delete.png
new file mode 100644
index 0000000..d9105a6
Binary files /dev/null and b/delete.png differ
diff --git a/delete.svg b/delete.svg
new file mode 100644
index 0000000..fc2ebd9
--- /dev/null
+++ b/delete.svg
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/gtk-imports.h b/gtk-imports.h
index cbe3a26..0282eb8 100644
--- a/gtk-imports.h
+++ b/gtk-imports.h
@@ -44,12 +44,30 @@ typedef GtkMenuShell GtkMenu;
typedef void GtkMenuItem;
typedef void GdkEvent;
typedef void GtkTextBuffer;
+typedef void GtkTextView;
typedef void GtkTextTagTable;
typedef void GtkContainer;
typedef void GtkLabel;
typedef void GtkHeaderBar;
typedef void GdkWindow;
typedef void GdkDevice;
+typedef void GtkImage;
+typedef void GdkPixbuf;
+typedef void GError;
+typedef void GtkStyleContext;
+typedef void GtkCssProvider;
+typedef void GtkStyleProvider;
+typedef void GtkWidgetPath;
+typedef void GtkAdjustment;
+typedef void GtkFrame;
+typedef void GtkEventBox;
+typedef void GdkCursor;
+typedef void GdkDisplay;
+typedef void GtkEntry;
+typedef void GtkDialog;
+typedef void GTimer;
+typedef void GtkComboBoxText;
+typedef void GtkComboBox;
typedef int gboolean;
typedef int gint;
@@ -63,11 +81,14 @@ typedef unsigned long long guint64;
typedef float gfloat;
typedef double gdouble;
typedef char gint8;
+typedef unsigned char guint8;
typedef short gint16;
-
+typedef unsigned short guint16;
+typedef size_t gssize;
typedef enum {
- GTK_WINDOW_TOPLEVEL = 0
+ GTK_WINDOW_TOPLEVEL = 0,
+ GTK_WINDOW_POPUP = 1
} GtkWindowType;
typedef enum {
@@ -172,36 +193,56 @@ typedef struct _GtkTextIter {
typedef enum
{
- GDK_DELETE,
- GDK_MOTION_NOTIFY,
- GDK_BUTTON_PRESS,
- GDK_BUTTON_RELEASE,
- GDK_KEY_PRESS,
- GDK_KEY_RELEASE,
- GDK_ENTER_NOTIFY,
- GDK_LEAVE_NOTIFY,
- GDK_FOCUS_CHANGE,
- GDK_PROXIMITY_IN,
- GDK_PROXIMITY_OUT,
- GDK_DRAG_ENTER,
- GDK_DRAG_LEAVE,
- GDK_DRAG_MOTION,
- GDK_DROP_START,
- GDK_SCROLL,
- GDK_GRAB_BROKEN,
- GDK_TOUCH_BEGIN,
- GDK_TOUCH_UPDATE,
- GDK_TOUCH_END,
- GDK_TOUCH_CANCEL,
- GDK_TOUCHPAD_SWIPE,
- GDK_TOUCHPAD_PINCH,
- GDK_PAD_BUTTON_PRESS,
- GDK_PAD_BUTTON_RELEASE,
- GDK_PAD_RING,
- GDK_PAD_STRIP,
- GDK_PAD_GROUP_MODE,
- GDK_TOUCHPAD_HOLD,
- GDK_PAD_DIAL,
+ GDK_NOTHING = -1,
+ GDK_DELETE = 0,
+ GDK_DESTROY = 1,
+ GDK_EXPOSE = 2,
+ GDK_MOTION_NOTIFY = 3,
+ GDK_BUTTON_PRESS = 4,
+ GDK_2BUTTON_PRESS = 5,
+ GDK_DOUBLE_BUTTON_PRESS = GDK_2BUTTON_PRESS,
+ GDK_3BUTTON_PRESS = 6,
+ GDK_TRIPLE_BUTTON_PRESS = GDK_3BUTTON_PRESS,
+ GDK_BUTTON_RELEASE = 7,
+ GDK_KEY_PRESS = 8,
+ GDK_KEY_RELEASE = 9,
+ GDK_ENTER_NOTIFY = 10,
+ GDK_LEAVE_NOTIFY = 11,
+ GDK_FOCUS_CHANGE = 12,
+ GDK_CONFIGURE = 13,
+ GDK_MAP = 14,
+ GDK_UNMAP = 15,
+ GDK_PROPERTY_NOTIFY = 16,
+ GDK_SELECTION_CLEAR = 17,
+ GDK_SELECTION_REQUEST = 18,
+ GDK_SELECTION_NOTIFY = 19,
+ GDK_PROXIMITY_IN = 20,
+ GDK_PROXIMITY_OUT = 21,
+ GDK_DRAG_ENTER = 22,
+ GDK_DRAG_LEAVE = 23,
+ GDK_DRAG_MOTION = 24,
+ GDK_DRAG_STATUS = 25,
+ GDK_DROP_START = 26,
+ GDK_DROP_FINISHED = 27,
+ GDK_CLIENT_EVENT = 28,
+ GDK_VISIBILITY_NOTIFY = 29,
+ GDK_SCROLL = 31,
+ GDK_WINDOW_STATE = 32,
+ GDK_SETTING = 33,
+ GDK_OWNER_CHANGE = 34,
+ GDK_GRAB_BROKEN = 35,
+ GDK_DAMAGE = 36,
+ GDK_TOUCH_BEGIN = 37,
+ GDK_TOUCH_UPDATE = 38,
+ GDK_TOUCH_END = 39,
+ GDK_TOUCH_CANCEL = 40,
+ GDK_TOUCHPAD_SWIPE = 41,
+ GDK_TOUCHPAD_PINCH = 42,
+ GDK_PAD_BUTTON_PRESS = 43,
+ GDK_PAD_BUTTON_RELEASE = 44,
+ GDK_PAD_RING = 45,
+ GDK_PAD_STRIP = 46,
+ GDK_PAD_GROUP_MODE = 47,
GDK_EVENT_LAST /* helper variable for decls */
} GdkEventType;
@@ -235,8 +276,22 @@ typedef struct _GdkEventMotion
gdouble x_root, y_root;
} GdkEventMotion;
+typedef struct _GdkEventKey
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ guint state;
+ guint keyval;
+ gint length;
+ gchar *string;
+ guint16 hardware_keycode;
+ guint8 group;
+ guint is_modifier : 1;
+} GdkEventKey;
-
+#define GDK_KEY_Escape 65307
typedef enum
{
@@ -268,14 +323,260 @@ typedef enum
GDK_ALL_EVENTS_MASK = 0x3FFFFFE
} GdkEventMask;
+typedef enum
+{
+ GTK_STATE_FLAG_NORMAL = 0,
+ GTK_STATE_FLAG_ACTIVE = 1 << 0,
+ GTK_STATE_FLAG_PRELIGHT = 1 << 1,
+ GTK_STATE_FLAG_SELECTED = 1 << 2,
+ GTK_STATE_FLAG_INSENSITIVE = 1 << 3,
+ GTK_STATE_FLAG_INCONSISTENT = 1 << 4,
+ GTK_STATE_FLAG_FOCUSED = 1 << 5,
+ GTK_STATE_FLAG_BACKDROP = 1 << 6,
+ GTK_STATE_FLAG_DIR_LTR = 1 << 7,
+ GTK_STATE_FLAG_DIR_RTL = 1 << 8,
+ GTK_STATE_FLAG_LINK = 1 << 9,
+ GTK_STATE_FLAG_VISITED = 1 << 10,
+ GTK_STATE_FLAG_CHECKED = 1 << 11,
+ GTK_STATE_FLAG_DROP_ACTIVE = 1 << 12
+} GtkStateFlags;
+
+
+typedef void (* GtkMenuPositionFunc) (
+ GtkMenu* menu,
+ gint* x,
+ gint* y,
+ gboolean* push_in,
+ gpointer user_data
+ );
+
+typedef struct _GdkRGBA
+{
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble alpha;
+} GdkRGBA;
+
+typedef struct _GtkRequisition
+{
+ gint width;
+ gint height;
+} GtkRequisition;
+
+typedef enum {
+ GTK_STYLE_CONTEXT_PRINT_NONE = 0,
+ GTK_STYLE_CONTEXT_PRINT_RECURSE = 1 << 0,
+ GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE = 1 << 1
+} GtkStyleContextPrintFlags;
+
+typedef enum
+{
+ GTK_WRAP_NONE,
+ GTK_WRAP_CHAR,
+ GTK_WRAP_WORD,
+ GTK_WRAP_WORD_CHAR
+} GtkWrapMode;
+
+typedef enum
+{
+ GTK_SHADOW_NONE,
+ GTK_SHADOW_IN,
+ GTK_SHADOW_OUT,
+ GTK_SHADOW_ETCHED_IN,
+ GTK_SHADOW_ETCHED_OUT
+} GtkShadowType;
+
+typedef enum
+{
+ GDK_X_CURSOR = 0,
+ GDK_ARROW = 2,
+ GDK_BASED_ARROW_DOWN = 4,
+ GDK_BASED_ARROW_UP = 6,
+ GDK_BOAT = 8,
+ GDK_BOGOSITY = 10,
+ GDK_BOTTOM_LEFT_CORNER = 12,
+ GDK_BOTTOM_RIGHT_CORNER = 14,
+ GDK_BOTTOM_SIDE = 16,
+ GDK_BOTTOM_TEE = 18,
+ GDK_BOX_SPIRAL = 20,
+ GDK_CENTER_PTR = 22,
+ GDK_CIRCLE = 24,
+ GDK_CLOCK = 26,
+ GDK_COFFEE_MUG = 28,
+ GDK_CROSS = 30,
+ GDK_CROSS_REVERSE = 32,
+ GDK_CROSSHAIR = 34,
+ GDK_DIAMOND_CROSS = 36,
+ GDK_DOT = 38,
+ GDK_DOTBOX = 40,
+ GDK_DOUBLE_ARROW = 42,
+ GDK_DRAFT_LARGE = 44,
+ GDK_DRAFT_SMALL = 46,
+ GDK_DRAPED_BOX = 48,
+ GDK_EXCHANGE = 50,
+ GDK_FLEUR = 52,
+ GDK_GOBBLER = 54,
+ GDK_GUMBY = 56,
+ GDK_HAND1 = 58,
+ GDK_HAND2 = 60,
+ GDK_HEART = 62,
+ GDK_ICON = 64,
+ GDK_IRON_CROSS = 66,
+ GDK_LEFT_PTR = 68,
+ GDK_LEFT_SIDE = 70,
+ GDK_LEFT_TEE = 72,
+ GDK_LEFTBUTTON = 74,
+ GDK_LL_ANGLE = 76,
+ GDK_LR_ANGLE = 78,
+ GDK_MAN = 80,
+ GDK_MIDDLEBUTTON = 82,
+ GDK_MOUSE = 84,
+ GDK_PENCIL = 86,
+ GDK_PIRATE = 88,
+ GDK_PLUS = 90,
+ GDK_QUESTION_ARROW = 92,
+ GDK_RIGHT_PTR = 94,
+ GDK_RIGHT_SIDE = 96,
+ GDK_RIGHT_TEE = 98,
+ GDK_RIGHTBUTTON = 100,
+ GDK_RTL_LOGO = 102,
+ GDK_SAILBOAT = 104,
+ GDK_SB_DOWN_ARROW = 106,
+ GDK_SB_H_DOUBLE_ARROW = 108,
+ GDK_SB_LEFT_ARROW = 110,
+ GDK_SB_RIGHT_ARROW = 112,
+ GDK_SB_UP_ARROW = 114,
+ GDK_SB_V_DOUBLE_ARROW = 116,
+ GDK_SHUTTLE = 118,
+ GDK_SIZING = 120,
+ GDK_SPIDER = 122,
+ GDK_SPRAYCAN = 124,
+ GDK_STAR = 126,
+ GDK_TARGET = 128,
+ GDK_TCROSS = 130,
+ GDK_TOP_LEFT_ARROW = 132,
+ GDK_TOP_LEFT_CORNER = 134,
+ GDK_TOP_RIGHT_CORNER = 136,
+ GDK_TOP_SIDE = 138,
+ GDK_TOP_TEE = 140,
+ GDK_TREK = 142,
+ GDK_UL_ANGLE = 144,
+ GDK_UMBRELLA = 146,
+ GDK_UR_ANGLE = 148,
+ GDK_WATCH = 150,
+ GDK_XTERM = 152,
+ GDK_LAST_CURSOR,
+ GDK_BLANK_CURSOR = -2,
+ GDK_CURSOR_IS_PIXMAP = -1
+} GdkCursorType;
+
+typedef enum
+{
+ GTK_ALIGN_FILL,
+ GTK_ALIGN_START,
+ GTK_ALIGN_END,
+ GTK_ALIGN_CENTER,
+ GTK_ALIGN_BASELINE
+} GtkAlign;
+
+typedef enum
+{
+ GTK_DIALOG_MODAL = 1 << 0,
+ GTK_DIALOG_DESTROY_WITH_PARENT = 1 << 1,
+ GTK_DIALOG_USE_HEADER_BAR = 1 << 2
+} GtkDialogFlags;
+
+typedef enum
+{
+ GTK_MESSAGE_INFO,
+ GTK_MESSAGE_WARNING,
+ GTK_MESSAGE_QUESTION,
+ GTK_MESSAGE_ERROR,
+ GTK_MESSAGE_OTHER
+} GtkMessageType;
+
+typedef enum
+{
+ GTK_BUTTONS_NONE,
+ GTK_BUTTONS_OK,
+ GTK_BUTTONS_CLOSE,
+ GTK_BUTTONS_CANCEL,
+ GTK_BUTTONS_YES_NO,
+ GTK_BUTTONS_OK_CANCEL
+} GtkButtonsType;
+
+typedef enum
+{
+ GTK_RESPONSE_NONE = -1,
+ GTK_RESPONSE_REJECT = -2,
+ GTK_RESPONSE_ACCEPT = -3,
+ GTK_RESPONSE_DELETE_EVENT = -4,
+ GTK_RESPONSE_OK = -5,
+ GTK_RESPONSE_CANCEL = -6,
+ GTK_RESPONSE_CLOSE = -7,
+ GTK_RESPONSE_YES = -8,
+ GTK_RESPONSE_NO = -9,
+ GTK_RESPONSE_APPLY = -10,
+ GTK_RESPONSE_HELP = -11
+} GtkResponseType;
+
+typedef struct _GdkEventFocus
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ gint16 in;
+} GdkEventFocus;
+
+typedef gboolean (*GSourceFunc) (gpointer user_data);
+
+typedef enum
+{
+ GDK_WINDOW_TYPE_HINT_NORMAL,
+ GDK_WINDOW_TYPE_HINT_DIALOG,
+ GDK_WINDOW_TYPE_HINT_MENU, /* Torn off menu */
+ GDK_WINDOW_TYPE_HINT_TOOLBAR,
+ GDK_WINDOW_TYPE_HINT_SPLASHSCREEN,
+ GDK_WINDOW_TYPE_HINT_UTILITY,
+ GDK_WINDOW_TYPE_HINT_DOCK,
+ GDK_WINDOW_TYPE_HINT_DESKTOP,
+ GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU, /* A drop down menu (from a menubar) */
+ GDK_WINDOW_TYPE_HINT_POPUP_MENU, /* A popup menu (from right-click) */
+ GDK_WINDOW_TYPE_HINT_TOOLTIP,
+ GDK_WINDOW_TYPE_HINT_NOTIFICATION,
+ GDK_WINDOW_TYPE_HINT_COMBO,
+ GDK_WINDOW_TYPE_HINT_DND
+} GdkWindowTypeHint;
+
+typedef enum
+{
+ GDK_VISIBILITY_UNOBSCURED,
+ GDK_VISIBILITY_PARTIAL,
+ GDK_VISIBILITY_FULLY_OBSCURED
+} GdkVisibilityState;
+
+typedef struct _GdkEventVisibility
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkVisibilityState state;
+} GdkEventVisibility;
#define G_TYPE_FUNDAMENTAL_SHIFT (2)
#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6)
+#define GTK_STYLE_PROVIDER_PRIORITY_USER 800
#endif
+// GLib
+DECL(GTimer*, g_timeout_add, (guint interval, GSourceFunc func, gpointer data));
+
+// Gtk Application / Window / Widget
+
DECL(GtkApplication *, gtk_application_new, (const char *name, GApplicationFlags flags))
DECL(int, g_application_run, (GApplication* application, int argc, char** argv))
@@ -287,47 +588,105 @@ DECL(void, gtk_window_set_decorated, (GtkWindow* window, gboolean setting ))
DECL(void, gtk_widget_show_all, (GtkWindow *window))
DECL(void, gtk_widget_hide, (GtkWidget* widget ))
+DECL(void, gtk_widget_show, (GtkWidget* widget))
+DECL(gboolean, gtk_widget_grab_focus, ( GtkWidget* widget ))
DECL(GtkWidget*, gtk_event_box_new, (void))
+DECL(void, gtk_event_box_set_visible_window, (GtkEventBox* event_box, gboolean visible_window ))
DECL(void, gtk_window_get_size, (GtkWindow *win, int *width, int *height))
DECL(void, gtk_window_resize, (GtkWindow* window, gint width, gint height))
DECL(void, gtk_window_set_default_size, (GtkWindow *window, gint width, gint height))
DECL(void, gtk_window_get_position, (GtkWindow* window, gint* root_x, gint* root_y))
DECL(void, gtk_window_move, (GtkWindow* window, gint x, gint y))
+DECL(void, gtk_window_present, (GtkWindow* window))
+DECL(void, gtk_window_set_type_hint, (GtkWindow* window, GdkWindowTypeHint hint))
+DECL(void, gtk_window_set_skip_taskbar_hint, (GtkWindow* window, gboolean setting))
+DECL(void, gtk_window_set_skip_pager_hint, (GtkWindow* window, gboolean setting))
+DECL(void, gtk_widget_set_can_focus, (GtkWidget* widget, gboolean can_focus ))
+DECL(void, gtk_window_set_transient_for, (GtkWindow* window, GtkWindow* parent ))
+DECL(GType, gtk_window_get_type, (void))
+DECL(GObject*, g_object_new, (GType object_type, const gchar* first_property_name, ...))
+
+DECL(void, gtk_widget_set_size_request, (GtkWidget* widget, int width, int height ))
+DECL(void, gtk_widget_get_preferred_size, (GtkWidget* widget, GtkRequisition* minimum_size, GtkRequisition* natural_size))
+DECL(void, gtk_widget_get_allocation, ( GtkWidget* widget, GtkAllocation* allocation ))
DECL(void, gtk_window_set_resizable, (GtkWindow* window, gboolean resizable))
DECL(GdkWindow *, gtk_widget_get_window, (GtkWidget *w));
+DECL(GdkWindow*, gdk_window_get_effective_toplevel, (GdkWindow* window))
+DECL(void, gdk_window_set_override_redirect, (GdkWindow* window, gboolean override_redirect))
+DECL(GtkWidget*, gtk_scrolled_window_new, (GtkAdjustment* hadjustment, GtkAdjustment* vadjustment))
DECL(gboolean, gtk_window_get_decorated, (GtkWindow* window))
DECL(void, gdk_window_set_events, (GdkWindow* window, GdkEventMask event_mask ))
+DECL(GdkEventMask, gdk_window_get_events, (GdkWindow* window ))
DECL(void, gtk_window_set_title, (GtkWindow* window, const gchar* title))
DECL(const gchar*, gtk_window_get_title, (GtkWindow* window))
DECL(void, gtk_widget_destroy, (GtkWidget* widget))
DECL(void, gtk_container_add, (GtkContainer* container, GtkWidget* widget))
+DECL(void, gtk_container_remove, (GtkContainer* container, GtkWidget* widget))
+
DECL(gboolean, gtk_widget_is_visible, (GtkWidget* widget))
DECL(GtkWidget*, gtk_label_new, (const char* str))
DECL(void, gtk_label_set_ellipsize, (GtkLabel* label, PangoEllipsizeMode mode))
DECL(void, gtk_label_set_label, (GtkLabel* label, const gchar* str))
DECL(const gchar*, gtk_label_get_text, (GtkLabel* label))
+DECL(GtkWidget*, gtk_entry_new, (void))
+DECL(void, gtk_entry_set_text, (GtkEntry* entry, const gchar* text ))
+DECL(const gchar*, gtk_entry_get_text, (GtkEntry* entry))
+
+DECL(GtkWidget*, gtk_separator_new, ( GtkOrientation orientation ))
+
+DECL(GtkWidget*, gtk_frame_new, ( const gchar* label ))
+DECL(void, gtk_frame_set_shadow_type, (GtkFrame* frame, GtkShadowType type ))
DECL(GtkWidget*, gtk_box_new, (GtkOrientation orientation, gint spacing ))
+DECL(void, gtk_widget_set_vexpand, (GtkWidget* widget, gboolean expand ))
+DECL(void, gtk_widget_set_hexpand, (GtkWidget* widget, gboolean expand ))
+DECL(void, gtk_widget_set_halign, (GtkWidget* widget, GtkAlign align ))
+DECL(void, gtk_widget_set_valign, (GtkWidget* widget, GtkAlign align ))
+
+DECL(gboolean, gtk_widget_translate_coordinates, ( GtkWidget* src_widget, GtkWidget* dest_widget, gint src_x, gint src_y, gint* dest_x, gint* dest_y))
DECL(void, gtk_main, (void))
DECL(void, gtk_main_quit, (void))
DECL(unsigned long, g_signal_connect_data, (GObject *obj, const char *signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags))
+// Messages
+DECL(GtkWidget*, gtk_message_dialog_new, (GtkWindow* parent, GtkDialogFlags flags, GtkMessageType type, GtkButtonsType buttons, const gchar* message_format, ...))
+DECL(gint, gtk_dialog_run, (GtkDialog* dialog))
+
+// Dialogs
+DECL(GtkWidget*, gtk_dialog_new, (void))
+DECL(GtkWidget*, gtk_dialog_add_button, (GtkDialog* dialog, const gchar* button_text, gint response_id ))
+DECL(void, gtk_dialog_response, (GtkDialog* dialog, gint response_id ))
+//DECL(GtkWidget*, gtk_dialog_new_with_buttons, (const gchar* title, GtkWindow* parent, GtkDialogFlags flags, const gchar* first_button_text, ...))
+//DECL(GtkWidget*, gtk_drop_down_new_from_strings, (const char* const* strings ))
+DECL(GtkWidget*, gtk_combo_box_new, (void));
+DECL(GtkWidget*, gtk_combo_box_text_new, (void))
+DECL(void, gtk_combo_box_text_append, ( GtkComboBoxText* combo_box, const gchar* id, const gchar* text ))
+DECL(GtkWidget*, gtk_dialog_get_content_area, (GtkDialog* dialog ))
+DECL(gboolean, gtk_combo_box_set_active_id, ( GtkComboBox* combo_box, const gchar* active_id ))
+DECL(const gchar*, gtk_combo_box_get_active_id, (GtkComboBox* combo_box))
+
// GObject / GValue
DECL(void, g_object_unref, (GObject* object))
+DECL(void, g_object_ref, (GObject* object))
DECL(void, g_object_set_property, (GObject* object, const gchar* property_name, const GValue* value))
DECL(GValue*, g_value_init, (GValue* value, GType g_type))
DECL(void, g_value_unset, (GValue* value))
DECL(void, g_value_set_int, (GValue* value, gint v_int))
+DECL(void, g_free, (gpointer mem))
+// Cursors
+DECL(GdkCursor*, gdk_cursor_new_from_name, (GdkDisplay* display, const gchar* name ))
+DECL(GdkCursor*, gdk_cursor_new, ( GdkCursorType cursor_type ))
+DECL(void, gdk_window_set_cursor, (GdkWindow* window, GdkCursor* cursor ))
// Menus
@@ -338,6 +697,8 @@ DECL(GtkMenuItem *, gtk_menu_item_new, (void));
DECL(GtkMenuItem *, gtk_menu_item_new_with_label, (const gchar *label));
DECL(void, gtk_menu_shell_append, (GtkMenuShell* menu_shell, GtkWidget* child))
DECL(GtkWidget *, gtk_separator_menu_item_new, (void))
+DECL(void, gtk_menu_popup, (GtkMenu* menu, GtkWidget* parent_menu_shell, GtkWidget* parent_menu_item,
+ GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time))
// Text Buffer / Widget
DECL(GtkTextBuffer*, gtk_text_buffer_new, (GtkTextTagTable* table))
@@ -347,17 +708,42 @@ DECL(void, gtk_text_buffer_get_end_iter, (GtkTextBuffer* buffer, GtkTextIter* it
DECL(GtkWidget*, gtk_text_view_new, (void))
DECL(GtkWidget*, gtk_text_view_new_with_buffer, ( GtkTextBuffer* buffer ))
DECL(void, gtk_text_buffer_set_text, (GtkTextBuffer* buffer, const gchar* text, gint len ))
+DECL(void, gtk_text_view_set_wrap_mode, (GtkTextView* text_view, GtkWrapMode wrap_mode ))
// Titlebar
DECL(GtkWidget*, gtk_header_bar_new, (void))
DECL(void, gtk_header_bar_set_custom_title, (GtkHeaderBar* bar, GtkWidget* title_widget))
-// Deprecated in Gtk3
+// Image
+DECL(GtkWidget*, gtk_image_new_from_file, (const char* filename ))
+DECL(GtkWidget*, gtk_image_new_from_pixbuf, (GdkPixbuf* pixbuf ))
+DECL(void, gtk_image_set_from_pixbuf, ( GtkImage* image, GdkPixbuf* pixbuf ))
+DECL(GdkPixbuf*, gdk_pixbuf_new_from_file, (const char* filename, GError** error))
+DECL(GdkPixbuf*, gdk_pixbuf_new_from_file_at_size, (const char* filename, int width, int height, GError** error))
+// Styles
+DECL(GtkStyleContext*, gtk_widget_get_style_context, (GtkWidget* widget))
+DECL(char*, gtk_style_context_to_string, (GtkStyleContext* context, GtkStyleContextPrintFlags flags))
+DECL(GtkCssProvider*, gtk_css_provider_new, (void))
+DECL(gboolean, gtk_css_provider_load_from_data, (GtkCssProvider* css_provider, const gchar* data, gssize length, GError** error))
+DECL(void, gtk_style_context_add_provider, (GtkStyleContext* context, GtkStyleProvider* provider, guint priority))
+DECL(const GtkWidgetPath*, gtk_style_context_get_path, (GtkStyleContext* context))
+DECL(char*, gtk_widget_path_to_string, (const GtkWidgetPath* path))
+
+// Deprecated in Gtk3
DECL(GtkStatusIcon*, gtk_status_icon_new, (void ))
DECL(GtkStatusIcon*, gtk_status_icon_new_from_file, (const gchar* filename))
+DECL(void, gtk_widget_override_background_color, (GtkWidget* widget, GtkStateFlags state, const GdkRGBA* color))
+DECL(void, gtk_window_set_has_resize_grip, (GtkWindow* window, gboolean value ))
#define g_signal_connect(instance, signal, c_handler, data) \
g_signal_connect_data(instance, signal, reinterpret_cast(c_handler), data, NULL, G_CONNECT_DEFAULT)
+// WIN32
+
+#ifdef _WIN32
+#include
+DECL(HWND, gdk_win32_window_get_handle, (GdkWindow *window));
+#endif
+
#endif // GTK_IMPORTS_H
diff --git a/gtkloader.cpp b/gtkloader.cpp
index cfd62e2..21edad6 100644
--- a/gtkloader.cpp
+++ b/gtkloader.cpp
@@ -105,6 +105,8 @@ void GtkLoader::dlopen()
"gtk-3-vs17",
"glib-2.0-0",
"gio-2.0-0",
+ "gdk-3-vs17",
+ "gdk_pixbuf-2.0-0",
NULL
};
int i;
diff --git a/hide.png b/hide.png
new file mode 100644
index 0000000..e58aa47
Binary files /dev/null and b/hide.png differ
diff --git a/hide.svg b/hide.svg
new file mode 100644
index 0000000..a6ae70c
--- /dev/null
+++ b/hide.svg
@@ -0,0 +1,27 @@
+
+
+
+
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
index 0a68b54..9e88434 100644
--- a/main.cpp
+++ b/main.cpp
@@ -14,7 +14,8 @@ static void activate (GtkApplication* app, gpointer user_data)
GtkWidget *window;
YellowNotes *notes = YELLOWNOTES(user_data);
- GtkStatusIcon *tray = gtk_status_icon_new_from_file(notes->imageFile("yellownotes.svg").c_str());
+ std::string img_file = notes->imageFile("yellownotes");
+ GtkStatusIcon *tray = gtk_status_icon_new_from_file(img_file.c_str());
g_signal_connect(tray, "activate", on_tray_activate, notes);
}
@@ -22,6 +23,8 @@ int main(int argc, char **argv)
{
GtkLoader l;
+ srand(time(NULL)); // seed with current time
+
try {
l.loadGtk();
} catch(std::string msg) {
diff --git a/plus.png b/plus.png
new file mode 100644
index 0000000..7e0eb9a
Binary files /dev/null and b/plus.png differ
diff --git a/plus.svg b/plus.svg
new file mode 100644
index 0000000..2dfdc78
--- /dev/null
+++ b/plus.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/tr.cpp b/tr.cpp
new file mode 100644
index 0000000..e217f8b
--- /dev/null
+++ b/tr.cpp
@@ -0,0 +1,94 @@
+#include "tr.h"
+#include
+
+void tr::add(const char *sentence, ...)
+{
+ va_list args;
+ va_start(args, sentence);
+
+ std::string sent(sentence);
+
+ const char *tr = va_arg(args, char *);
+ while (tr != nullptr) {
+ std::string t(tr);
+ size_t pos = t.find(":");
+ std::string lang = t.substr(0, pos);
+ std::string str = t.substr(pos + 1);
+
+ std::unordered_map::iterator it;
+ it = _translations.find(lang);
+ if (it != _translations.end()) {
+ Translations_t *m = it->second;
+ std::pair p = { sent, str };
+ m->insert(p);
+ } else {
+ Translations_t *m = new Translations_t();
+ std::pair p = { sent, str };
+ m->insert(p);
+ std::pair lp = { lang, m };
+ _translations.insert(lp);
+ }
+
+ tr = va_arg(args, char *);
+ }
+
+ va_end(args);
+}
+
+const char *tr::translate(const char *str)
+{
+ std::unordered_map::iterator it;
+
+ it = _translations.find(_lang);
+
+ if (it == _translations.end()) {
+ return str;
+ } else {
+ Translations_t *m = it->second;
+ Translations_t::iterator n_it;
+ std::string s(str);
+ n_it = m->find(s);
+ if (n_it == m->end()) {
+ return str;
+ } else {
+ return n_it->second.c_str();
+ }
+ }
+}
+
+void tr::setLang(const std::string &l)
+{
+ _lang = l;
+}
+
+tr::tr()
+{
+ add("Quit", "nl:Beƫindigen", nullptr);
+ add("New Note", "nl:Nieuwe Notitie", nullptr);
+ add("Show Notes", "nl:Notities Presenteren", nullptr);
+ add("Hide Notes", "nl:Notities Verbergen", nullptr);
+ add("Reload Notes", "nl:Notities opnieuw laden", nullptr);
+ add("Setup", "nl:Instellingen", nullptr);
+ _lang = "en";
+}
+
+static tr *_t = nullptr;
+
+static void init()
+{
+ if (_t == nullptr) {
+ _t = new tr();
+ }
+}
+
+const char *_(const char *str)
+{
+ init();
+ return _t->translate(str);
+}
+
+void setLang(const std::string &lang)
+{
+ init();
+ _t->setLang(lang);
+}
diff --git a/tr.h b/tr.h
new file mode 100644
index 0000000..cf041ae
--- /dev/null
+++ b/tr.h
@@ -0,0 +1,31 @@
+#ifndef TR_H
+#define TR_H
+
+#include
+#include
+
+typedef std::unordered_map Translations_t;
+
+class tr
+{
+private:
+ std::unordered_map _translations;
+ std::string _lang;
+
+private:
+ void add(const char *sentence, ...);
+
+public:
+ const char *translate(const char *str);
+
+public:
+ void setLang(const std::string &l);
+
+public:
+ tr();
+};
+
+const char *_(const char *str);
+void setLang(const std::string &lang);
+
+#endif // TR_H
diff --git a/yellownotes.cpp b/yellownotes.cpp
index 57aeb22..e055c33 100644
--- a/yellownotes.cpp
+++ b/yellownotes.cpp
@@ -11,31 +11,74 @@
#include
#endif
+#ifdef _WIN32
+#include
+#endif
+
#include
+extern "C" {
#include "gtk-imports.h"
+}
+
+#include "tr.h"
+
+static void trim(std::string &s) {
+ size_t start = s.find_first_not_of(" \t\n\r");
+ size_t end = s.find_last_not_of(" \t\n\r");
+
+ if (start == std::string::npos)
+ s.clear(); // String contains only whitespace
+ else
+ s = s.substr(start, end - start + 1);
+}
+
class YellowNote
{
private:
+ YellowNotes *_notes;
+
GtkWindow *_note_widget;
+
+ GtkWidget *_evt_box;
GtkWidget *_note_box;
- GtkTextBuffer *_buffer;
- GtkWidget *_text_widget;
- GtkWidget *_title_box;
+ GtkWidget *_frame;
+
+ GtkWidget *_note_header;
+ GtkImage *_color_image;
+ GtkImage *_delete_image;
+ GtkImage *_plus_image;
+ GtkImage *_hide_image;
GtkWidget *_title_label;
- GtkHeaderBar *_note_header;
- GtkWidget *_header_evt_box;
+ GtkWidget *_title_entry;
+ GtkWidget *_title_separator;
+
+ GtkWidget *_scroll_widget;
+ GtkWidget *_text_widget;
+ GtkTextBuffer *_buffer;
+
std::string _filename;
std::string _note;
std::string _title;
+
bool _hidden;
int _x;
int _y;
int _width;
int _height;
bool _in_transaction;
+ bool _editing_title;
+
+ int _save_counter;
+ int _save_id;
+
+ ColorType_t _color;
+ bool _color_changed;
bool _moving;
+ bool _resize_right;
+ bool _resize_bottom;
+ bool _resize_edge;
int _x_orig;
int _y_orig;
@@ -48,22 +91,49 @@ private:
void updatePosition();
void updateHidden();
void updateSize();
+ void updateColor();
+
+ void adjustTitle(bool mutate);
+
+ void get_header_screen_coords(int &header_top, int &header_bottom);
+ void get_frame_screen_coords(int &frame_bottom, int &frame_right);
+ void get_screen_left_right(GtkWidget *widget, int &left, int &right);
+
+ void nextColor();
+ void deleteMe();
+ void addNew();
+
+ void updateWidgetColors(GtkWidget *w);
public:
- void changed();
- void size_allocated(GtkAllocation *a);
+ void changed(GtkWidget *sender);
+ void size_allocated(GtkWidget *sender, GtkAllocation *a);
public:
- bool move_begin(GdkEventButton *evt);
- bool move_end(GdkEventButton *evt);
- bool moving(GdkEventMotion *evt);
+ void toFront();
+
+public:
+ bool move_begin(GtkWidget *sender, GdkEventButton *evt);
+ bool move_end(GtkWidget *sender, GdkEventButton *evt);
+ bool moving(GtkWidget *sender, GdkEventMotion *evt);
+ bool titleEscape(GtkWidget *sender, GdkEventKey *key);
+ void titleEnter(GtkWidget *sender);
+ bool titleFocusOut(GtkWidget *sender, GdkEventFocus *evt);
+ void textChanged(void *sender);
+ bool textSaveTimeout();
+ bool windowPresented(void *sender, GdkEventVisibility *evt);
+ void showNote(GtkWidget *sender);
+
+public:
+ std::string title();
+ bool isHidden();
public:
void load();
void save();
public:
- YellowNote(const std::string &filename);;
+ YellowNote(YellowNotes *notes, const std::string &filename);
~YellowNote();
};
@@ -71,19 +141,49 @@ SIGNAL2(YellowNote, on_size_allocated, size_allocated, GtkAllocation)
BSIGNAL2(YellowNote, on_button_press, move_begin, GdkEventButton);
BSIGNAL2(YellowNote, on_button_release, move_end, GdkEventButton);
BSIGNAL2(YellowNote, on_mouse_move, moving, GdkEventMotion);
+SIGNAL(YellowNote, on_title_activate, titleEnter);
+BSIGNAL2(YellowNote, on_title_escape, titleEscape, GdkEventKey);
+BSIGNAL2(YellowNote, on_title_focus_out, titleFocusOut, GdkEventFocus);
+BSIGNAL2(YellowNote, on_window_present, windowPresented, GdkEventVisibility);
+SIGNAL(YellowNote, on_text_change, textChanged);
+SIGNAL(YellowNote, on_show_note, showNote);
+
+
+static gboolean on_text_save_timeout(gpointer data)
+{
+ YellowNote *n = reinterpret_cast(data);
+ return n->textSaveTimeout();
+}
SIGNAL(YellowNotes, on_new_yellow, newNote)
+SIGNAL(YellowNotes, on_show, showNotes);
+SIGNAL(YellowNotes, on_reload, reloadNotes);
+SIGNAL(YellowNotes, on_setup, setup);
SIGNAL(YellowNotes, on_quit, quit)
+SIGNAL(YellowNotes, on_hide_toplevel, topLevelHidden)
+SIGNAL(YellowNotes, on_setup_ok, setupClose);
+SIGNAL(YellowNotes, on_setup_close, setupCancel);
+BSIGNAL2(YellowNotes, on_setup_del, setupDel, void);
+
std::string YellowNotes::imageFile(const char *name)
{
-
- return appDir() + "/" + name;
+#ifdef _WIN32
+ std::string ext = ".png";
+#else
+ std::string ext = ".svg";
+#endif
+ return appDir() + "/" + name + ext;
}
std::string YellowNotes::appDir()
{
+#ifdef __linux
std::string base = "/home/hans/src/yellownotes";
+#endif
+#ifdef _WIN32
+ std::string base = "c:/devel/yellownotes";
+#endif
return base;
}
@@ -94,6 +194,11 @@ std::string YellowNotes::notesDir()
const char *homedir = pw->pw_dir;
#endif
+#ifdef _WIN32
+ char homedir[10240];
+ snprintf(homedir, 10240, "%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH"));
+#endif
+
std::string home_dir = homedir;
std::string notes_dir = home_dir + "/yellownotes";
@@ -105,7 +210,77 @@ std::string YellowNotes::notesDir()
return notes_dir;
}
-void YellowNotes::popupTrayMenu()
+std::string YellowNotes::css(ColorType_t type)
+{
+ const char *bgs[] = { "#404040", // dark
+ "#faf32a", // yellow
+ "#fcbf56", // orange,
+ "#5df0f5", // blue
+ "#fc77f4", // Cyaan
+ "#74fc94", // greeen
+ "#f7bcbc", // red
+ "#cdcfd1" // grey
+ };
+
+ const char *fgs[] = { "white",
+ "black",
+ "black",
+ "black",
+ "black",
+ "black",
+ "black",
+ "black"
+ };
+
+ auto from_hex = [](std::string hex_num) {
+ return strtol(hex_num.c_str(), NULL, 16);
+ };
+
+ auto darker = [from_hex](std::string color) {
+ int red = from_hex(color.substr(1, 2));
+ int green = from_hex(color.substr(3, 2));
+ int blue = from_hex(color.substr(5, 2));
+ float factor = 0.9;
+ red *= factor;
+ green *= factor;
+ blue *= factor;
+ char buf[20];
+ sprintf(buf, "#%02x%02x%02x", red, green, blue);
+ std::string s = buf;
+ return s;
+ };
+
+ char font_size[20];
+ sprintf(font_size, "%dpx", _font_size);
+
+ std::string css = std::string() +
+ "label, box.horizontal, textview.view, textview.view text, frame, messagedialog.background {\n"
+ " background-color: " + bgs[type] + ";\n"
+ " color: " + fgs[type] + ";\n"
+ " font-family: sans;\n"
+ " font-size: " + font_size + ";\n"
+ "}\n"
+ "frame border {\n"
+ " border: none;\n"
+ " box-shadow: 5px 5px 5px " + darker(bgs[type]) + ";\n"
+ " margin: 5px;\n"
+ "}\n";
+
+ return css;
+}
+
+int YellowNotes::fontSize()
+{
+ return _font_size;
+}
+
+int YellowNotes::iconSize()
+{
+ return _font_size * 1.5;
+}
+
+
+void YellowNotes::popupTrayMenu(void *sender)
{
GtkMenu *tray_menu = reinterpret_cast(_tray_menu);
@@ -114,22 +289,64 @@ void YellowNotes::popupTrayMenu()
tray_menu = gtk_menu_new();
_tray_menu = reinterpret_cast(tray_menu);
- GtkMenuItem *new_yellow = gtk_menu_item_new_with_label("New Note");
- GtkMenuItem *handle_notes = gtk_menu_item_new_with_label("Organize Notes");
+ GtkMenuItem *new_yellow = gtk_menu_item_new_with_label(_("New Note"));
+ GtkMenuItem *show_notes = gtk_menu_item_new_with_label(_("Show Notes"));
+ GtkMenuItem *reload_notes = gtk_menu_item_new_with_label(_("Reload Notes"));
GtkWidget *sep = gtk_separator_menu_item_new();
- GtkMenuItem *quit = gtk_menu_item_new_with_label("Quit");
+ std::list hidden;
+ std::list h_notes;
+ std::list::iterator it = _notes.begin();
+ while (it != _notes.end()) {
+ YellowNote *n = *it;
+ GtkWidget *m = gtk_menu_item_new_with_label(n->title().c_str());
+ if (n->isHidden()) {
+ hidden.push_back(m);
+ h_notes.push_back(n);
+ }
+ it++;
+ }
+
+ GtkWidget *sep1 = gtk_separator_menu_item_new();
+
+ GtkMenuItem *setup = gtk_menu_item_new_with_label(_("Setup"));
+ GtkMenuItem *quit = gtk_menu_item_new_with_label(_("Quit"));
gtk_menu_shell_append(tray_menu, new_yellow);
- gtk_menu_shell_append(tray_menu, handle_notes);
+ gtk_menu_shell_append(tray_menu, show_notes);
+ gtk_menu_shell_append(tray_menu, reload_notes);
gtk_menu_shell_append(tray_menu, sep);
+
+ std::list::iterator w_it = hidden.begin();
+ while (w_it != hidden.end()) {
+ gtk_menu_shell_append(tray_menu, *w_it);
+ w_it++;
+ }
+
+ gtk_menu_shell_append(tray_menu, sep1);
+ gtk_menu_shell_append(tray_menu, setup);
gtk_menu_shell_append(tray_menu, quit);
gtk_widget_show_all(tray_menu);
g_signal_connect(new_yellow, "activate", on_new_yellow, this);
+ g_signal_connect(show_notes, "activate", on_show, this);
+ g_signal_connect(reload_notes, "activate", on_reload, this);
+ g_signal_connect(setup, "activate", on_setup, this);
g_signal_connect(quit, "activate", on_quit, this);
+ w_it = hidden.begin();
+ it = h_notes.begin();
+ while(w_it != hidden.end()) {
+ g_signal_connect(*w_it, "activate", on_show_note, *it);
+ w_it++;
+ it++;
+ }
+#ifdef __linux
gtk_menu_popup_at_pointer(tray_menu, nullptr);
+#endif
+#ifdef _WIN32
+ gtk_menu_popup(tray_menu, nullptr, nullptr, nullptr, nullptr, 0, 0);
+#endif
}
void YellowNotes::clearNotes()
@@ -141,8 +358,64 @@ void YellowNotes::clearNotes()
}
}
+void YellowNotes::loadConfig()
+{
+ std::string notes_dir = notesDir();
+ std::string cfg_file = notes_dir + "/yellownotes.cfg";
+ std::filesystem::path p(cfg_file);
+
+ auto add = [this](const char *k, const char *v) {
+ _cfg.insert(std::pair(std::string(k), std::string(v)));
+ };
+
+ _cfg.clear();
+ add("lang", "en");
+
+ if (std::filesystem::is_regular_file(p)) {
+ FILE *f = fopen(cfg_file.c_str(), "rt");
+ char buf[10240];
+ char *b = fgets(buf, 10240, f);
+ while (b != nullptr) {
+ std::string e = std::string(b);
+ trim(e);
+ if (e != "") {
+ size_t pos = e.find("=");
+ std::string k = e.substr(0, pos);
+ std::string v = e.substr(pos + 1);
+ trim(k);
+ trim(v);
+ _cfg.erase(k);
+ _cfg.insert(std::pair(k, v));
+ }
+ b = fgets(buf, 10240, f);
+ }
+ fclose (f);
+ }
+
+ setLang(currentLang());
+}
+
+void YellowNotes::saveConfig()
+{
+ std::string notes_dir = notesDir();
+ std::string cfg_file = notes_dir + "/yellownotes.cfg";
+
+ FILE *f = fopen(cfg_file.c_str(), "wt");
+ if (f) {
+ std::unordered_map::iterator it;
+ it = _cfg.begin();
+ while (it != _cfg.end()) {
+ fprintf(f, "%s=%s\n", it->first.c_str(), it->second.c_str());
+ it++;
+ }
+ fclose(f);
+ }
+}
+
void YellowNotes::loadNotes()
{
+ gtk_widget_show_all(topLevel());
+
clearNotes();
std::string notes_dir = notesDir();
@@ -159,110 +432,327 @@ void YellowNotes::loadNotes()
{
const auto full_name = entry.path().string();
- if (entry.is_regular_file())
+ if (entry.is_regular_file() && full_name.rfind(".note") != std::string::npos)
{
const auto base_name = entry.path().filename().string();
if (base_name.rfind(".note") > 0) {
- YellowNote *note = new YellowNote(full_name);
+ YellowNote *note = new YellowNote(this, full_name);
_notes.push_back(note);
}
}
}
+
+ gtk_widget_hide(topLevel());
}
-void YellowNotes::newNote()
+void YellowNotes::showNotes(void *sender)
{
- std::string new_note_title = "New Note";
+ std::list::const_iterator it = _notes.begin();
+ while (it != _notes.end()) {
+ YellowNote *note = *it;
+ note->toFront();
+ it++;
+ }
+
+}
+
+void YellowNotes::setupCancel(GtkWidget *sender)
+{
+ if (_dlg) {
+ gtk_widget_destroy(_dlg);
+ _dlg = nullptr;
+ _langs = nullptr;
+ }
+}
+
+bool YellowNotes::setupDel(GtkWidget *sender, void *evt)
+{
+ setupCancel(sender);
+ return true;
+}
+
+void YellowNotes::setupClose(GtkWidget *sender)
+{
+ if (_dlg != nullptr) {
+ std::cout << "hey" << std::endl;
+ gtk_dialog_response(_dlg, GTK_RESPONSE_OK);
+ std::string lang = std::string(gtk_combo_box_get_active_id(_langs));
+ std::cout << "lang " << lang << std::endl;
+ setCurrentLang(lang);
+ gtk_widget_destroy(_dlg);
+ _dlg = nullptr;
+ _langs = nullptr;
+ saveConfig();
+ } else {
+ std::cout << "close button" << std::endl;
+ }
+}
+
+void YellowNotes::setup(void *sender)
+{
+ loadConfig();
+
+ GtkWidget *dlg = gtk_dialog_new();
+ gtk_window_set_title(dlg, _("Yellownotes Setup"));
+ _dlg = dlg;
+
+ GtkWidget *ok_btn = gtk_dialog_add_button(dlg, _("Ok"), GTK_RESPONSE_OK);
+ GtkWidget *content = gtk_dialog_get_content_area(dlg);
+
+ GtkWidget *langs = gtk_combo_box_text_new();
+ _langs = langs;
+ gtk_combo_box_text_append(langs, "en", "English");
+ gtk_combo_box_text_append(langs, "nl", "Nederlands");
+
+ std::string current_lang = currentLang();
+ gtk_combo_box_set_active_id(langs, current_lang.c_str());
+
+ GtkWidget *hbox = gtk_box_new(GtkOrientation::GTK_ORIENTATION_HORIZONTAL, 5);
+
+ gtk_container_add(hbox, langs);
+ gtk_container_add(content, hbox);
+
+ g_signal_connect(ok_btn, "clicked", on_setup_ok, this);
+ g_signal_connect(dlg, "close", on_setup_close, this);
+ g_signal_connect(dlg, "delete-event", on_setup_del, this);
+
+ gtk_widget_show_all(dlg);
+}
+
+void YellowNotes::reloadNotes(void *sender)
+{
+ std::list::const_iterator it = _notes.begin();
+ while (it != _notes.end()) {
+ YellowNote *note = *it;
+ delete note;
+ it++;
+ }
+ _notes.clear();
+ loadNotes();
+ showNotes(sender);
+}
+
+
+void YellowNotes::newNote(void *sender)
+{
+ unsigned long long milliseconds_since_epoch =
+ std::chrono::system_clock::now().time_since_epoch() /
+ std::chrono::milliseconds(1);
+
+ char buf[200];
+ int r = rand() % 1000;
+ sprintf(buf, "%llu-%d", milliseconds_since_epoch, r);
+
+ std::string new_note_file = buf;
std::string notes_dir = notesDir();
- auto filename = [notes_dir](const std::string & title, int i) {
+ auto filename = [notes_dir](const std::string & fname, int i) {
char s[20];
- sprintf(s, " %d", i);
- std::string fn = notes_dir + "/" + title + s + ".note";
+ sprintf(s, "%d", i);
+ std::string fn = notes_dir + "/" + fname + "-" + s + ".note";
return fn;
};
-
int i = 1;
- std::filesystem::path p(filename(new_note_title, i));
+ std::filesystem::path p(filename(new_note_file, i));
while(std::filesystem::is_regular_file(p)) {
i += 1;
- p = std::filesystem::path(filename(new_note_title, i));
+ p = std::filesystem::path(filename(new_note_file, i));
}
- YellowNote *note = new YellowNote(p);
+ YellowNote *note = new YellowNote(this, p.string());
_notes.push_back(note);
note->show();
note->save();
}
-void YellowNotes::quit()
+void YellowNotes::quit(void *sender)
{
gtk_main_quit();
}
+void YellowNotes::remove(YellowNote *n)
+{
+ _notes.remove(n);
+}
+
+std::string YellowNotes::currentLang()
+{
+ std::string key("lang");
+ return _cfg[key];
+}
+
+void YellowNotes::setCurrentLang(const std::string &l)
+{
+ std::string key("lang");
+ _cfg.erase(key);
+ _cfg.insert(std::pair(key, l));
+}
+
+static int show_notes_timed(void *user_data)
+{
+ YellowNotes *notes = reinterpret_cast(user_data);
+ notes->showNotes(nullptr);
+ return false;
+}
+
+void YellowNotes::topLevelHidden(GtkWidget *sender)
+{
+ g_timeout_add(500, show_notes_timed, this);
+}
+
+GtkWindow *YellowNotes::topLevel()
+{
+ if (_toplevel == nullptr) {
+ _toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_widget_show_all(_toplevel);
+ g_signal_connect(_toplevel, "hide", on_hide_toplevel, this);
+ }
+ return _toplevel;
+}
+
YellowNotes::YellowNotes(void *app)
{
_app = app;
_tray_menu = nullptr;
+ _font_size = 15;
+ _toplevel = nullptr;
+ loadConfig();
}
YellowNotes::~YellowNotes()
{
if (_tray_menu) { gtk_widget_destroy(reinterpret_cast(_tray_menu)); }
clearNotes();
+ gtk_widget_destroy(_toplevel);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// YellowNote implementation
////////////////////////////////////////////////////////////////////////////////////////////////////
-YellowNote::YellowNote(const std::string &filename) {
+YellowNote::YellowNote(YellowNotes *notes, const std::string &filename)
+{
+ _notes = notes;
_filename = filename;
- _title = "";
- _x = -1;
- _y = -1;
- _width = -1;
- _height = -1;
+ _title = _("New Note");
+ _x = 200;
+ _y = 300;
+ _width = 300;
+ _height = 200;
_hidden = false;
+ _editing_title = false;
+ _save_counter = 0;
+ _save_id = -1;
_moving = false;
+ _resize_bottom = false;
+ _resize_edge = false;
+ _resize_right = false;
+
+ _color = ColorType_t::YELLOW;
+ _color_changed = false;
+
+ _note_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_can_focus(_note_widget, true);
+ gtk_window_set_decorated(_note_widget, false);
+ gtk_window_set_type_hint(_note_widget, GDK_WINDOW_TYPE_HINT_POPUP_MENU);
+ gtk_window_set_transient_for(_note_widget, _notes->topLevel());
+
+ _scroll_widget = gtk_scrolled_window_new(nullptr, nullptr);
+ gtk_widget_set_vexpand(_scroll_widget, true);
- _note_widget = gtk_window_new(GtkWindowType::GTK_WINDOW_TOPLEVEL);
_buffer = gtk_text_buffer_new(nullptr);
_text_widget = gtk_text_view_new_with_buffer(_buffer);
+ gtk_text_view_set_wrap_mode(_text_widget, GTK_WRAP_WORD);
- _header_evt_box = gtk_event_box_new();
- _note_header = gtk_header_bar_new();
+ _evt_box = gtk_event_box_new();
+
+ _note_header = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
- gtk_window_set_decorated(_note_widget, false);
_note_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
- //_title_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
_title_label = gtk_label_new(_title.c_str());
gtk_label_set_ellipsize(_title_label, PANGO_ELLIPSIZE_END);
- gtk_header_bar_set_custom_title(_note_header, _title_label);
+ gtk_widget_set_hexpand(_title_label, true);
- //gtk_container_add(_title_box, _title_label);
- gtk_container_add(_note_box, _header_evt_box);
- gtk_container_add(_header_evt_box, _note_header);
- gtk_container_add(_note_box, _text_widget);
- gtk_container_add(_note_widget, _note_box);
+ _title_entry = gtk_entry_new();
+ gtk_widget_set_hexpand(_title_entry, true);
+
+ _title_separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
+
+ _frame = gtk_frame_new(nullptr);
+ gtk_frame_set_shadow_type(_frame, GtkShadowType::GTK_SHADOW_OUT);
+
+ int height = _notes->iconSize();
+ int width = height;
+
+ GdkPixbuf *color_pixbuf = gdk_pixbuf_new_from_file_at_size(notes->imageFile("color").c_str(),
+ width, height, nullptr
+ );
+ _color_image = gtk_image_new_from_pixbuf(color_pixbuf);
+ g_object_unref(color_pixbuf);
+
+ GdkPixbuf *delete_pixbuf = gdk_pixbuf_new_from_file_at_size(notes->imageFile("delete").c_str(),
+ width, height, nullptr
+ );
+ _delete_image = gtk_image_new_from_pixbuf(delete_pixbuf);
+ gtk_widget_set_halign(_delete_image, GtkAlign::GTK_ALIGN_END);
+ g_object_unref(delete_pixbuf);
+
+ GdkPixbuf *plus_pixbuf = gdk_pixbuf_new_from_file_at_size(notes->imageFile("plus").c_str(),
+ width, height, nullptr
+ );
+ _plus_image = gtk_image_new_from_pixbuf(plus_pixbuf);
+ gtk_widget_set_halign(_plus_image, GtkAlign::GTK_ALIGN_END);
+ g_object_unref(plus_pixbuf);
+
+ GdkPixbuf *hide_pixbuf = gdk_pixbuf_new_from_file_at_size(notes->imageFile("hide").c_str(),
+ width, height, nullptr
+ );
+ _hide_image = gtk_image_new_from_pixbuf(hide_pixbuf);
+ gtk_widget_set_halign(_plus_image, GtkAlign::GTK_ALIGN_END);
+ g_object_unref(hide_pixbuf);
+
+ gtk_container_add(_note_header, _color_image);
+ gtk_container_add(_note_header, _title_label);
+ gtk_container_add(_note_header, _plus_image);
+ gtk_container_add(_note_header, _delete_image);
+ gtk_container_add(_note_header, _hide_image);
+
+ gtk_container_add(_scroll_widget, _text_widget);
+
+ gtk_container_add(_note_box, _note_header);
+ gtk_container_add(_note_box, _title_separator);
+ gtk_container_add(_note_box, _scroll_widget);
+
+ gtk_container_add(_frame, _note_box);
+ gtk_container_add(_evt_box, _frame);
+ gtk_container_add(_note_widget, _evt_box);
gtk_widget_show_all(_note_widget);
- {
- GdkWindow *w = gtk_widget_get_window(_title_label);
- int mask = GDK_BUTTON1_MOTION_MASK + GDK_BUTTON_PRESS_MASK + GDK_BUTTON_RELEASE_MASK;
- gdk_window_set_events(w, static_cast(mask));
- }
-
+ //GdkWindow *window = gdk_window_get_effective_toplevel(gtk_widget_get_window(_note_widget));
+ //gdk_window_set_events(window, static_cast(gdk_window_get_events(window) | GDK_VISIBILITY_NOTIFY_MASK));
+ //gdk_window_set_override_redirect(window, true);
g_signal_connect(_note_widget, "size_allocate", on_size_allocated, this);
- g_signal_connect(_header_evt_box, "button_press_event", on_button_press, this);
- g_signal_connect(_header_evt_box, "button_release_event", on_button_release, this);
- g_signal_connect(_header_evt_box, "motion_notify_event", on_mouse_move, this);
+ g_signal_connect(_evt_box, "button_press_event", on_button_press, this);
+ g_signal_connect(_evt_box, "button_release_event", on_button_release, this);
+ g_signal_connect(_evt_box, "motion_notify_event", on_mouse_move, this);
+ g_signal_connect(_title_entry, "activate", on_title_activate, this);
+ g_signal_connect(_title_entry, "key_press_event", on_title_escape, this);
+ g_signal_connect(_title_entry, "focus_out_event", on_title_focus_out, this);
+ g_signal_connect(_buffer, "changed", on_text_change, this);
+ g_signal_connect(_note_widget, "visibility_notify_event", on_window_present, this);
+
+ // Keep label and entry of title alive
+ g_object_ref(_title_label);
+ g_object_ref(_title_entry);
+ g_object_ref(_delete_image);
+ g_object_ref(_plus_image);
+ g_object_ref(_hide_image);
load();
@@ -271,10 +761,81 @@ YellowNote::YellowNote(const std::string &filename) {
YellowNote::~YellowNote()
{
+ g_object_unref(_title_label);
+ g_object_unref(_title_entry);
+ g_object_unref(_delete_image);
+ g_object_unref(_plus_image);
+ g_object_unref(_hide_image);
gtk_widget_destroy(_note_widget);
_note_widget = nullptr;
}
+void YellowNote::updateWidgetColors(GtkWidget *w)
+{
+ auto set_style = [this](GtkWidget *widget) {
+ GtkStyleContext *c = gtk_widget_get_style_context(widget);
+ const char *style = gtk_style_context_to_string(c, GTK_STYLE_CONTEXT_PRINT_RECURSE);
+ GtkCssProvider *css = gtk_css_provider_new();
+ gtk_style_context_add_provider(c, css, GTK_STYLE_PROVIDER_PRIORITY_USER);
+ std::string widget_css = _notes->css(_color);
+ gtk_css_provider_load_from_data(css, widget_css.c_str(), widget_css.size(), nullptr);
+ };
+
+ set_style(w);
+}
+
+void YellowNote::updateColor()
+{
+
+ auto set_style = [this](GtkWidget *w) {
+ this->updateWidgetColors(w);
+ };
+
+ set_style(_title_label);
+ set_style(_note_header);
+ set_style(_text_widget);
+ set_style(_note_widget);
+ set_style(_frame);
+}
+
+void YellowNote::nextColor()
+{
+ int c = _color;
+ c += 1;
+ _color = static_cast(c);
+ if (_color > ColorType_t::LAST) {
+ _color = ColorType_t::FIRST;
+ }
+ save();
+ updateColor();
+}
+
+void YellowNote::addNew()
+{
+ _notes->newNote(this);
+}
+
+void YellowNote::deleteMe()
+{
+ GtkWidget *msg = gtk_message_dialog_new(_note_widget,
+ GtkDialogFlags::GTK_DIALOG_MODAL,
+ GtkMessageType::GTK_MESSAGE_QUESTION,
+ GtkButtonsType::GTK_BUTTONS_YES_NO,
+ "%s", "Are you sure you want to delete this note?"
+ );
+ updateWidgetColors(msg);
+
+ int response = gtk_dialog_run(msg);
+ gtk_widget_destroy (msg);
+
+ if (response == GTK_RESPONSE_YES) {
+ _notes->remove(this);
+ std::filesystem::path p(_filename);
+ std::filesystem::remove(p);
+ delete this;
+ }
+}
+
void YellowNote::updateTitle()
{
gtk_label_set_label(_title_label, _title.c_str());
@@ -296,21 +857,34 @@ void YellowNote::updateSize()
gtk_window_resize(_note_widget, _width, _height);
}
+void YellowNote::showNote(GtkWidget *sender)
+{
+ show();
+}
+
void YellowNote::show()
{
gtk_widget_show_all(_note_widget);
+ _hidden = false;
+ save();
}
void YellowNote::hide()
{
gtk_widget_hide(_note_widget);
+ _hidden = true;
+ save();
}
-
-void YellowNote::changed()
+void YellowNote::changed(GtkWidget *sender)
{
bool sv = false;
+ if (_color_changed) {
+ _color_changed = true;
+ sv = true;
+ }
+
bool hidden = !gtk_widget_is_visible(_note_widget);
if (hidden != _hidden) {
_hidden = hidden;
@@ -344,7 +918,6 @@ void YellowNote::changed()
sv = true;
}
-
const char *c_t = gtk_label_get_text (_title_label);
if (c_t != nullptr) {
std::string t(c_t);
@@ -357,42 +930,317 @@ void YellowNote::changed()
if (sv) { save(); }
}
-void YellowNote::size_allocated(GtkAllocation *a)
+void YellowNote::size_allocated(GtkWidget *sender, GtkAllocation *a)
{
- changed();
+ changed(sender);
}
-bool YellowNote::move_begin(GdkEventButton *evt)
+void YellowNote::toFront()
{
- std::cout << "move_begin" << std::endl;
- _moving = true;
- _x_orig = evt->x_root;
- _y_orig = evt->y_root;
- return true;
+ if (_hidden) {
+ gtk_window_move(_note_widget, _x, _y);
+ gtk_widget_hide(_note_widget);
+ } else {
+ gtk_window_present(_note_widget);
+ gtk_window_move(_note_widget, _x, _y);
+ }
}
-bool YellowNote::move_end(GdkEventButton *evt)
+void YellowNote::get_header_screen_coords(int &header_top, int &header_bottom)
{
- std::cout << "move_end" << std::endl;
- _moving = false;
- return true;
+ int left, top;
+ gtk_window_get_position(_note_widget, &left, &top);
+ header_top = top;
+
+ GtkAllocation alloc;
+ gtk_widget_get_allocation(_note_header, &alloc);
+ header_bottom = alloc.y + alloc.height + top;
}
-bool YellowNote::moving(GdkEventMotion *evt)
+void YellowNote::get_frame_screen_coords(int &frame_bottom, int &frame_right)
+{
+ int left, top;
+ gtk_window_get_position(_note_widget, &left, &top);
+ GtkAllocation alloc;
+
+ gtk_widget_get_allocation(_scroll_widget, &alloc);
+ frame_bottom = alloc.y + alloc.height + top;
+ frame_right = alloc.x + alloc.width + left;
+}
+
+void YellowNote::get_screen_left_right(GtkWidget *widget, int &left, int &right)
+{
+ int wleft, wtop;
+ gtk_window_get_position(_note_widget, &wleft, &wtop);
+ GtkAllocation alloc;
+
+ gtk_widget_get_allocation(widget, &alloc);
+ left = wleft + alloc.x;
+ right = left + alloc.width;
+}
+
+void YellowNote::adjustTitle(bool mutate)
+{
+ if (!_editing_title) { return; }
+ _editing_title = false;
+
+ if (mutate) {
+ std::string _old_title = _title;
+ _title = gtk_entry_get_text(_title_entry);
+ trim(_title);
+ gtk_label_set_label(_title_label, _title.c_str());
+ save();
+ }
+
+ gtk_container_remove(_note_header, _title_entry);
+ gtk_container_add(_note_header, _title_label);
+ gtk_container_remove(_note_header, _plus_image);
+ gtk_container_add(_note_header, _plus_image);
+ gtk_container_remove(_note_header, _delete_image);
+ gtk_container_add(_note_header, _delete_image);
+ gtk_container_remove(_note_header, _hide_image);
+ gtk_container_add(_note_header, _hide_image);
+}
+
+bool YellowNote::windowPresented(void *sender, GdkEventVisibility *evt) // TODO according to docs this must not be a pointer
+{
+ return false;
+}
+
+std::string YellowNote::title()
+{
+ return _title;
+}
+
+bool YellowNote::isHidden()
+{
+ return _hidden;
+}
+
+void YellowNote::textChanged(void *sender)
+{
+ if (_in_transaction) return;
+
+ std::cout << "Changed " << _save_id << std::endl;
+ _save_counter++;
+ if (_save_id == -1) {
+ std::cout << "Starting save timer" << std::endl;
+ _save_id = _save_counter;
+ g_timeout_add(1000, on_text_save_timeout, this);
+ }
+}
+
+bool YellowNote::textSaveTimeout()
+{
+ if (_save_counter != _save_id) {
+ std::cout << "Something changed" << std::endl;
+ _save_id = _save_counter;
+ g_timeout_add(1000, on_text_save_timeout, this);
+ return false;
+ } else {
+ _save_id = -1;
+ std::cout << "Saving" << std::endl;
+ save();
+ return false;
+ }
+}
+
+void YellowNote::titleEnter(GtkWidget *sender)
+{
+ adjustTitle(true);
+}
+
+bool YellowNote::titleEscape(GtkWidget *sender, GdkEventKey *key)
+{
+ if (key->keyval == GDK_KEY_Escape && _editing_title) {
+ adjustTitle(false);
+ return true;
+ }
+ return false;
+}
+
+bool YellowNote::titleFocusOut(GtkWidget *sender, GdkEventFocus *evt)
+{
+ if (_editing_title) {
+ adjustTitle(false);
+ return true;
+ }
+ return false;
+}
+
+#define AROUND(c, n) ((c >= (n - threshold)) && (c <= (n + threshold)))
+
+bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt)
{
int x = evt->x_root;
int y = evt->y_root;
- int dx = x - _x_orig;
- int dy = y - _y_orig;
+ int header_top, header_bottom;
+ get_header_screen_coords(header_top, header_bottom);
- std::cout << "moving " << x << ", " << y << ", dx = " << dx << ", dy = " << dy << ", _x = " << _x << ", _y = " << y << std::endl;
+ int frame_bottom, frame_right;
+ get_frame_screen_coords(frame_bottom, frame_right);
- //gtk_window_move(_note_widget, _x + dx, _y + dy);
+ int color_left, color_right;
+ get_screen_left_right(_color_image, color_left, color_right);
+
+ int delete_left, delete_right;
+ get_screen_left_right(_delete_image, delete_left, delete_right);
+
+ int plus_left, plus_right;
+ get_screen_left_right(_plus_image, plus_left, plus_right);
+
+ int hide_left, hide_right;
+ get_screen_left_right(_hide_image, hide_left, hide_right);
+
+ if (y >= header_top && y <= header_bottom) {
+ if (x >= color_left && x <= color_right) {
+ nextColor();
+ return true;
+ }
+ if (x >= plus_left && x <= plus_right) {
+ addNew();
+ return true;
+ }
+ if (x >= hide_left && x <= hide_right) {
+ hide();
+ return true;
+ }
+ if (x >= delete_left && x <= delete_right) {
+ deleteMe();
+ return true;
+ }
+ }
+
+ if (evt->type == GDK_2BUTTON_PRESS) {
+ gtk_container_remove(_note_header, _title_label);
+ gtk_container_add(_note_header, _title_entry);
+ gtk_container_remove(_note_header, _plus_image);
+ gtk_container_add(_note_header, _plus_image);
+ gtk_container_remove(_note_header, _delete_image);
+ gtk_container_add(_note_header, _delete_image);
+ gtk_container_remove(_note_header, _hide_image);
+ gtk_container_add(_note_header, _hide_image);
+ gtk_widget_show(_title_entry);
+ gtk_entry_set_text(_title_entry, _title.c_str());
+ gtk_widget_grab_focus(_title_entry);
+ _editing_title = true;
+ return true;
+ }
+
+ if (y >= header_top && y <= header_bottom) {
+ _moving = true;
+ _x_orig = evt->x;
+ _y_orig = evt->y;
+ return true;
+ }
+
+ int threshold = 8;
+
+ if (AROUND(y, frame_bottom) && AROUND(x, frame_right)) {
+ _resize_edge = true;
+ } else if (AROUND(y, frame_bottom)) {
+ _resize_bottom = true;
+ } else if (AROUND(x, frame_right)) {
+ _resize_right = true;
+ }
return false;
}
+bool YellowNote::move_end(GtkWidget *sender, GdkEventButton *evt)
+{
+ if (_moving) {
+ _moving = false;
+ return true;
+ }
+
+ if (_resize_edge || _resize_bottom || _resize_right) {
+ _resize_edge = false;
+ _resize_bottom = false;
+ _resize_right = false;
+ return true;
+ }
+ return false;
+}
+
+bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt)
+{
+ int x = evt->x_root;
+ int y = evt->y_root;
+
+ if (_moving) {
+ int the_x = x - _x_orig;
+ int the_y = y - _y_orig;
+ gtk_window_move(_note_widget, the_x, the_y);
+ return true;
+ }
+
+ if (_resize_bottom || _resize_right || _resize_edge) {
+ if (_resize_edge) {
+ int left, top;
+ gtk_window_get_position(_note_widget, &left, &top);
+ int width = x - left;
+ int height = y - top;
+ if (width < 100) { width = 100; }
+ if (height < 60) { height = 60; }
+ gtk_window_resize(_note_widget, width, height);
+ return true;
+ }
+
+ if (_resize_right) {
+ int left, top;
+ gtk_window_get_position(_note_widget, &left, &top);
+ int w, h;
+ gtk_window_get_size(_note_widget, &w, &h);
+ int width = x - left;
+ if (width < 100) { width = 100; }
+ gtk_window_resize(_note_widget, width, h);
+ return true;
+ }
+
+ if (_resize_bottom) {
+ int left, top;
+ gtk_window_get_position(_note_widget, &left, &top);
+ int w, h;
+ gtk_window_get_size(_note_widget, &w, &h);
+ int height = y - top;
+ if (height < 60) { height = 60; }
+ gtk_window_resize(_note_widget, w, height);
+ return true;
+ }
+ }
+
+ int frame_bottom, frame_right;
+ get_frame_screen_coords(frame_bottom, frame_right);
+
+ int header_top, header_bottom;
+ get_header_screen_coords(header_top, header_bottom);
+
+ GdkWindow *window = gtk_widget_get_window(_frame);
+ GdkCursor *c;
+
+ int threshold = 8;
+
+ if (y >= header_top && y <= header_bottom) {
+ c = gdk_cursor_new(GDK_LEFT_PTR);
+ } else if (AROUND(x, frame_right) && AROUND(y, frame_bottom)) {
+ c = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
+ } else if (AROUND(x, frame_right)) {
+ c = gdk_cursor_new(GDK_RIGHT_SIDE);
+ } else if (AROUND(y, frame_bottom)) {
+ c = gdk_cursor_new(GDK_BOTTOM_SIDE);
+ } else {
+ c = nullptr;
+ }
+
+ gdk_window_set_cursor(window, c);
+ if (c) g_object_unref(c);
+
+ return false;
+}
+
+#define YELLOWNOTE_VERSION 1
void YellowNote::load()
{
@@ -409,8 +1257,6 @@ void YellowNote::load()
_in_transaction = true;
std::filesystem::path p(_filename);
- const auto base_name = p.filename().string();
- _title = base_name.substr(0, base_name.rfind(".note"));
size_t s = 0;
if (std::filesystem::is_regular_file(p)) {
@@ -419,15 +1265,27 @@ void YellowNote::load()
FILE *f = fopen(_filename.c_str(), "rt");
if (f) {
+ int version = readInt(f, -1);
+
_hidden = readInt(f, -1);
_x = readInt(f, 200);
_y = readInt(f, 200);
_width = readInt(f, 300);
_height = readInt(f, 200);
- int pos = ftell(f);
+ int color;
+ color = readInt(f, ColorType_t::YELLOW);
+ _color = static_cast(color);
+
char *buf = static_cast(malloc(s));
memset(buf, 0, s);
+
+ fgets(buf, s, f);
+ _title = buf;
+ trim(_title);
+
+ memset(buf, 0, s);
+ int pos = ftell(f);
int bytes = s - pos;
fread(buf, bytes, 1, f);
@@ -437,9 +1295,10 @@ void YellowNote::load()
}
updateTitle();
- updateHidden();
+ updateColor();
updatePosition();
updateSize();
+ updateHidden();
_in_transaction = false;
}
@@ -453,11 +1312,14 @@ void YellowNote::save()
std::filesystem::path p(_filename);
FILE *f = fopen(_filename.c_str(), "wt");
if (f) {
+ fprintf(f, "%d\n", YELLOWNOTE_VERSION);
fprintf(f, "%d\n", _hidden);
fprintf(f, "%d\n", _x);
fprintf(f, "%d\n", _y);
fprintf(f, "%d\n", _width);
fprintf(f, "%d\n", _height);
+ fprintf(f, "%d\n", _color);
+ fprintf(f, "%s\n", _title.c_str());
GtkTextIter start, end;
gtk_text_buffer_get_start_iter(_buffer, &start);
@@ -465,7 +1327,7 @@ void YellowNote::save()
gchar *text = gtk_text_buffer_get_text(_buffer, &start, &end, false);
fprintf(f, "%s", text);
fclose(f);
- free(text);
+ g_free(text);
}
}
diff --git a/yellownotes.h b/yellownotes.h
index 91ee34f..11d02d5 100644
--- a/yellownotes.h
+++ b/yellownotes.h
@@ -3,15 +3,43 @@
#include
#include
+#include
+
+extern "C" {
+#include "gtk-imports.h"
+}
class YellowNote;
+typedef enum {
+ DARK = 0,
+ FIRST= DARK,
+ YELLOW,
+ ORANGE,
+ BLUE,
+ CYAAN,
+ GREEN,
+ RED,
+ GREY,
+ LAST = GREY
+} ColorType_t;
+
class YellowNotes
{
private:
void *_tray_menu;
void *_app;
+ void *_dlg;
+ void *_langs;
+
std::list _notes;
+ int _font_size;
+ GtkWindow *_toplevel;
+ std::unordered_map _cfg;
+
+private:
+ void loadConfig();
+ void saveConfig();
public:
void loadNotes();
@@ -21,11 +49,27 @@ public:
std::string imageFile(const char *name);
std::string appDir();
std::string notesDir();
+ std::string css(ColorType_t type);
+ int fontSize();
+ int iconSize();
+ GtkWindow *topLevel();
public:
- void popupTrayMenu();
- void newNote();
- void quit();
+ void popupTrayMenu(void *sender);
+ void newNote(void *sender);
+ void showNotes(void *sender);
+ void reloadNotes(void *sender);
+ void quit(void *sender);
+ void topLevelHidden(GtkWidget *sender);
+ void setup(void *sender);
+ void setupClose(GtkWidget *sender);
+ void setupCancel(GtkWidget *sender);
+ bool setupDel(GtkWidget *sender, void *evt);
+ void remove(YellowNote *n);
+
+public:
+ std::string currentLang();
+ void setCurrentLang(const std::string &l);
public:
YellowNotes(void *app);
@@ -34,12 +78,15 @@ public:
#define YELLOWNOTES(obj) reinterpret_cast(obj)
#define SIGNAL(type, func, member) \
- static void func(GObject *obj, gpointer user_data) { type *o = reinterpret_cast(user_data); o->member(); }
+ static void func(GObject *obj, gpointer user_data) { type *o = reinterpret_cast(user_data); o->member(obj); }
+
+#define BSIGNAL(type, func, member) \
+ static gboolean func(GObject *obj, gpointer user_data) { std::cout << user_data << std::endl; type *o = reinterpret_cast(user_data); return o->member(obj); }
#define SIGNAL2(type, func, member, argtype) \
- static void func(GObject *obj, void *arg, gpointer user_data) { type *o = reinterpret_cast(user_data); o->member(reinterpret_cast(arg)); }
+ static void func(GObject *obj, void *arg, gpointer user_data) { type *o = reinterpret_cast(user_data); o->member(obj, reinterpret_cast(arg)); }
#define BSIGNAL2(type, func, member, argtype) \
- static gboolean func(GObject *obj, void *arg, gpointer user_data) { type *o = reinterpret_cast(user_data); return o->member(reinterpret_cast(arg)); }
+ static gboolean func(GObject *obj, void *arg, gpointer user_data) { type *o = reinterpret_cast(user_data); return o->member(obj, reinterpret_cast(arg)); }
#endif // YELLOWNOTES_H