From 5fcf57739e68a8b5053e03778aaee0eed445babd Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Thu, 11 Mar 2021 22:00:22 -0500 Subject: settings editor, and lots of changes in service of that --- src/user/settings/color_editor.cpp | 16 ++++ src/user/settings/color_editor.h | 19 ++++ src/user/settings/editor.cpp | 30 ++++++ src/user/settings/editor.h | 20 ++++ src/user/settings/main.cpp | 191 +++++++++++++++++++++++++++++++++++++ src/user/settings/model.cpp | 4 + src/user/settings/model.h | 24 +++++ src/user/settings/str_editor.cpp | 17 ++++ src/user/settings/str_editor.h | 19 ++++ 9 files changed, 340 insertions(+) create mode 100644 src/user/settings/color_editor.cpp create mode 100644 src/user/settings/color_editor.h create mode 100644 src/user/settings/editor.cpp create mode 100644 src/user/settings/editor.h create mode 100644 src/user/settings/main.cpp create mode 100644 src/user/settings/model.cpp create mode 100644 src/user/settings/model.h create mode 100644 src/user/settings/str_editor.cpp create mode 100644 src/user/settings/str_editor.h (limited to 'src/user/settings') 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 + +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 + +#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 +#include +#include +#include +#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 *list = new dllist(); + 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 + +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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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(file_head.main_entries + 10); + + dllist 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 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 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 +#include + +union setting_data { + char *string; + _pixel_t color; +}; + +struct setting { + enum { + STRING, + COLOR + } kind; + union setting_data data; + const char *name; +}; + +extern alist 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 + +#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 + +#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 -- cgit v1.2.3