This commit is contained in:
Er2 2021-11-07 20:14:25 +03:00
commit b6067074c0
25 changed files with 979 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*~
build/
# may be in fatpak, maybe not
.flatpak-builder

19
data/gresource.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/er2/cord">
<file>style.css</file>
<!-- file alias="style-dark.css">style-dark.css</file>
<file alias="add-note-symbolic.svg">icons/scalable/add-note-symbolic.svg</file>
<file alias="notebook-symbolic.svg">icons/scalable/notebook-symbolic.svg</file>
<file alias="notebook-config-symbolic.svg">icons/scalable/notebook-config-symbolic.svg</file>
<file alias="title_menu.ui">ui/title_menu.ui</file>
<file alias="shortcuts.ui">ui/shortcuts.ui</file>
<file alias="main_window.ui">ui/main_window.ui</file>
<file alias="menu.ui">ui/menu.ui</file>
<file alias="note_theme.ui">ui/note_theme.ui</file>
<file alias="note_menu.ui">ui/note_menu.ui</file>
<file alias="trash_note_menu.ui">ui/trash_note_menu.ui</file>
<file alias="edit_notebooks.ui">ui/edit_notebooks.ui</file>
<file alias="move_to_dialog.ui">ui/move_to_dialog.ui</file -->
</gresource>
</gresources>

10
data/gschema.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema path="/org/er2/cord/" id="org.er2.cord">
<key name="name" type="s">
<default>'Er2'</default>
<summary>Name</summary>
<description>The font to be used for content.</description>
</key>
</schema>
</schemalist>

21
data/meson.build Normal file
View File

@ -0,0 +1,21 @@
gnome = import('gnome')
i18n = import('i18n')
sch = gnome.compile_schemas(depend_files: 'gschema.xml')
res = gnome.compile_resources(
'res', 'gresource.xml',
source_dir: 'data',
c_name: 'as'
)
source += res
source += sch
schemas_dir = datadir /'glib-2.0'/'schemas'
install_data(
'gschema.xml',
install_dir: schemas_dir,
rename: [meson.project_name() + '.gschema.xml']
)
meson.add_install_script('glib-compile-schemas', schemas_dir)

9
data/style.css Normal file
View File

@ -0,0 +1,9 @@
window:not(.maximized) {
border-radius: 8px;
}
popover arrow {
background: rgba(0,0,0,0);
border: none;
}

52
meson.build Normal file
View File

@ -0,0 +1,52 @@
project('org.er2.cord', ['vala', 'c'], version: '1.0')
datadir = get_option('prefix') / get_option('datadir')
conf = configuration_data()
conf.set_quoted('ID', 'org.er2.cord') # meson.project_name())
conf.set_quoted('VERSION', meson.project_version())
conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
conf.set_quoted('DATADIR', get_option('prefix') / get_option('datadir'))
conf.set_quoted('GNOMELOCALEDIR', join_paths(get_option('prefix'), get_option('localedir')))
configure_file(output: 'config.h', configuration: conf)
add_project_arguments(
'-include', 'config.h',
language: 'c'
)
source = files(
'src/main.vala',
'src/Launcher.vala',
'src/api/Message.vala',
'src/api/User.vala',
'src/screens/Main.vala',
'src/screens/Settings.vala',
'src/screens/NewServer.vala',
'src/tools/Config.vala',
'src/tools/CConfig.vapi',
'src/widgets/Avatar.vala',
'src/widgets/Chat.vala',
'src/widgets/Message.vala',
'src/widgets/Scroller.vala',
)
deps = [
dependency('gtk4')
]
subdir('data')
subdir('po')
executable(
'er2cord',
source,
dependencies: deps,
install: true
)

1
po/LINGUAS Normal file
View File

@ -0,0 +1 @@
ru

5
po/POTFILES Normal file
View File

@ -0,0 +1,5 @@
../src/screens/Main.vala
../src/screens/Settings.vala
../src/screens/NewServer.vala
../src/api/User.vala
../src/widgets/Chat.vala

1
po/meson.build Normal file
View File

@ -0,0 +1 @@
i18n.gettext(meson.project_name(), preset: 'glib')

112
po/org.er2.cord.pot Normal file
View File

@ -0,0 +1,112 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2021 Er2
# This file is distributed under Zlib License.
# Er2 <er2@dismail.de>, 2021.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: org.er2.cord\n"
"Report-Msgid-Bugs-To: er2+tr@dismail.de\n"
"POT-Creation-Date: 2021-11-07 18:54+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Er2 <er2@dismail.de>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../src/screens/Main.vala:26
msgid "Er2Cord"
msgstr ""
#: ../src/screens/Main.vala:42
msgid "Send"
msgstr ""
#: ../src/screens/Main.vala:71
msgid "Me"
msgstr ""
#: ../src/screens/Main.vala:72 ../src/screens/Settings.vala:12
msgid "Settings"
msgstr ""
#: ../src/screens/Main.vala:73
msgid "Switch account"
msgstr ""
#: ../src/screens/Main.vala:74
msgid "Log off"
msgstr ""
#: ../src/screens/Main.vala:75
msgid "Quit"
msgstr ""
#: ../src/screens/Main.vala:79
msgid "Server"
msgstr ""
#: ../src/screens/Main.vala:80
msgid "Account"
msgstr ""
#: ../src/screens/Main.vala:81
msgid "Friend"
msgstr ""
#: ../src/screens/Main.vala:82
msgid "Invite"
msgstr ""
#: ../src/screens/Main.vala:84
msgid "New"
msgstr ""
#: ../src/screens/NewServer.vala:20
msgid "Enter"
msgstr ""
#: ../src/screens/NewServer.vala:45
msgid "Invite link"
msgstr ""
#: ../src/screens/NewServer.vala:47
msgid "Examples:\n"
msgstr ""
#: ../src/screens/NewServer.vala:57
msgid "Server name"
msgstr ""
#: ../src/screens/NewServer.vala:60
msgid "Server region"
msgstr ""
#: ../src/screens/NewServer.vala:62
msgid "By creating a server, you agree to Discord rules"
msgstr ""
#: ../src/screens/NewServer.vala:64
msgid "Join"
msgstr ""
#: ../src/screens/NewServer.vala:65
msgid "Create"
msgstr ""
#: ../src/api/User.vala:29
msgid "Clyde"
msgstr ""
#: ../src/widgets/Chat.vala:20
#, c-format
msgid "Welcome to %s!"
msgstr ""
#: ../src/widgets/Chat.vala:21
#, c-format
msgid "This is start of the %s."
msgstr ""

113
po/ru.po Normal file
View File

@ -0,0 +1,113 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2021 Er2
# This file is distributed under Zlib License.
# Er2 <er2@dismail.de>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: org.er2.cord\n"
"Report-Msgid-Bugs-To: er2+tr@dismail.de\n"
"POT-Creation-Date: 2021-11-07 18:54+0300\n"
"PO-Revision-Date: 2021-11-07 19:02+0300\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
"Last-Translator: \n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
"Language: ru\n"
#: ../src/screens/Main.vala:26
msgid "Er2Cord"
msgstr "Er2Cord"
#: ../src/screens/Main.vala:42
msgid "Send"
msgstr "Отправить"
#: ../src/screens/Main.vala:71
msgid "Me"
msgstr "Я"
#: ../src/screens/Main.vala:72 ../src/screens/Settings.vala:12
msgid "Settings"
msgstr "Настройки"
#: ../src/screens/Main.vala:73
msgid "Switch account"
msgstr "Сменить аккаунт"
#: ../src/screens/Main.vala:74
msgid "Log off"
msgstr "Выйти из аккаунта"
#: ../src/screens/Main.vala:75
msgid "Quit"
msgstr "Выход"
#: ../src/screens/Main.vala:79
msgid "Server"
msgstr "Сервер"
#: ../src/screens/Main.vala:80
msgid "Account"
msgstr "Аккаунт"
#: ../src/screens/Main.vala:81
msgid "Friend"
msgstr "Друг"
#: ../src/screens/Main.vala:82
msgid "Invite"
msgstr "Приглашение"
#: ../src/screens/Main.vala:84
msgid "New"
msgstr "Новый"
#: ../src/screens/NewServer.vala:20
msgid "Enter"
msgstr "Войти"
#: ../src/screens/NewServer.vala:45
msgid "Invite link"
msgstr "Ссылка приглашения"
#: ../src/screens/NewServer.vala:47
msgid "Examples:\n"
msgstr "Примеры:\n"
#: ../src/screens/NewServer.vala:57
msgid "Server name"
msgstr "Имя сервера"
#: ../src/screens/NewServer.vala:60
msgid "Server region"
msgstr "Регион сервера"
#: ../src/screens/NewServer.vala:62
msgid "By creating a server, you agree to Discord rules"
msgstr "Создавая этот сервер, вы соглашаетесь с правилами Discord"
#: ../src/screens/NewServer.vala:64
msgid "Join"
msgstr "Присоединиться"
#: ../src/screens/NewServer.vala:65
msgid "Create"
msgstr "Создать"
#: ../src/api/User.vala:29
msgid "Clyde"
msgstr "Клайд"
#: ../src/widgets/Chat.vala:20
#, c-format
msgid "Welcome to %s!"
msgstr "Добро пожаловать в %s!"
#: ../src/widgets/Chat.vala:21
#, c-format
msgid "This is start of the %s."
msgstr "Это начало канала %s."

48
src/Launcher.vala Normal file
View File

@ -0,0 +1,48 @@
/** Launcher of window
* (c) Er2 2021
* Zlib License
*/
namespace Er2Cord {
class Launcher : Gtk.Application {
public Config config;
public Launcher() {
Object(
application_id: ID,
flags: GLib.ApplicationFlags.FLAGS_NONE
);
actions();
config = new Config();
}
public override void activate() {
var win = this.active_window;
if(win == null) win = new AppWindow(this);
win.present();
}
public void actions() {
// App-only actions!
add_action_entries({
{"quit", () => quit()
, null, null, null},
{"settings", () => {
var wid = new Settings();
wid.config = this.config;
to_top(wid);
}, null, null, null},
{"serv", () => to_top(new NewServer())
, null, null, null},
}, this);
set_accels_for_action("app.quit", {"<Control>q"});
set_accels_for_action("app.settings", {"<Control>s"});
}
public void to_top(Gtk.Window wid) {
wid.transient_for = active_window;
wid.modal = true;
wid.application = this;
wid.present();
}
}
}

56
src/api/Message.vala Normal file
View File

@ -0,0 +1,56 @@
/** Message class
* (c) Er2 2021
* Zlib License
*/
namespace Er2Cord {
class Message {
public User user;
public string text;
public string date;
public Message? reply;
public MessageEmbed[]? embeds;
public Message(
string text,
User user,
string date = "unk.",
Message? reply = null,
MessageEmbed[]? embeds = null
) {
this.user = user;
this.text = text;
this.date = date;
this.reply = reply;
this.embeds = embeds;
}
}
enum EmbedType {
RICH,
IMAGE,
VIDEO,
GIF,
ARTICLE,
LINK,
}
struct EmbedField {
string name;
string value;
bool _inline;
}
struct MessageEmbed {
EmbedType type;
string? title;
string? description;
string? url;
// string? timestamp;
int? color;
//? footer;
//? image;
//? thumbnail;
//? video;
//? provider;
//? author;
EmbedField[]? fields;
}
}

41
src/api/User.vala Normal file
View File

@ -0,0 +1,41 @@
/** User class
* (c) Er2 2021
* Zlib License
*/
namespace Er2Cord {
class User {
public Avatar ava;
public string name;
public int discr;
public static double[] getColors(int k) {
switch(k) {
case 0: return {0.447, 0.537, 0.855};
case 1: return {0.459, 0.494, 0.541};
case 2: return {0.231, 0.647, 0.360};
case 3: return {0.980, 0.651, 0.102};
case 4: return {0.929, 0.259, 0.271};
case 5: return {0.922, 0.271, 0.624};
default: return {0.000, 0.000, 0.000};
}
}
public double[] color {
owned get { return getColors(discr % 5); }
}
public User(
string name = _("Clyde"),
int discr = 0000,
Avatar? ava = null
) {
this.name = name;
this.discr = discr;
if(ava == null)
this.ava = new Avatar.gen(name, color);
else this.ava = ava;
}
}
}

9
src/main.vala Normal file
View File

@ -0,0 +1,9 @@
/** Startup file
* (c) Er2 2021
* Zlib License
*/
static int main (string[] args) {
var app = new Er2Cord.Launcher();
return app.run(args);
}

36
src/meson.build Normal file
View File

@ -0,0 +1,36 @@
gnome = import('gnome')
schemas = gnome.compile_schemas()
source = files(
'main.vala',
'Launcher.vala',
'api/Message.vala',
'api/User.vala',
'screens/Main.vala',
'screens/Settings.vala',
'screens/NewServer.vala',
'tools/Config.vala',
'widgets/Avatar.vala',
'widgets/Chat.vala',
'widgets/Message.vala',
'widgets/Scroller.vala',
)
deps = [
dependency('gtk4')
]
executable(
'er2cord',
source,
schemas,
dependencies: deps,
install: true
)

101
src/screens/Main.vala Normal file
View File

@ -0,0 +1,101 @@
/** Main window
* (c) Er2 2021
* Zlib License
*/
using Gtk;
namespace Er2Cord {
Chat chat;
Scroller gld;
Scroller chn;
Scroller ppl;
Entry text;
class AppWindow : ApplicationWindow {
construct {
var css = new CssProvider();
css.load_from_resource("/org/er2/cord/style.css");
StyleContext.add_provider_for_display(
get_style_context().display,
css,
STYLE_PROVIDER_PRIORITY_USER
);
set_default_size(500, 500);
set_title(_("Er2Cord"));
set_titlebar(win_title());
chat = new Chat(new User());
gld = new Scroller();
chn = new Scroller(100);
ppl = new Scroller();
var main = new Grid();
main.column_spacing = 2;
main.attach(chat.scr, 2, 0);
main.attach(chat.user.ava, 0, 1);
main.attach(new Label(chat.user.name), 1, 1);
text = new Entry();
var send = new Button.with_label(_("Send"));
text.show_emoji_icon = true;
text.activate.connect(send_message);
send.clicked.connect(send_message);
main.attach(text, 2, 1);
main.attach(send, 3, 1);
main.attach(gld.scr, 0, 0);
main.attach(chn.scr, 1, 0);
main.attach(ppl.scr, 3, 0);
chat.send_message("hello");
child = main;
}
public Widget win_title() {
var bar = new HeaderBar();
var abtn = new MenuButton();
var mbtn = new MenuButton();
var aenu = new GLib.Menu();
var menu = new GLib.Menu();
var mfs = new GLib.Menu();
var mus = new GLib.Menu();
mfs.append(_("Me"), "app.me");
mfs.append(_("Settings"), "app.settings");
mus.append(_("Switch account"), "app.switch");
mus.append(_("Log off"), "app.logoff");
mus.append(_("Quit"), "app.quit");
menu.append_section(null, mfs);
menu.append_section(null, mus);
aenu.append(_("Server"), "app.serv");
aenu.append(_("Account"), "app.login");
aenu.append(_("Friend"), "app.friend");
aenu.append(_("Invite"), "app.invite");
abtn.label = _("New");
abtn.menu_model = aenu;
mbtn.menu_model = menu;
bar.pack_start(abtn);
bar.pack_end(new Separator(VERTICAL));
bar.pack_end(mbtn);
return bar;
}
public void send_message() {
chat.send_message(text.text);
text.text = "";
}
public AppWindow(Gtk.Application app) { Object(application: app); }
}
}

View File

