summaryrefslogtreecommitdiffstats
path: root/src/message-stack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/message-stack.cpp')
-rw-r--r--src/message-stack.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/message-stack.cpp b/src/message-stack.cpp
new file mode 100644
index 0000000..cebd5f2
--- /dev/null
+++ b/src/message-stack.cpp
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MessageStack - manages stack of active status messages
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright (C) 2004 MenTaLguY
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include <cstring>
+#include <glib.h>
+#include <cstring>
+#include "message-stack.h"
+
+namespace Inkscape {
+
+MessageStack::MessageStack()
+: _messages(nullptr), _next_id(1)
+{
+}
+
+MessageStack::~MessageStack()
+{
+ while (_messages) {
+ _messages = _discard(_messages);
+ }
+}
+
+MessageId MessageStack::push(MessageType type, gchar const *message) {
+ return _push(type, 0, message);
+}
+
+MessageId MessageStack::pushF(MessageType type, gchar const *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ MessageId id=pushVF(type, format, args);
+ va_end(args);
+ return id;
+}
+
+MessageId MessageStack::pushVF(MessageType type, gchar const *format, va_list args)
+{
+ MessageId id;
+ gchar *message=g_strdup_vprintf(format, args);
+ id = push(type, message);
+ g_free(message);
+ return id;
+}
+
+void MessageStack::cancel(MessageId id) {
+ Message **ref;
+ for ( ref = &_messages ; *ref ; ref = &(*ref)->next ) {
+ if ( (*ref)->id == id ) {
+ *ref = _discard(*ref);
+ _emitChanged();
+ break;
+ }
+ }
+}
+
+MessageId MessageStack::flash(MessageType type, Glib::ustring const &message)
+{
+ MessageId id = flash( type, message.c_str() );
+ return id;
+}
+
+MessageId MessageStack::flash(MessageType type, gchar const *message) {
+ switch (type) {
+ case INFORMATION_MESSAGE: // stay rather long so as to seem permanent, but eventually disappear
+ return _push(type, 6000 + 80*strlen(message), message);
+ break;
+ case ERROR_MESSAGE: // pretty important stuff, but temporary
+ return _push(type, 4000 + 60*strlen(message), message);
+ break;
+ case WARNING_MESSAGE: // a bit less important than error
+ return _push(type, 2000 + 40*strlen(message), message);
+ break;
+ case IMMEDIATE_MESSAGE: // same length as normal, higher priority
+ return _push(type, 1000 + 20*strlen(message), message);
+ break;
+ case NORMAL_MESSAGE: // something ephemeral
+ default:
+ return _push(type, 1000 + 20*strlen(message), message);
+ break;
+ }
+}
+
+MessageId MessageStack::flashF(MessageType type, gchar const *format, ...) {
+ va_list args;
+ va_start(args, format);
+ MessageId id = flashVF(type, format, args);
+ va_end(args);
+ return id;
+}
+
+MessageId MessageStack::flashVF(MessageType type, gchar const *format, va_list args)
+{
+ gchar *message=g_strdup_vprintf(format, args);
+ MessageId id = flash(type, message);
+ g_free(message);
+ return id;
+}
+
+MessageId MessageStack::_push(MessageType type, guint lifetime, gchar const *message)
+{
+ Message *m=new Message;
+ MessageId id=_next_id++;
+
+ m->stack = this;
+ m->id = id;
+ m->type = type;
+ m->message = g_strdup(message);
+
+ if (lifetime) {
+ m->timeout_id = g_timeout_add(lifetime, &MessageStack::_timeout, m);
+ } else {
+ m->timeout_id = 0;
+ }
+
+ m->next = _messages;
+ _messages = m;
+
+ _emitChanged();
+
+ return id;
+}
+
+MessageStack::Message *MessageStack::_discard(MessageStack::Message *m)
+{
+ Message *next=m->next;
+ if (m->timeout_id) {
+ g_source_remove(m->timeout_id);
+ m->timeout_id = 0;
+ }
+ g_free(m->message);
+ m->message = nullptr;
+ m->stack = nullptr;
+ delete m;
+ return next;
+}
+
+void MessageStack::_emitChanged() {
+ if (_messages) {
+ _changed_signal.emit(_messages->type, _messages->message);
+ } else {
+ _changed_signal.emit(NORMAL_MESSAGE, nullptr);
+ }
+}
+
+gboolean MessageStack::_timeout(gpointer data) {
+ Message *m=reinterpret_cast<Message *>(data);
+ m->timeout_id = 0;
+ m->stack->cancel(m->id);
+ return FALSE;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :