summaryrefslogtreecommitdiff
path: root/src/user/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/settings')
-rw-r--r--src/user/settings/color_editor.cpp16
-rw-r--r--src/user/settings/color_editor.h19
-rw-r--r--src/user/settings/editor.cpp30
-rw-r--r--src/user/settings/editor.h20
-rw-r--r--src/user/settings/main.cpp191
-rw-r--r--src/user/settings/model.cpp4
-rw-r--r--src/user/settings/model.h24
-rw-r--r--src/user/settings/str_editor.cpp17
-rw-r--r--src/user/settings/str_editor.h19
9 files changed, 340 insertions, 0 deletions
diff --git a/src/user/settings/color_editor.cpp b/src/user/settings/color_editor.cpp
new file mode 100644
index 0000000..1673824
--- /dev/null
+++ b/src/user/settings/color_editor.cpp
@@ -0,0 +1,16 @@
+#include "color_editor.h"
+
+color_editor::color_editor(struct setting *s, const char *sname)
+ : c(&s->data.color), p(s->data.color) {
+ editing_widget_ready(p, sname);
+}
+
+#include <knob/format.h>
+
+void color_editor::set_data() {
+ const _pixel_t new_c = p.get_picked_color();
+ if ((c->r != new_c.r) || (c->g != new_c.g) || (c->b != new_c.b)) {
+ *c = new_c;
+ main_w->is_saved = false;
+ }
+} \ No newline at end of file
diff --git a/src/user/settings/color_editor.h b/src/user/settings/color_editor.h
new file mode 100644
index 0000000..c41ec3f
--- /dev/null
+++ b/src/user/settings/color_editor.h
@@ -0,0 +1,19 @@
+#ifndef COLOR_EDITOR_H
+#define COLOR_EDITOR_H
+
+#include <raleigh/w/colorpicker.h>
+
+#include "editor.h"
+#include "model.h"
+
+class color_editor : public editor {
+public:
+ color_editor(struct setting *s, const char *sname);
+ void set_data() override;
+
+private:
+ _pixel_t *c;
+ colorpicker p;
+};
+
+#endif \ No newline at end of file
diff --git a/src/user/settings/editor.cpp b/src/user/settings/editor.cpp
new file mode 100644
index 0000000..1804a85
--- /dev/null
+++ b/src/user/settings/editor.cpp
@@ -0,0 +1,30 @@
+#include <raleigh/w/padding.h>
+#include <raleigh/w/button.h>
+#include <raleigh/w/label.h>
+#include <raleigh/w/vbox.h>
+#include "editor.h"
+
+bool editor_save(window_tag_t e) {
+ ((editor *)e)->set_data();
+ return true;
+}
+
+editor::editor()
+ : w(0) {}
+
+void editor::editing_widget_ready(widget &e, const char *s) {
+ label *l = new label(s);
+ padding *p = new padding(*l, 4);
+
+ dllist<widget &> *list = new dllist<widget &>();
+ list->add_back(*p);
+ list->add_back(e);
+
+ vbox *box = new vbox(*list);
+
+ w = new window(*box, RGB(bf, bf, bf), &editor_save, this);
+}
+
+void editor::show() {
+ w->show();
+} \ No newline at end of file
diff --git a/src/user/settings/editor.h b/src/user/settings/editor.h
new file mode 100644
index 0000000..2980884
--- /dev/null
+++ b/src/user/settings/editor.h
@@ -0,0 +1,20 @@
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#include <raleigh/d/saving_window.h>
+
+using namespace raleigh;
+
+class editor {
+ friend bool editor_save(window_tag_t e);
+public:
+ void show();
+protected:
+ editor();
+ void editing_widget_ready(widget &e, const char *sname);
+ virtual void set_data() = 0;
+private:
+ window *w;
+};
+
+#endif \ No newline at end of file
diff --git a/src/user/settings/main.cpp b/src/user/settings/main.cpp
new file mode 100644
index 0000000..2045137
--- /dev/null
+++ b/src/user/settings/main.cpp
@@ -0,0 +1,191 @@
+#include <raleigh/d/saving_window.h>
+#include <raleigh/w/padding.h>
+#include <raleigh/w/button.h>
+#include <raleigh/w/label.h>
+#include <raleigh/w/vbox.h>
+#include <structs/map.h>
+#include <knob/format.h>
+#include <knob/file.h>
+#include <stdint.h>
+
+#include "color_editor.h"
+#include "str_editor.h"
+#include "model.h"
+
+struct file_header {
+ uint32_t main_offset;
+ uint32_t main_entries;
+ uint32_t names_offset;
+ uint32_t data_offset;
+} __attribute__ ((packed));
+
+struct main_entry {
+ uint32_t name_offset;
+ uint8_t name_len;
+ enum : uint8_t {
+ STRING = 0,
+ COLOR
+ } kind;
+ uint16_t pad;
+ union {
+ struct {
+ uint32_t data_offset;
+ uint32_t data_len;
+ } as_string;
+ _pixel_t as_color;
+ };
+} __attribute__ ((packed));
+
+#define SETTINGS_FILE "sys/settings.pls"
+
+using namespace raleigh;
+
+bool save(save_tag_t) {
+ struct file *f = open_file(SETTINGS_FILE);
+ struct file_header fh;
+ fh.main_offset = sizeof(struct file_header);
+ fh.main_entries = settings.n_entries;
+ fh.names_offset = fh.main_offset + sizeof(struct main_entry) * settings.n_entries;
+
+ uint32_t name_i = 0;
+ uint32_t data_i = 0;
+ seek_file_to(f, sizeof(struct file_header));
+ struct main_entry me;
+
+ for (struct setting *i = settings.buf; i < settings.buf + settings.n_entries; ++i) {
+ me.name_offset = name_i;
+ me.name_len = strlen(i->name);
+ name_i += me.name_len;
+
+ switch (i->kind) {
+ case setting::STRING:
+ me.kind = main_entry::STRING;
+ me.as_string.data_offset = data_i;
+ me.as_string.data_len = strlen(i->data.string);
+ data_i += me.as_string.data_len;
+ break;
+ case setting::COLOR:
+ me.kind = main_entry::COLOR;
+ me.as_color = i->data.color;
+ break;
+ }
+
+ write_to_file(f, sizeof(struct main_entry), &me);
+ }
+
+ seek_file_to(f, fh.names_offset);
+ for (struct setting *i = settings.buf; i < settings.buf + settings.n_entries; ++i)
+ write_to_file(f, strlen(i->name), (void *)i->name);
+
+ fh.data_offset = get_file_pos(f);
+ for (struct setting *i = settings.buf; i < settings.buf + settings.n_entries; ++i)
+ switch (i->kind) {
+ case setting::STRING:
+ write_to_file(f, strlen(i->data.string), (void *)i->data.string);
+ break;
+ default:
+ break;
+ }
+
+ trunc_file(f);
+ seek_file_to(f, 0);
+ write_to_file(f, sizeof(struct file_header), &fh);
+ close_file(f);
+
+ main_w->is_saved = true;
+ return true;
+}
+
+void on_button_click(button_tag_t n) {
+ struct setting *const s = settings.buf + (uint32_t)n;
+ editor *e;
+ switch (s->kind) {
+ case setting::STRING:
+ e = new str_editor(s, s->name);
+ break;
+ case setting::COLOR:
+ e = new color_editor(s, s->name);
+ break;
+ default:
+ show_error_and_quitf("Internal model corrupted: setting %s had type 0x%2x.", s->name, s->kind);
+ }
+ e->show();
+}
+
+button *make_button(uint32_t i) {
+ label *l = new label(settings.buf[i].name);
+ padding *p = new padding(*l, 2);
+ return new button(*p, &on_button_click, (button_tag_t)i);
+}
+
+void main() {
+ struct file *f = open_file(SETTINGS_FILE);
+
+ struct file_header file_head;
+ read_from_file(f, sizeof(struct file_header), &file_head);
+
+ settings = alist<struct setting>(file_head.main_entries + 10);
+
+ dllist<widget &> for_vbox;
+
+ label l("Click a setting name below to edit its value.");
+ label l2("A restart is required for changes to take effect.");
+
+ dllist<widget &> for_subbox;
+ for_subbox.add_back(l);
+ for_subbox.add_back(l2);
+ vbox subbox(for_subbox);
+
+ padding p_subbox(subbox, 2);
+ for_vbox.add_back(p_subbox);
+
+ for (uint32_t i = 0; i < file_head.main_entries; ++i) {
+ struct main_entry entry;
+ seek_file_to(f, file_head.main_offset + i * sizeof(struct main_entry));
+ read_from_file(f, sizeof(struct main_entry), &entry);
+
+ char *const sname = new char[entry.name_len + 1];
+ seek_file_to(f, file_head.names_offset + entry.name_offset);
+ read_from_file(f, entry.name_len, sname);
+ sname[entry.name_len] = '\0';
+
+ switch (entry.kind) {
+ char *sz;
+ struct setting s;
+ case main_entry::STRING:
+ sz = new char[entry.as_string.data_len + 1];
+ seek_file_to(f, file_head.data_offset + entry.as_string.data_offset);
+ read_from_file(f, entry.as_string.data_len, sz);
+ sz[entry.as_string.data_len] = '\0';
+
+ s.kind = setting::STRING;
+ s.data.string = sz;
+ s.name = sname;
+ settings.add_back(s);
+ break;
+
+ case main_entry::COLOR:
+ s.kind = setting::COLOR;
+ s.data.color = entry.as_color;
+ s.name = sname;
+ settings.add_back(s);
+ break;
+ default:
+ show_error_and_quitf("Refusing to open " SETTINGS_FILE ":\n\"%s\" has unrecognized type id 0x%2x.\nHighest known is 0x01.", sname, entry.kind);
+ }
+
+ button *const b = make_button(settings.n_entries - 1);
+
+ padding *p = new padding(*b, 2);
+ for_vbox.add_back(*p);
+ }
+
+ close_file(f);
+
+ vbox box(for_vbox);
+ padding pbox(box, 2);
+
+ main_w = new saving_window(&save, 0, pbox);
+ main_w->show();
+ start_runtime();
+} \ No newline at end of file
diff --git a/src/user/settings/model.cpp b/src/user/settings/model.cpp
new file mode 100644
index 0000000..e27de0d
--- /dev/null
+++ b/src/user/settings/model.cpp
@@ -0,0 +1,4 @@
+#include "model.h"
+
+alist<struct setting> settings;
+raleigh::saving_window *main_w; \ No newline at end of file
diff --git a/src/user/settings/model.h b/src/user/settings/model.h
new file mode 100644
index 0000000..0c9b1d2
--- /dev/null
+++ b/src/user/settings/model.h
@@ -0,0 +1,24 @@
+#ifndef MODEL_H
+#define MODEL_H
+
+#include <raleigh/d/saving_window.h>
+#include <structs/alist.h>
+
+union setting_data {
+ char *string;
+ _pixel_t color;
+};
+
+struct setting {
+ enum {
+ STRING,
+ COLOR
+ } kind;
+ union setting_data data;
+ const char *name;
+};
+
+extern alist<struct setting> settings;
+extern raleigh::saving_window *main_w;
+
+#endif \ No newline at end of file
diff --git a/src/user/settings/str_editor.cpp b/src/user/settings/str_editor.cpp
new file mode 100644
index 0000000..5e86e96
--- /dev/null
+++ b/src/user/settings/str_editor.cpp
@@ -0,0 +1,17 @@
+#include <knob/block.h>
+
+#include "str_editor.h"
+
+str_editor::str_editor(struct setting *s, const char *sname)
+ : e(10, 25, s->data.string), s(&s->data.string) {
+ editing_widget_ready(e, sname);
+}
+
+void str_editor::set_data() {
+ const char *const contents = e.get_contents();
+ if (strequ(contents, *s))
+ return;
+ delete *s;
+ *s = strdup(contents);
+ main_w->is_saved = false;
+} \ No newline at end of file
diff --git a/src/user/settings/str_editor.h b/src/user/settings/str_editor.h
new file mode 100644
index 0000000..02bd7d8
--- /dev/null
+++ b/src/user/settings/str_editor.h
@@ -0,0 +1,19 @@
+#ifndef STR_EDITOR_H
+#define STR_EDITOR_H
+
+#include <raleigh/w/entry.h>
+
+#include "editor.h"
+#include "model.h"
+
+class str_editor : public editor {
+public:
+ str_editor(struct setting *s, const char *sname);
+ void set_data() override;
+
+private:
+ entry e;
+ char **s;
+};
+
+#endif \ No newline at end of file