@ -0,0 +1,68 @@
/** New server window
* (c) Er2 2021
* Zlib License
*/
using Gtk;
namespace Er2Cord {
class NewServer : Window {
Stack stack;
construct {
stack = new Stack();
stack.vexpand = stack.hexpand = true;
stack.transition_type = SLIDE_LEFT_RIGHT;
pages();
var main = new Box(VERTICAL, 2);
main.append(ava_info());
main.append(stack);
main.append(new Button.with_label(_("Enter")));
child = main;
set_titlebar(win_title());
}
public Widget win_title() {
var bar = new HeaderBar();
var swi = new StackSwitcher();
swi.stack = stack;
bar.title_widget = swi;
return bar;
}
public Box ava_info() {
var box = new Box(HORIZONTAL, 2);
box.halign = CENTER;
box.append(new Image.from_icon_name("avatar-default-symbolic"));
box.append(new Label("MyName at Discord"));
return box;
}
private void pages() {
var jpg = new Box(VERTICAL, 0);
var jlk = new Entry();
jlk.placeholder_text = _("Invite link");
jpg.append(jlk);
jpg.append(new Label(_("Examples:\n") +
"""https://discord.gg/discord
discord.gg/discord
discord
"""));
var cpg = new Grid();
var csn = new Entry();
var crg = new ComboBox();
cpg.row_homogeneous = cpg.column_homogeneous = true;
csn.placeholder_text = _("Server name");
cpg.attach(csn, 0, 0, 2, 1);
cpg.attach(crg, 1, 1);
cpg.attach(new Label(_("Server region")), 0, 1);
cpg.attach(new Label("TODO: Avatars"), 2, 0, 1, 2);
cpg.attach(new Label(_("By creating a server, you agree to Discord rules")), 0, 2, 2, 1);
stack.add_titled(jpg, "1", _("Join"));
stack.add_titled(cpg, "2", _("Create"));
}
}
}

28
src/screens/Settings.vala Normal file
View File

@ -0,0 +1,28 @@
/** Settings window
* (c) Er2 2021
* Zlib License
*/
using Gtk;
namespace Er2Cord {
class Settings : Window {
public Config config;
construct {
set_title(_("Settings"));
set_titlebar(win_title());
var main = new Grid();
main.column_spacing = 2;
var ent = new Entry();
child = main;
}
public Widget win_title() {
var bar = new HeaderBar();
return bar;
}
}
}

8
src/tools/CConfig.vapi Normal file
View File

@ -0,0 +1,8 @@
[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
namespace Er2Cord {
public const string ID;
public const string VERSION;
public const string GETTEXT_PACKAGE;
public const string DATADIR;
public const string GNOMELOCALEDIR;
}

17
src/tools/Config.vala Normal file
View File

@ -0,0 +1,17 @@
/** Configuration using GSettings
* (c) Er2 2021
* Zlib License
*/
namespace Er2Cord {
class Config : GLib.Settings {
public string name { get; set; }
public Config() {
Object(schema_id: ID);
// var, class, option flags
bind("name", this, "name", DEFAULT);
}
}
}

73
src/widgets/Avatar.vala Normal file
View File

@ -0,0 +1,73 @@
/** Avatar widget
* (c) Er2 2021
* Zlib License
*/
using Cairo;
namespace Er2Cord {
class Avatar : Gtk.DrawingArea {
public ImageSurface ava;
public int size;
public int round;
public Avatar(ImageSurface ava,
int size = 32,
int? round = null
) {
if(round == null) round = size / 2;
content_width = size;
content_height = size;
halign = valign = CENTER;
this.ava = ava;
this.size = size;
this.round = round;
set_draw_func((th, cr, w, h) => {
cr.set_source_surface(draw(), 0, 0);
cr.paint();
});
}
public Avatar.gen(string name, double[] colors,
int size = 32,
int? round = null
) {
var sf = new ImageSurface(ARGB32, 256, 256);
var cr = new Context(sf);
cr.set_source_rgb(colors[0], colors[1], colors[2]);
cr.rectangle(0, 0, 256, 256);
cr.paint();
cr.set_source_rgb(1, 1, 1);
cr.move_to(75, 170);
cr.set_font_size(128);
cr.show_text(@"$(name[0])");
this(sf, size, round);
}
public ImageSurface draw() {
var x = 0, y = 0, w = size, h = size;
var sf = new ImageSurface(ARGB32, w, h);
var cr = new Context(sf);
double iw = (double)w / ava.get_width();
double ih = (double)h / ava.get_height();
cr.scale(iw, ih);
cr.set_source_surface(ava, 0, 0);
cr.scale(1.0 / iw, 1.0 / ih);
cr.new_sub_path();
cr.arc(x + round, y + round, round, Math.PI, 3 * Math.PI / 2);
cr.arc(x + w - round, y + round, round, 3 * Math.PI / 2, 2 * Math.PI);
cr.arc(x + w - round, y + h - round, round, 0, Math.PI / 2);
cr.arc(x + round, y + h - round, round, Math.PI / 2, Math.PI);
cr.close_path();
cr.clip();
cr.paint();
return sf;
}
}
}

52
src/widgets/Chat.vala Normal file
View File

@ -0,0 +1,52 @@
/** Chat class
* (c) Er2 2021
* Zlib License
*/
using Gtk;
namespace Er2Cord {
class Chat : Scroller {
public User user;
public string channel;
Message[] msgs;
public Chat(User user, string channel = "#channelName") {
base(0, new Box(VERTICAL, 0), true);
this.user = user;
this.channel = channel;
//this.msgs = new Message[1];
var ava = new Avatar.gen(channel, User.getColors(1), 64);
var big = new Gtk.Label("<span size='xx-large' weight='bold'>" + _("Welcome to %s!").printf(channel) + "</span>");
var txt = new Gtk.Label(_("This is start of the %s.").printf(channel));
var sep = new Gtk.Separator(HORIZONTAL);
big.use_markup = true;
big.halign = START;
txt.halign = START;
sep.margin_start = 8;
sep.margin_end = 8;
sep.margin_top = 8;
sep.margin_bottom = 8;
append(ava);
append(big);
append(txt);
append(sep);
}
public bool send_message(string text, Message? reply = null) {
if(text == "") return false;
var msg = new Message(text, user, "\\(*.*)/");
this.msgs += msg;
append(new MessageWid(msg));
// https://stackoverflow.com/a/4479178
var adj = scr.vadjustment;
adj.value = adj.upper;
scr.vadjustment = adj;
return true;
}
}
}

63
src/widgets/Message.vala Normal file
View File

@ -0,0 +1,63 @@
/** Message widget
* (c) Er2 2021
* Zlib License
*/
using Gtk;
namespace Er2Cord {
class MessageWid : Grid {
public Message msg;
public MessageWid(Message msg) {
this.msg = msg;
column_spacing = 4;
var rbox = new Box(HORIZONTAL, 4);
if(msg.reply != null) msgReply(rbox);
attach(rbox, 0, 0, 3, 1);
msgHead();
msgContent();
}
public MessageWid.content(
string text,
User user,
string date = "unk.",
Message? reply = null,
MessageEmbed[]? embeds = null
) {
this(new Message(text, user, date, reply, embeds));
}
private void msgReply(Box box) {
var nik = new Label(@"<b>$(msg.reply.user.name)</b>");
var txt = new Label(string.joinv("\n", msg.reply.text.split("\n", 3)[0:2]));
nik.use_markup = true;
box.append(new Image.from_icon_name("mail-replied-symbolic"));
box.append(nik);
box.append(txt);
}
public void msgHead() {
var nick = new Label(@"<b>$(msg.user.name)</b>");
var date = new Label(msg.date);
nick.use_markup = true;
attach(msg.user.ava, 0, 1);
attach(nick, 1, 1);
attach(date, 2, 1);
}
public void msgContent() {
var box = new Box(VERTICAL, 0);
var txt = new Label(msg.text);
txt.halign = START;
txt.wrap = true;
txt.wrap_mode = CHAR;
box.append(txt);
attach(box, 1, 2, 2, 1);
}
}
}

32
src/widgets/Scroller.vala Normal file
View File

@ -0,0 +1,32 @@
/** Scroller class
* (c) Er2 2021
* Zlib License
*/
using Gtk;
namespace Er2Cord {
class Scroller : Object {
Box box;
public ScrolledWindow scr; // FIXME: GTK Developers is pidors
public Scroller(
int w = 48,
Box wid = new Box(VERTICAL, 0),
bool exp = false
) {
scr = new ScrolledWindow();
if(w != 0) scr.width_request = w;
scr.hscrollbar_policy = NEVER;
scr.vexpand = true;
scr.hexpand = exp;
box = wid;
scr.child = box;
}
public void append(Widget w) {
box.append(w);
}
}
}