Compare commits

...

126 Commits

Author SHA1 Message Date
Tristan B. Kildaire 426a65cf96 Sucked those offsets out of my thumb, I couldn't be ared right now 2021-01-28 16:39:08 +02:00
Tristan B. Kildaire 66bb86e4cd WIP: Direct messages woith `from` field
Just offset incorrectly it seems
2021-01-28 16:26:57 +02:00
Tristan B. Kildaire 3d6e01fb2a Oh lol, they're unchecked 2021-01-28 16:11:26 +02:00
Tristan B. Kildaire a14d67e0fd Upgrade tristanable 2021-01-28 16:08:24 +02:00
Tristan B. Kildaire e0bd021db1 Fok idk 2021-01-28 15:57:34 +02:00
Tristan B. Kildaire f2120f5fd4 Call `findUser` on direct message notification received 2021-01-28 15:32:03 +02:00
Tristan B. Kildaire ddee77a5b7 Corrected array-base offset 2021-01-28 15:29:04 +02:00
Tristan B. Kildaire 75ac2e16d4 WIP: Direct messages 2021-01-28 15:21:08 +02:00
Tristan B. Kildaire 5bac2157f8 User area now populated with copied-over code from Channel (similiar)
Set message type (isUser=1/true) for sending of messages via enter and send button
2021-01-28 14:26:00 +02:00
Tristan B. Kildaire 302603a6f6 Removed debug 2021-01-28 14:18:41 +02:00
Tristan B. Kildaire 40342772c2 Fixed bug 2021-01-28 14:17:21 +02:00
Tristan B. Kildaire 13d5176a89 No class cast exception, the cast went ahead, had UB that caused a segfault somewhere 2021-01-28 13:56:39 +02:00
Tristan B. Kildaire e6ef053f13 Added a new debugs 2021-01-28 13:55:10 +02:00
Tristan B. Kildaire 602d23e067 MessageArea is responsible for box 2021-01-28 13:40:49 +02:00
Tristan B. Kildaire 37c1afeaaa Added handler 2021-01-28 13:38:10 +02:00
Tristan B. Kildaire 21f60747a6 Use the delegate as intended 2021-01-28 13:35:22 +02:00
Tristan B. Kildaire 4c687b06eb It's a delegate, we have access to `this`, use it 2021-01-28 13:34:16 +02:00
Tristan B. Kildaire e75aee2221 Added direct message button to UserNode 2021-01-28 13:28:56 +02:00
Tristan B. Kildaire 4ff60a02c9 Remove dunused fields 2021-01-28 13:03:31 +02:00
Tristan B. Kildaire a3d70929e5 Renamed `chans` -> `areas`
Renamed `focusedChan` -> `focusedArea`
2021-01-28 13:00:02 +02:00
Tristan B. Kildaire 029cd5a3ee Only loop through Channel objects 2021-01-28 12:57:58 +02:00
Tristan B. Kildaire be543d33fd Missing imports 2021-01-28 11:44:00 +02:00
Tristan B. Kildaire a9b3617b0d Added stub for User area 2021-01-28 11:43:24 +02:00
Tristan B. Kildaire 31611d6f94 Restructure and inherit 2021-01-28 11:41:19 +02:00
Tristan B. Kildaire d4912089b1 WIP: Message areas 2021-01-28 11:33:11 +02:00
Tristan B. Kildaire 638b1bfa9b Comment change 2021-01-28 11:30:56 +02:00
Tristan B. Kildaire 58951da6b0 Now show property values too 2021-01-28 11:30:43 +02:00
Tristan B. Kildaire 1420e8e86f Use gogga for some debug messages 2021-01-28 11:08:18 +02:00
Tristan B. Kildaire 27c42711e0 Updated dub.json 2021-01-27 22:43:37 +02:00
Tristan B. Kildaire f5791f2eae Changed message shown to be "prescence" instead of "status"
ALso show an error on setting sttaus when not connected to any server
2021-01-27 22:39:33 +02:00
Tristan B. Kildaire 97295cf042 Fixed error message shown when you attempt to set your status and are not connected to any server 2021-01-27 22:37:49 +02:00
Tristan B. Kildaire ce9a675da0 Don't crash when you select "Channel list" when you have no open sessions 2021-01-27 22:37:20 +02:00
Tristan B. Kildaire 62895ccaee Implemented custom channel join (useful for when you want to create a new channel)
It will show up in the channels list window
2021-01-27 22:09:57 +02:00
Tristan B. Kildaire ecd23539ab Prototyping: Channel join for uncreated channels 2021-01-27 21:51:26 +02:00
Tristan B. Kildaire 5ea0a76a08 Testing 2020-12-04 19:04:19 +02:00
Tristan B. Kildaire e965b9a82c New bformat fucks up tristsnabale 2020-12-04 18:49:36 +02:00
Tristan B. Kildaire 68ad0e5f38 Upgraded to new libdnet 2020-12-04 18:43:44 +02:00
Tristan B. Kildaire 01578ab03b Upgraded to new libdnet 2020-12-04 18:26:30 +02:00
Tristan B. Kildaire 95f36698f7 Added file chooser 2020-10-28 08:52:00 +02:00
Tristan B. Kildaire d10c8f1c3c TODO 2020-10-28 08:23:34 +02:00
Tristan B. Kildaire 624d53d909 Increased font size 2020-10-28 08:19:33 +02:00
Tristan B. Kildaire 1da36e6936 Remved TODO 2020-10-28 08:17:48 +02:00
Tristan B. Kildaire 015521082e Added TODO 2020-10-26 10:23:35 +02:00
Tristan B. Kildaire 27bc84da56 Code cleanup 2020-10-26 00:00:24 +02:00
Tristan B. Kildaire 9bc6deb17d Fully migrated to UserNode 2020-10-25 23:58:19 +02:00
Tristan B. Kildaire 4894017ad5 Fixed spacing between button and label for UserNode 2020-10-25 23:52:08 +02:00
Tristan B. Kildaire 347221d1a2 New UserNode system works 2020-10-25 23:47:03 +02:00
Tristan B. Kildaire 185e5efd5f Pass in Connection instead 2020-10-25 23:43:43 +02:00
Tristan B. Kildaire 32deadfc83 Add components to final Box 2020-10-25 23:39:09 +02:00
Tristan B. Kildaire ac48d440bd Copied over code for user lusts entry into UserNode 2020-10-25 23:35:55 +02:00
Tristan B. Kildaire b090584fbd Added logo and title to connection assistant 2020-10-25 11:26:08 +02:00
Tristan B. Kildaire 87db85f7aa WIP: UserNode 2020-10-25 11:25:33 +02:00
Tristan B. Kildaire 3ee0830b65 Only connect to the server if not all whitespace 2020-10-24 12:13:34 +02:00
Tristan B. Kildaire 0a3b4acb14 Strip whitespace from server address, port and username 2020-10-24 12:08:56 +02:00
Tristan B. Kildaire 7c60695cce WIP 2020-10-24 12:08:00 +02:00
Tristan B. Kildaire f83ff298bd Clean up 2020-10-24 11:59:20 +02:00
Tristan B. Kildaire 5d1e9c2454 Cleaned up 2020-10-24 11:51:47 +02:00
Tristan B. Kildaire b0ace4deeb Moved handler set 2020-10-24 00:14:30 +02:00
Tristan B. Kildaire 8d5be66f2b Connection assistant now moved to its own object and can now spawn new connections 2020-10-23 23:39:37 +02:00
Tristan B. Kildaire 6ca88b2717 Added Network configuration and Account configuration to the connection assistant 2020-10-23 22:35:55 +02:00
Tristan B. Kildaire cac85f254e Code cleanup 2020-10-23 22:05:17 +02:00
Tristan B. Kildaire c347490291 Removed old status protocol code 2020-10-23 22:05:08 +02:00
Tristan B. Kildaire 9561e1cbb7 Stub 2020-10-23 22:04:22 +02:00
Tristan B. Kildaire e49824b58b Clean up
Display connection assistant on link click
Display error on set prescence when no active connections
2020-10-23 22:04:19 +02:00
Tristan B. Kildaire 29fba2f7bd Test 1 2020-10-23 22:03:44 +02:00
Tristan B. Kildaire e0293bfe7b Added member listing to tooltip for each channel listed in the ChannelList window 2020-10-23 17:12:56 +02:00
Tristan B. Kildaire f57758777e Added tooltip for each channel item in the ChannelList window 2020-10-23 17:10:44 +02:00
Tristan B. Kildaire 3b22f095bb Disallow re-ordering S IT DOWNS'T ALIGN WWITH ARRAY ACCESSES 2020-10-23 17:00:04 +02:00
Tristan B. Kildaire 77575c6ff1 Connect to default server on click of gennesis link 2020-10-23 16:10:01 +02:00
Tristan B. Kildaire 0f6aabb311 Updated title font and added link to servers 2020-10-23 15:17:00 +02:00
Tristan B. Kildaire 912fdb3745 Added note on `connectServer(address, port)` 2020-10-23 15:05:13 +02:00
Tristan B. Kildaire 2454a4b484 Refactored connection logic into its own function, `connectServer(address, port)` which can be called by any GTK signal handler 2020-10-23 15:04:46 +02:00
Tristan B. Kildaire 7d0542086d Added welcome page that dissappears on first connection. 2020-10-23 15:01:26 +02:00
Tristan B. Kildaire d086492730 Added welcome page that disappears when you add your first connection 2020-10-23 14:39:12 +02:00
Tristan B. Kildaire 5ddc84417d Removed test connection 2020-10-23 14:23:08 +02:00
Tristan B. Kildaire 8060ff34d6 Test 2020-10-23 14:20:36 +02:00
Tristan B. Kildaire eb9c72d0e1 Todo 2020-10-23 14:20:33 +02:00
Tristan B. Kildaire c4d149782f Just messing around 2020-10-23 14:02:07 +02:00
Tristan B. Kildaire 0e40518dc4 Clean up 2020-10-23 14:02:01 +02:00
Tristan B. Kildaire 0c2fd122f3 Allow messages to be right -clicked and copied (their contents) 2020-10-23 09:35:45 +02:00
Tristan B. Kildaire 2c3040391d Italised whole join text 2020-10-23 08:56:52 +02:00
Tristan B. Kildaire b6781a4ce0 Set leave message to italics 2020-10-23 08:53:33 +02:00
Tristan B. Kildaire 0c3479eac6 Made channel title label larger and bold 2020-10-22 23:21:01 +02:00
Tristan B. Kildaire 682c5e482e Added new text input 2020-10-21 22:29:23 +02:00
Tristan B. Kildaire 9ea68ca748 2020-10-21 09:00:33 +02:00
Tristan B. Kildaire c9ee505167 Removed debug code.
Cleaned up.
2020-10-21 07:53:47 +02:00
Tristan B. Kildaire 001860b875 Use new `sendMessage` handler 2020-10-21 00:27:03 +02:00
Tristan B. Kildaire 953493cb07 Now messages are received and placed in the respective channel 2020-10-20 23:39:56 +02:00
Tristan B. Kildaire bf36f033be Set status to available on startup 2020-10-20 21:11:24 +02:00
Tristan B. Kildaire ed909a0558 Print out received data 2020-10-20 20:14:29 +02:00
Tristan B. Kildaire 5ae50a098f Left-aligned text 2020-10-20 19:23:54 +02:00
Tristan B. Kildaire 4bab9d04c5 Fuck Pango 2020-10-20 18:59:10 +02:00
Tristan B. Kildaire 413502d1ee Added join buttons 2020-10-20 15:36:18 +02:00
Tristan B. Kildaire ef2a48c684 Delete the status property on empty status message in status box 2020-10-20 14:02:05 +02:00
Tristan B. Kildaire 7ec56f1036 Implemented status field for setting your status 2020-10-20 12:16:44 +02:00
Tristan B. Kildaire 4d2ff21cc8 Now using User properties sub-protocol for prescence and status 2020-10-20 11:34:22 +02:00
Tristan B. Kildaire f51a118348 Cleaned up 2020-10-20 11:26:49 +02:00
Tristan B. Kildaire 26685a322c Cleaned up 2020-10-20 08:07:35 +02:00
Tristan B. Kildaire 700ccfa3c0 Cleaned up 2020-10-20 08:06:16 +02:00
Tristan B. Kildaire 65eb2d2518 Cleaned up 2020-10-20 08:04:49 +02:00
Tristan B. Kildaire 168a7c7e12 Cleaned up 2020-10-20 08:04:11 +02:00
Tristan B. Kildaire 63e0b09751 Clean up 2020-10-20 08:00:20 +02:00
Tristan B. Kildaire 9f1d51bbba Cleaned up 2020-10-19 19:28:38 +02:00
Tristan B. Kildaire 0e30d54fe6 Clean up 2020-10-19 19:19:28 +02:00
Tristan B. Kildaire ec150159df S 2020-10-19 19:12:15 +02:00
Tristan B. Kildaire 8546dff6e6 Removed uneeded method call 2020-10-19 19:08:15 +02:00
Tristan B. Kildaire 7da8efee61 Migrated channel joining code (the majority of it) from gui.d to Connection.d (only the needed left overs are in gui.d - for the handler)
Also set the fields back to private
2020-10-19 19:07:56 +02:00
Tristan B. Kildaire 5332d26be9 Channel sidebar is now for switching between channels you have joined, to join a channel you now will have to go to the list channels menu 2020-10-19 18:45:23 +02:00
Tristan B. Kildaire 99f22f96e3 Moved channel selection over to list box (accessible via toolbar).
I should clean up accessing this stuff, although I don't mind the crossover accessing to instance fields, I would lik to keep it to a minimum
2020-10-19 18:32:53 +02:00
Tristan B. Kildaire c0e55329df Made `addChannel(string)` public 2020-10-19 18:28:27 +02:00
Tristan B. Kildaire de38f78432 Made `findChannel` pblic 2020-10-19 18:26:56 +02:00
Tristan B. Kildaire 00482eeccc Added stub handler for clicking channel in channel list. 2020-10-19 18:22:48 +02:00
Tristan B. Kildaire 7f8ae349fe Set icon for "List channels" 2020-10-19 18:01:00 +02:00
Tristan B. Kildaire a52dbc744e Added basic channel list window 2020-10-19 16:23:00 +02:00
Tristan B. Kildaire c973463cd7 Fiixed Help menu 2020-10-19 16:15:01 +02:00
Tristan B. Kildaire 4437bf4fce Added help menu. 2020-10-19 16:14:28 +02:00
Tristan B. Kildaire f612d9c727 Added artists tag. 2020-10-19 16:11:24 +02:00
Tristan B. Kildaire 3e5db759e5 Added about dialog. 2020-10-19 16:09:08 +02:00
Tristan B. Kildaire 301c09c063 Allow reordering of channel tab 2020-10-19 14:58:00 +02:00
Tristan B. Kildaire 29556a6d8c Allow reordering on connection tabs 2020-10-19 14:57:16 +02:00
Tristan B. Kildaire 7ae11e120e Added status message fetch 2020-10-19 14:06:14 +02:00
Tristan B. Kildaire ac9ea39a8f Boldened username in tooltip 2020-10-19 13:53:57 +02:00
Tristan B. Kildaire 730c5348f1 Italicised leave message 2020-10-19 13:48:39 +02:00
Tristan B. Kildaire 4ab6ef6040 Italicised join message 2020-10-19 13:48:15 +02:00
Tristan B. Kildaire 5ab62e5c4a Align messages not sent (i.e. received) to the start (left) 2020-10-19 13:44:58 +02:00
Tristan B. Kildaire 860fa3b714 Fixed connection addition with variadic username 2020-10-19 09:27:10 +02:00
14 changed files with 1844 additions and 494 deletions

1
.gitignore vendored
View File

@ -23,3 +23,4 @@ docs/
# Code coverage
*.lst
unnamed-thing
gustav

View File

@ -4,8 +4,9 @@
],
"copyright": "Copyright © 2020, Tristan B. Kildaire",
"dependencies": {
"gtk-d": "~>3.9.0",
"libdnet": "~>0.1.8"
"gogga": "0.0.2",
"gtk-d": "3.9.0",
"libdnet": "0.2.3"
},
"description": "GTK graphical DNET client",
"license": "GPL v3",

View File

@ -2,8 +2,9 @@
"fileVersion": 1,
"versions": {
"bformat": "1.0.8",
"gogga": "0.0.2",
"gtk-d": "3.9.0",
"libdnet": "0.1.8",
"libdnet": "0.2.3",
"tristanable": "0.1.1"
}
}

View File

@ -1,287 +0,0 @@
/**
* Channel
*
* Represents a channel which is a collection
* of the channel name the users list widget,
* the title widget and the chat list box widget
* along with the input box state
*/
import gtk.Box;
import gtk.ListBox;
import gtk.Label;
import gtk.TextView;
import libdnet.dclient;
import gtk.Label;
import std.string;
import gtk.Button;
public final class Channel
{
private DClient client;
/**
* Channel details
*/
private string channelName;
/**
* The container for this Channel
*/
private Box box;
/**
* UI components
*
* Users's box
* - Label users
* - ListBox users
*/
private ListBox users;
private ListBox textArea;
private TextView textInput;
/* TODO: No mutexes should be needed (same precaution) as the GTK lock provides safety */
private string[] usersString;
this(DClient client, string channelName)
{
this.client = client;
this.channelName = channelName;
initializeBox();
}
private void initializeBox()
{
box = new Box(GtkOrientation.HORIZONTAL, 1);
/* The user's box */
Box userBox = new Box(GtkOrientation.VERTICAL, 1);
/* The user's list */
users = new ListBox();
userBox.add(new Label("Users"));
// import gtk.Expander;
// Expander g = new Expander("Bruh");
// g.setExpanded(true)
// g.add(users);
userBox.add(users);
/* The text box */
Box textBox = new Box(GtkOrientation.VERTICAL, 1);
textBox.add(new Label(channelName));
textArea = new ListBox();
import gtk.ScrolledWindow;
ScrolledWindow scrollTextChats = new ScrolledWindow(textArea);
textBox.add(scrollTextChats);
textInput = new TextView();
Box textInputBox = new Box(GtkOrientation.HORIZONTAL, 1);
textInputBox.packStart(textInput,1,1,0);
import gtk.Button;
/* The send button */
Button sendButton = new Button("Send");
sendButton.addOnClicked(&sendMessageBtn);
textInputBox.add(sendButton);
textBox.add(textInputBox);
// import gtk.TextView;
// TextView f = new TextView();
// textBox.add(f);
box.add(textBox);
box.packEnd(userBox,0,0,0);
textBox.setChildPacking(scrollTextChats, true, true, 0, GtkPackType.START);
box.setChildPacking(textBox, true, true, 0, GtkPackType.START);
}
private void sendMessageBtn(Button)
{
/* Retrieve the message */
string message = textInput.getBuffer().getText();
/* TODO: Add the message to our log (as it won't be delivered to us) */
addMessage(message);
/* Send the message */
client.sendMessage(0, channelName, message);
/* Clear the text box */
textInput.getBuffer().setText("");
box.showAll();
}
public Box getBox()
{
return box;
}
public string getName()
{
return channelName;
}
/**
* Returns a Label with the tooltip event such
* that it will run that handler on hover
*/
private Label getUserLabel(string username)
{
Label bruh = new Label(username);
bruh.setHasTooltip(true);
// import gtk.Window;
// Window k = new Window(GtkWindowType.POPUP);
// bruh.setTooltipWindow(k);
bruh.addOnQueryTooltip(&kak);
return bruh;
}
public void populateUsersList()
{
string[] memberList = client.getMembers(channelName);
foreach(string member; memberList)
{
Label bruh = getUserLabel(member);
users.add(bruh);
usersString~=member;
}
}
import gtk.Tooltip;
import gtk.Widget;
private static string statusToGtkIcon(string status)
{
/* The GTK icon */
string gtkIcon = "image-missing";
if(cmp(status, "available") == 0)
{
gtkIcon = "user-available";
}
else if(cmp(status, "away") == 0)
{
gtkIcon = "user-away";
}
else if(cmp(status, "busy") == 0)
{
gtkIcon = "user-busy";
}
/* TODO: This doesn't make sense */
else if(cmp(status, "offline") == 0)
{
gtkIcon = "user-offline";
}
return gtkIcon;
}
private bool kak(int,int,bool, Tooltip d, Widget poes)
{
import std.stdio;
writeln("ttoltip activatd");
/* The username hovered over */
string userHover = (cast(Label)poes).getText();
/* Fetch the status message */
string[] statusMessage = split(client.getMemberInfo(userHover), ",");
writeln(statusMessage);
/* First one is prescence */
string prescence = statusMessage[0];
d.setIconFromIconName(statusToGtkIcon(prescence), GtkIconSize.DIALOG);
d.setText(userHover~"\n"~prescence);
// /* The notification box */
// Box notificationBox = new Box(GtkOrientation.VERTICAL, 1);
// Label title = new Label((cast(Label)poes).getText());
// Label status = new Label("status goes here");
// notificationBox.add(title);
// notificationBox.add(status);
// import gtk.Style;
// // title.setStyle(new Style());
// d.setCustom(notificationBox);
return 1;
}
public void channelJoin(string username)
{
/* Add join message to message log */
textArea.add(new Label("--> "~username~" joined the channel"));
/* Add user to user list */
users.add(getUserLabel(username));
usersString~=username;
}
public void channelLeave(string username)
{
/* Add leave message to message log */
textArea.add(new Label("<-- "~username~" left the channel"));
/* TODO: Better way with just removing one dude */
/* Remove the user form users list */
string[] newUsers;
foreach(string currentUser; usersString)
{
if(cmp(currentUser, username))
{
newUsers ~= currentUser;
}
}
usersString = newUsers;
/* Clear list */
users.removeAll();
foreach(string currentUser; usersString)
{
users.add(getUserLabel(currentUser));
}
/* Remove user from user list */
/* TODO: Do this better */
// foreach(Label label; users.get)
// users.add(new Label(username));
}
public void addMessage(string s)
{
textArea.add(new Label(s));
}
}

View File

@ -5,29 +5,36 @@ import gui;
import gdk.Threads : te = threadsEnter, tl = threadsLeave;
import gtk.Box;
import std.stdio;
import libdnet.dclient;
import libdnet.client;
import std.socket;
import gtk.ListBox;
import gtk.Label;
import Channel;
import areas.Channel;
import areas.MessageArea;
import areas.User;
import std.string;
import core.sync.mutex;
import gtk.Notebook;
import std.conv;
import gogga;
public final class Connection : Thread
{
private GUI gui;
private Box box;
private ListBox channels;
private ListBox users;
private ListBox textArea;
private DClient client;
private Address address;
private string[] auth;
private string statusText;
/* TODO: Check if we need to protect */
/* TODO: So far usage is in signal handlers (mutex safved) and within te-tl lock for notifications */
@ -38,9 +45,18 @@ public final class Connection : Thread
* All joined Channel-s in this Connection
*/
private Notebook notebookSwitcher;
private Channel[] chans; /*TODO: Technically locking by GTK would make this not needed */
private MessageArea[] areas; /*TODO: Technically locking by GTK would make this not needed */
private Mutex chansLock;
private Channel focusedChan;
private MessageArea focusedArea;
// public void setPrescence(string pres)
// {
// /* The new status */
// string newStatus =
// statusText = "";
// statusText =
// }
this(GUI gui, Address address, string[] auth)
{
@ -52,6 +68,8 @@ public final class Connection : Thread
/* Initialize locks */
initializeLocks();
statusText = "Hey there, I'm using Dnet!";
/* Start the notification atcher */
start();
}
@ -75,6 +93,7 @@ public final class Connection : Thread
te();
box = getChatPane();
gui.notebook.add(box);
//gui.notebook.setTabReorderable(box, true);
//gui.notebook setChildPacking(box, true, true, 0, GtkPackType.START);
// gui.mainWindow.
gui.notebook.setTabLabelText(box, auth[0]~"@"~address.toString());
@ -88,8 +107,15 @@ public final class Connection : Thread
client = new DClient(address);
client.auth(auth[0], auth[1]); /* TODO: DO this without auth (the list in the loop, crahses server) */
/* Display all channels */
channelList();
/* Set your prescense */
client.setProperty("pres","available");
// te();
// import ProfileWIndow;
// ProfileWindow profile = new ProfileWindow(this, auth[0]);
// tl();
/**
* Notification loop
@ -100,17 +126,29 @@ public final class Connection : Thread
{
/* Receive a notification */
byte[] notificationData = client.awaitNotification();
writeln(notificationData);
gprintln("A new notification has arrived");
gprintln("Notification data: "~to!(string)(notificationData));
te();
// import std.conv;
// textArea.add(new Label(to!(string)(notificationData)));
// textArea.showAll();
process(notificationData);
//gui.mainWindow.showAll();
// import gtk.InfoBar;
// InfoBar notificationBar = new InfoBar();
// notificationBar.add(new Label("Poes"));
// notificationBar.setMessageType(GtkMessageType.INFO);
// notificationBar
// box.add(notificationBar);
// notificationBar.showAll();
notebookSwitcher.showAll();
tl();
@ -118,24 +156,100 @@ public final class Connection : Thread
}
}
/**
* Processes an incoming notification
* accordingly
*/
private void process(byte[] data)
{
/* TODO: Implement me */
/* TODO: Check notification type */
/* Get the notification type */
ubyte notificationType = data[0];
gprintln("NotificationType: "~to!(string)(notificationType));
/* For normal message (to channel or user) */
if(notificationType == 0)
{
/* TODO: Decode using tristanable */
writeln("new message");
/* TODO: Handle private messages */
/* Decode is a test for assuming channel message received */
data = data[1..data.length];
gprintln("Channel/User Notification: "~to!(string)(data));
/* If this is a new message channel notification */
if(data[0] == 0)
{
gprintln("New channel message received", DebugType.WARNING);
/* Decode the [usernameLength, username] */
ubyte usernameLength = data[1];
gprintln("ChannelMessage: (Username length): "~to!(string)(usernameLength));
string username = cast(string)data[2..2+usernameLength];
gprintln("ChannelMessage: (Username): "~username);
/* Decode the [channelLength, channel] */
ubyte channelLength = data[2+usernameLength];
gprintln("ChannelMessage: (Channel length): "~to!(string)(channelLength));
string channel = cast(string)data[2+usernameLength+1..2+usernameLength+1+channelLength];
gprintln("ChannelMessage: (Channel): "~channel);
findChannel(channel).receiveMessage(username, cast(string)data[2+usernameLength+1+channelLength..data.length]);
}
/* If this is a new direct message notification */
else if(data[0] == 1)
{
gprintln("New direct message received", DebugType.WARNING);
/* Decode the [usernameLength, username] (username here is recipient's) */
ubyte recipientLength = data[1];
gprintln("DirectMessage: (Recipient length): "~to!(string)(recipientLength));
string recipient = cast(string)data[2..2+recipientLength];
gprintln("DirectMessage: (Recipient): "~recipient);
/* Decode the [usernameLength, username] (username here is sender's) */
ubyte sendersLength = data[2+recipientLength];
gprintln("DirectMessage: (Sender length): "~to!(string)(sendersLength));
string sender = cast(string)data[2+recipientLength+1..2+recipientLength+1+sendersLength];
gprintln("DirectMessage: (Sender): "~sender);
/* The message is the remainder */
string message = cast(string)data[2+recipientLength+1+sendersLength..data.length];
gprintln("DirectMessage: (Message): "~message);
/**
* TODO: DIfferes from channels, channels we never get delivered those we have no tab for as we haven't joined them
* and because server side knows we haven't joined iot we don't receive the notifivcaiton, eher however, there is no
* user tab possibly yet, so we will need to add it our selves */
User userArea = findUser(sender);
if(userArea)
{
userArea.receiveMessage(sender, message);
}
else
{
/* Add a new UserArea which will generate a new tab for us */
addDirectMessage_unsafe(sender);
/* The above statement adds an entry for us, now let's find the added UserArea */
userArea = findUser(sender);
/* Now let's add the direct message */
userArea.receiveMessage(sender, message);
}
}
else
{
/* TODO: Handle this */
gprintln("FOk");
}
}
/* Channel notification (ntype=1) */
else if(notificationType == 1)
@ -186,7 +300,168 @@ public final class Connection : Thread
}
private void addUserDM(User newUser)
{
/* TODO: However this we need to mutex for the areas as we could recieve a new message by watcher which adds for us */
chansLock.lock();
areas ~= newUser;
chansLock.unlock();
}
/**
* Opens a new tab for a new direct message
*
* (To be called by a handler, which auto-mutexes)
*
* 1. Will add a new area
* 2. Will add a new tab to the notebook switcher
* 3. Will switch the current tab to said tab
*/
public void addDirectMessage_unsafe(string username)
{
/* TODO: Get box over here etc. */
gprintln("Henlo begi");
/* Check if we have joined this user already */
User foundUser = findUser(username);
gprintln("Henlo");
/* If we have joined this user before */
if(foundUser)
{
/* TODO: Switch to */
writeln("nope time: "~username);
}
/* If we haven't joined this user before */
else
{
/* Create the new User area */
User newUser = new User(this, username);
/* Add the user */
addUserDM(newUser);
/* Set as the `foundChannel` */
foundUser = newUser;
/* Get the Widgets container for this channel and add a tab for it */
notebookSwitcher.add(newUser.getBox());
notebookSwitcher.setTabReorderable(newUser.getBox(), true);
notebookSwitcher.setTabLabelText(newUser.getBox(), newUser.getUsername());
writeln("hdsjghjsd");
writeln("first time: "~username);
// /* Get the user's list */
// newChannel.populateUsersList();
}
/* Render recursively all children of the container and then the container itself */
box.showAll();
}
/**
* Attempts to find the User object you are looking for
*/
public User findUser(string username)
{
User result;
chansLock.lock();
/**
* Loop through each MessageArea and only inspect those
* whose type is `Channel`
*/
foreach(MessageArea area; areas)
{
/* Make sure the object is of type `Channel` */
if(typeid(area) == typeid(User))
{
/* Down-cast */
User user = cast(User)area;
/* Find the matching channel */
if(cmp(user.getUsername(), username) == 0)
{
result = user;
break;
}
}
}
import std.stdio;
writeln("\""~username~"\"");
chansLock.unlock();
return result;
}
public void joinChannel(string channelName)
{
/* Check if we have joined this channel already */
Channel foundChannel = findChannel(channelName);
/* If we have joined this channel before */
if(foundChannel)
{
/* TODO: Switch to */
writeln("nope time: "~channelName);
}
/* If we haven't joined this channel before */
else
{
/* Join the channel */
client.join(channelName);
/* Create the Channel object */
Channel newChannel = new Channel(this, channelName);
/* Add the channel */
addChannel(newChannel);
/* Set as the `foundChannel` */
foundChannel = newChannel;
/* Get the Widgets container for this channel and add a tab for it */
notebookSwitcher.add(newChannel.getBox());
notebookSwitcher.setTabReorderable(newChannel.getBox(), true);
notebookSwitcher.setTabLabelText(newChannel.getBox(), newChannel.getName());
writeln("hdsjghjsd");
writeln("first time: "~channelName);
/* Get the user's list */
newChannel.populateUsersList();
}
/* Render recursively all children of the container and then the container itself */
box.showAll();
}
private void channelList()
@ -219,106 +494,90 @@ public final class Connection : Thread
}
}
private Channel findChannel(string channelName)
/**
* Attempts to find the Channel object you are looking for
*/
public Channel findChannel(string channelName)
{
Channel result;
chansLock.lock();
foreach(Channel channel; chans)
/**
* Loop through each MessageArea and only inspect those
* whose type is `Channel`
*/
foreach(MessageArea area; areas)
{
if(cmp(channel.getName(), channelName) == 0)
/* Make sure the object is of type `Channel` */
if(typeid(area) == typeid(Channel))
{
result = channel;
break;
/* Down-cast */
Channel channel = cast(Channel)area;
/* Find the matching channel */
if(cmp(channel.getName(), channelName) == 0)
{
result = channel;
break;
}
}
}
import std.stdio;
writeln("\""~channelName~"\"");
chansLock.unlock();
return result;
}
private void addChannel(Channel newChannel)
/**
* Adds the given channel to the tarcking list
*
* This adds the Channel object to the list of
* channels joined
*
* TODO: Migrate the gui.d channel join selectChannel
* here
* NOTE: You must manually join it though
*/
public void addChannel(Channel newChannel)
{
/* Add the channel to the `chans` tracking list */
chansLock.lock();
chans ~= newChannel;
areas ~= newChannel;
chansLock.unlock();
/* Add the channel to the channels list (sidebar) */
writeln("Adding channel "~newChannel.getName());
Label babaBooey = new Label(newChannel.getName()); /* TODO: Fuck Pango, fix here but yeah _ */
babaBooey.setUseMarkup(false);
babaBooey.setText(newChannel.getName());
channels.add(babaBooey);
}
private void selectChannel(ListBox s)
/**
* Called when you select a channel in the sidebar
*
* This moves you to the correct notebook tab for
* that channel
*/
private void viewChannel(ListBox s)
{
/* Get the name of the channel selected */
string channelSelected = (cast(Label)(s.getSelectedRow().getChild())).getText();
/* Check if we have joined this channel already */
Channel foundChannel = findChannel(channelSelected);
/* If we have joined this channel before */
if(foundChannel)
{
/* TODO: Switch to */
writeln("nope time: "~channelSelected);
}
/* If we haven't joined this channel before */
else
{
/* Join the channel */
client.join(channelSelected);
/* Create the Channel object */
Channel newChannel = new Channel(client, channelSelected);
/* Add the channel */
addChannel(newChannel);
/* Set as the `foundChannel` */
foundChannel = newChannel;
/* Get the Widgets container for this channel and add a tab for it */
notebookSwitcher.add(newChannel.getBox());
notebookSwitcher.setTabLabelText(newChannel.getBox(), newChannel.getName());
writeln("hdsjghjsd");
writeln("first time: "~channelSelected);
/* Get the user's list */
newChannel.populateUsersList();
}
writeln(foundChannel is null);
/* Switch to the channel's pane */
notebookSwitcher.setCurrentPage(foundChannel.getBox());
box.showAll();
// notebookSwitcher.showAll();
/* TODO: Now add the widget */
// /* Set this as the currently selected channel */
// currentChannel = channelSelected;
// currentChannelLabel.setText(currentChannel);
// // currentChannelLabel.show();
// // box.show();
// /* Fetch a list of members */
// string[] members = client.getMembers(channelSelected);
// /* Display the members */
// users.removeAll();
// foreach(string member; members)
// {
// users.add(new Label(member));
// users.showAll();
// }
// /* Clear the text area */
// textArea.removeAll();
// textArea.showAll();
}
@ -345,7 +604,7 @@ public final class Connection : Thread
/* The channel's list */
channels = new ListBox();
channels.addOnSelectedRowsChanged(&selectChannel);
channels.addOnSelectedRowsChanged(&viewChannel);
channelBox.add(new Label("Channels"));
channelBox.add(channels);

View File

@ -0,0 +1,169 @@
module ConnectionAssistant;
/**
* ConnectionAssistant
*
* This provides a graphical utility for
* configuring new connections
*/
import gtk.Assistant;
import gtk.Label;
import gtk.Box;
import gtk.Entry;
import gtk.Image;
import gui;
import std.conv;
import std.string : cmp, strip;
public final class ConnectionAssistant : Assistant
{
/* Associated GUI instance */
private GUI gui;
private Entry serverAddress;
private Entry serverPort;
private Entry username;
private Entry password;
/* Summary box */
Box summaryBox;
this(GUI gui)
{
this.gui = gui;
initWindow();
}
private void initWindow()
{
Assistant connectionAssistant = new Assistant();
/* Welcome page */
Box welcomeBox = new Box(GtkOrientation.VERTICAL, 1);
Image logo = new Image("user-available", GtkIconSize.DIALOG);
logo.setPixelSize(250);
welcomeBox.add(logo);
Label title = new Label("<span size=\"100\">Gustav</span>");
title.setMarkup("<span font_desc=\"Open Sans Extrabold\" size=\"50000\">Gustav</span>");
welcomeBox.add(title);
Label hello = new Label("");
hello.setMarkup("<span size=\"15000\">Welcome to the connection setup</span>");
welcomeBox.add(hello);
connectionAssistant.insertPage(welcomeBox, 0);
connectionAssistant.setPageTitle(welcomeBox, "Welcome");
/* Configure a server */
Box serverBox = new Box(GtkOrientation.VERTICAL, 1);
Label serverBoxTitle = new Label("");
serverBoxTitle.setMarkup("<span size=\"15000\">Server details</span>");
serverBox.packStart(serverBoxTitle,0,0,30);
serverAddress = new Entry();
serverBox.add(serverAddress);
serverAddress.setPlaceholderText("DNET server address");
serverPort = new Entry();
serverBox.add(serverPort);
serverPort.setPlaceholderText("DNET server port");
connectionAssistant.insertPage(serverBox, 1);
connectionAssistant.setPageTitle(serverBox, "Network");
/* Configure your profile details */
Box profileBox = new Box(GtkOrientation.VERTICAL, 1);
Label profileBoxTitle = new Label("");
profileBoxTitle.setMarkup("<span size=\"15000\">Account details</span>");
profileBox.packStart(profileBoxTitle,0,0,30);
username = new Entry();
profileBox.add(username);
username.setPlaceholderText("username");
password = new Entry();
profileBox.add(password);
password.setPlaceholderText("password");
connectionAssistant.insertPage(profileBox, 2);
connectionAssistant.setPageTitle(profileBox, "Account");
/* TODO: We should actually verify inputs before doing this */
connectionAssistant.setPageComplete(welcomeBox, true);
connectionAssistant.setPageComplete(serverBox, true);
connectionAssistant.setPageComplete(profileBox, true);
/* Summary */
summaryBox = new Box(GtkOrientation.VERTICAL, 1);
Label summaryBoxTitle = new Label("");
summaryBoxTitle.setMarkup("<span size=\"15000\">Summary</span>");
summaryBox.packStart(summaryBoxTitle,0,0,30);
connectionAssistant.insertPage(summaryBox, 4);
connectionAssistant.setPageType(summaryBox, GtkAssistantPageType.SUMMARY);
connectionAssistant.addOnClose(&assistentComplete);
connectionAssistant.addOnCancel(&assistenctCancel);
connectionAssistant.showAll();
}
private void assistenctCancel(Assistant e)
{
/* TODO: Get this to work */
/* TODO: The `.close()` doesn't seem to work */
}
/* TODO: I want this code to run when we are on the summary page */
private void kak()
{
/* Summary data */
Label serverAddressLabel = new Label("");
serverAddressLabel.setMarkup("<b>Server Address:</b> "~serverAddress.getBuffer().getText());
Label serverPortLabel = new Label("");
serverPortLabel.setMarkup("<b>Server Port:</b> "~serverPort.getBuffer().getText());
Label accountUsername = new Label("");
accountUsername.setMarkup("<b>Account username:</b> "~username.getBuffer().getText());
Label accountPassword = new Label("");
accountPassword.setMarkup("<b>Account password:</b> "~password.getBuffer().getText());
summaryBox.add(serverAddressLabel);
summaryBox.add(serverPortLabel);
summaryBox.add(accountUsername);
summaryBox.add(accountPassword);
}
private void assistentComplete(Assistant)
{
/* Get the server details */
string serverAddress = strip(serverAddress.getBuffer().getText());
string serverPort = strip(serverPort.getBuffer().getText());
/* Get the account details */
string accountUsername = strip(username.getBuffer().getText());
string accountPassword = password.getBuffer().getText();
/* TODO: Check for emptiness */
if(cmp(serverAddress, "") == 0 || cmp(serverPort, "") == 0 || cmp(accountUsername, "") == 0 || cmp(accountPassword, "") == 0)
{
/* TODO: Handle error here */
}
else
{
/* Create a new Connection */
gui.connectServer(serverAddress, to!(ushort)(serverPort), [accountUsername, accountPassword]);
}
}
}

66
source/ProfileWIndow.d Normal file
View File

@ -0,0 +1,66 @@
/**
* Profile window
*
* User profile window
*/
import Connection;
import gtk.Window;
import gtk.Label;
import gtk.Image;
import std.conv;
import gtk.Box;
public final class ProfileWindow
{
private Connection connection;
private string username;
this(Connection connection, string username)
{
this.connection = connection;
this.username = username;
showWindow();
}
private void showWindow()
{
/* Create the window with the username as the title */
Window profileWindow = new Window(username);
/* Create a Box for contents */
Box profileBox = new Box(GtkOrientation.VERTICAL, 1);
/* Create a Image for the profile picture */
Image profileImage = new Image("/home/deavmi/Downloads/logo.png");
profileBox.add(profileImage);
// profileImage.
/* Create the username label */
Label usernameTitle = new Label("");
usernameTitle.setMarkup("<span size=\"20000\">"~username~"</span>");
profileBox.add(usernameTitle);
/* Display all props (keys) */
string[] props = connection.getClient().getProperties(username);
profileBox.add(new Label(to!(string)(props)));
/* Display all props (values) */
string[] propValues;
foreach(string property; props)
{
propValues ~= connection.getClient().getProperty(username, property);
}
profileBox.add(new Label(to!(string)(propValues)));
profileWindow.add(profileBox);
profileWindow.showAll();
// profileWindow.unmaximize();
// profileWindow.setAttachedTo()
}
}

35
source/UserDirectory.d Normal file
View File

@ -0,0 +1,35 @@
module UserDirectory;
import Connection;
import gtk.SearchBar;
import gtk.Entry;
import gtk.Window;
public final class UserDirectory
{
/* The associated connection */
private Connection connection;
this(Connection connection)
{
this.connection = connection;
initWindow();
}
private void initWindow()
{
Window userWindow = new Window(GtkWindowType.TOPLEVEL);
userWindow.setTitle("User directory");
SearchBar searchBar = new SearchBar();
Entry searchEntry = new Entry();
searchEntry.setText("fsdhjsdfhjkdsfhjksdfhjk");
// searchBar.handleEvent()
searchBar.connectEntry(searchEntry);
userWindow.add(searchBar);
userWindow.showAll();
}
}

View File

@ -1,29 +1,164 @@
// import gtk.Tooltip;
// import libdnet.dclient;
// import gtk.Label;
module UserNode;
// public final class UserNode
// {
// private Tooltip tooltip;
// private DClient client;
// private Label username;
import Connection;
import libdnet.client;
import gtk.Box;
import gtk.Button;
import gtk.Image;
import gtk.Label;
import gtk.Tooltip;
import gtk.Widget;
import std.string;
import ProfileWIndow;
// this(DClient client, Label username)
// {
// this.client = client;
// this.username = username;
public final class UserNode
{
private Connection connection;
private string username;
// initialize();
// }
private Box box;
// private void initialize()
// {
// username.getToo
// tooltip = new Tooltip(cast(GtkStruct*)username.getStruct());
// }
this(Connection connection, string username)
{
this.connection = connection;
this.username = username;
// // public Tooltip getToolTip()
// // {
initBox();
}
private void userButtonClick(Button)
{
/* Create a new ProfileWindow */
ProfileWindow profileWindow = new ProfileWindow(connection, username);
}
private void initBox()
{
/* Create a new Box */
box = new Box(GtkOrientation.HORIZONTAL, 10);
/* Layout [Button (Prescence Icon)] - Label <username> - [Button (Reply Icon)]*/
Button userButton = new Button();
Image userButtonImg = new Image("user-available", GtkIconSize.BUTTON);
userButton.setImage(userButtonImg);
// // }
// }
/* Set the handler for on click */
userButton.addOnClicked(&userButtonClick);
/* Create a label */
Label userLabel = new Label(username);
/* Enable the tooltip */
userLabel.setHasTooltip(true);
/* Set the handler to run on hover */
userLabel.addOnQueryTooltip(&userLabelHoverHandler);
/* TODO: Implement me */
/* Add both components */
box.add(userButton);
box.add(userLabel);
/* Add the direct message button */
Button messageButton = new Button();
Image messageButtonImg = new Image("mail-forward", GtkIconSize.BUTTON);
messageButton.setImage(messageButtonImg);
/* Set the handler for on click */
messageButton.addOnClicked(&newDirectMessage);
box.add(messageButton);
}
/**
* This is the handler for when the "direct message" button is clicked
*
* It will call `addDirectMessage_unsafe` with the username specified
*/
private void newDirectMessage(Button)
{
connection.addDirectMessage_unsafe(username);
}
/**
* Event handler to be run when you hover over a user's
* username in the Users sidebar list which will show
* the status as text (and in an icon format), the user's
* username and also their status message
*/
private bool userLabelHoverHandler(int, int, bool, Tooltip tooltip, Widget userLabel)
{
/* Get the client */
DClient client = connection.getClient();
/* The username hovered over */
string userHover = (cast(Label)userLabel).getText();
/* The final tooltip */
string toolTipText = "<b>"~userHover~"</b>";
/* Check if there is a `precensce` message */
if(client.isProperty(userHover, "pres"))
{
/* Fetch the precensce */
string prescence = client.getProperty(userHover, "pres");
/* Set the icon */
tooltip.setIconFromIconName(statusToGtkIcon(prescence), GtkIconSize.DIALOG);
/* Append the precesnee to the tooltip text */
toolTipText ~= "\n"~prescence;
}
/* Check if there is a `status` message */
if(client.isProperty(userHover, "status"))
{
/* Next is status message */
string status = client.getProperty(userHover, "status");
/* Append the status to the tooltip text */
toolTipText ~= "\n<i>"~status~"</i>";
}
/* Set the tooltip text */
tooltip.setMarkup(toolTipText);
/* TODO: Point of return value? */
return 1;
}
private static string statusToGtkIcon(string status)
{
/* The GTK icon */
string gtkIcon = "image-missing";
if(cmp(status, "available") == 0)
{
gtkIcon = "user-available";
}
else if(cmp(status, "away") == 0)
{
gtkIcon = "user-away";
}
else if(cmp(status, "busy") == 0)
{
gtkIcon = "user-busy";
}
/* TODO: This doesn't make sense */
else if(cmp(status, "offline") == 0)
{
gtkIcon = "user-offline";
}
return gtkIcon;
}
public Box getBox()
{
return box;
/* TODO: Implement me */
}
}

View File

@ -18,67 +18,14 @@ import gdk.Threads : threadsEnter, threadsLeave;
import gtk.SelectionData;
import gtk.Widget;
void main()
{
/* Initialize the framework with no arguments */
string[] args;
Main.initMultiThread(args);
// threadsEnter();
// /* Create the main window */
// MainWindow main = new MainWindow("unnamed");
// Box grid = new Box(GtkOrientation.VERTICAL, 1);
// MenuBar menu = new MenuBar();
// grid.add(menu);
// MenuItem fileMenu = new MenuItem("unamed");
// MenuItem thing1 = new MenuItem("poes");
// Menu bruh = new Menu();
// bruh.add(thing1);
// fileMenu.setSubmenu(bruh);
// menu.add(fileMenu);
// menu.add(new MenuItem("bruh"));
// /* Status bar */
// Statusbar statusBar = new Statusbar();
// statusBar.add(new Label("Gustav: Not connected"));
// grid.add(new Label("poo"));
// ListBox channels = new ListBox();
// Notebook tabs = new Notebook();
// tabs.add(channels);
// grid.add(tabs);
// grid.packEnd(statusBar, false, false, 0);
// Label k = new Label("dhjhfdjfhfjk");
// channels.add(k);
// main.add(grid);
// /* Display the window and all its components */
// main.showAll();
// k.setText("peoe");
// tabs.appendPage(new Label("lol"), "server2");
// main.showAll();
GUI gui = new GUI();
gui.start();
@ -86,9 +33,6 @@ void main()
/* Start the event loop */
Main.run();
}

345
source/areas/Channel.d Normal file
View File

@ -0,0 +1,345 @@
/**
* Channel
*
* Represents a channel which is a collection
* of the channel name the users list widget,
* the title widget and the chat list box widget
* along with the input box state
*/
module areas.Channel;
import gtk.Box;
import gtk.ListBox;
import gtk.Label;
import gtk.TextView;
import libdnet.client;
import gtk.Label;
import std.string;
import gtk.Button;
import gtk.Tooltip;
import gtk.Widget;
import gtk.ScrolledWindow;
import gtk.Button;
import gtk.Entry;
import UserNode;
import pango.PgAttributeList;
import pango.PgAttribute;
import Connection;
import gogga;
import areas.MessageArea;
public final class Channel : MessageArea
{
private DClient client;
private Connection connection;
/**
* Channel details
*/
private string channelName;
/**
* UI components
*
* Users's box
* - Label users
* - ListBox users
*/
private ListBox users;
private ListBox textArea;
private Entry textInput;
/* TODO: No mutexes should be needed (same precaution) as the GTK lock provides safety */
private string[] usersString;
this(Connection connection, string channelName)
{
this.client = connection.getClient();
this.connection = connection;
this.channelName = channelName;
initializeBox();
}
private void initializeBox()
{
box = new Box(GtkOrientation.HORIZONTAL, 1);
/* The user's box */
Box userBox = new Box(GtkOrientation.VERTICAL, 1);
/* The user's list */
users = new ListBox();
userBox.add(new Label("Users"));
// import gtk.Expander;
// Expander g = new Expander("Bruh");
// g.setExpanded(true)
// g.add(users);
userBox.add(users);
/* The text box */
Box textBox = new Box(GtkOrientation.VERTICAL, 1);
/* Channel title */
Label channelTitleLabel = new Label(channelName);
channelTitleLabel.setMarkup("<span size=\"large\"><b>"~channelName~"</b></span>");
textBox.add(channelTitleLabel);
/* The messages box */
textArea = new ListBox();
ScrolledWindow scrollTextChats = new ScrolledWindow(textArea);
textBox.add(scrollTextChats);
/* The Box for the whole |attach button| text field| send button| */
Box textInputBox = new Box(GtkOrientation.HORIZONTAL, 1);
import gtk.Image;
/* The attachment button */
Button attachFileButton = new Button("Upload");
Image attachFileButtonIcon = new Image("user-available", GtkIconSize.BUTTON); /* TODO: Fix icon now showing */
attachFileButton.setImage(attachFileButtonIcon);
attachFileButton.addOnClicked(&uploadFileDialog);
textInputBox.add(attachFileButton);
/* The text input */
textInput = new Entry();
textInput.addOnActivate(&sendMessageEnter);
textInput.addOnChanged(&textChangd);
textInputBox.packStart(textInput,1,1,0);
/* The send button */
Button sendButton = new Button("Send");
sendButton.addOnClicked(&sendMessageBtn);
textInputBox.add(sendButton);
textBox.add(textInputBox);
box.add(textBox);
box.packEnd(userBox,0,0,0);
textBox.setChildPacking(scrollTextChats, true, true, 0, GtkPackType.START);
box.setChildPacking(textBox, true, true, 0, GtkPackType.START);
}
private void uploadFileDialog(Button e)
{
import gtk.FileChooserDialog; /* TODO: Set parent */
FileChooserDialog fileChooser = new FileChooserDialog("Send file to "~channelName, null, FileChooserAction.OPEN);
fileChooser.run();
gprintln("Selected file: "~fileChooser.getFilename());
}
import gtk.EditableIF;
private void textChangd(EditableIF)
{
/* If the text box just became empty stop ssending typing notifications */
/* Send typing stats */
// client.sendIsTyping(channelName, true);
/* TODO: Client implement wiht different tag? */
}
private void sendMessageEnter(Entry)
{
/* Retrieve the message */
string message = textInput.getBuffer().getText();
/* TODO: Add the message to our log (as it won't be delivered to us) */
sendMessage(message);
/* Send the message */
client.sendMessage(0, channelName, message);
/* Clear the text box */
textInput.getBuffer().setText("",0);
box.showAll();
}
private void sendMessageBtn(Button)
{
/* Retrieve the message */
string message = textInput.getBuffer().getText();
/* TODO: Add the message to our log (as it won't be delivered to us) */
sendMessage(message);
/* Send the message */
client.sendMessage(0, channelName, message);
/* Clear the text box */
textInput.getBuffer().setText("",0);
box.showAll();
}
public string getName()
{
return channelName;
}
private Box getUserListItem(string username)
{
/* This is an item for a username in this Channel's user list */
Box box = new Box(GtkOrientation.HORIZONTAL, 1);
import gtk.IconView;
IconView icon = new IconView();
import gtk.StatusIcon;
StatusIcon d = new StatusIcon("user-available");
return box;
}
// private bool userLabelPopup(Widget)
// {
// import std.stdio;
// writeln("NOWNOWNOWNOWNOW");
// return true;
// }
public void populateUsersList()
{
string[] memberList = client.getMembers(channelName);
foreach(string member; memberList)
{
/* Create the user entry in the list */
UserNode userNode = new UserNode(connection, member);
users.add(userNode.getBox());
/* Add the user to the tracking list */
usersString~=member;
}
}
public void channelJoin(string username)
{
/* The label to add */
Label joinLabel = new Label("--> "~username~" joined the channel");
joinLabel.setHalign(GtkAlign.START);
PgAttributeList joinLabelAttrs = new PgAttributeList();
PgAttribute joinLabelAttr = PgAttribute.styleNew(PangoStyle.ITALIC);
joinLabelAttrs.insert(joinLabelAttr);
joinLabel.setAttributes(joinLabelAttrs);
/* Add join message to message log */
textArea.add(joinLabel);
/* Create the user entry in the list */
UserNode userNode = new UserNode(connection, username);
users.add(userNode.getBox());
/* Add the user to the tracking list */
usersString~=username;
}
public void channelLeave(string username)
{
/* The label to add */
Label leaveLabel = new Label("<-- "~username~" left the channel");
leaveLabel.setHalign(GtkAlign.START);
PgAttributeList leaveLabelAttrs = new PgAttributeList();
PgAttribute leaveLabelAttr = PgAttribute.styleNew(PangoStyle.ITALIC);
leaveLabelAttrs.insert(leaveLabelAttr);
leaveLabel.setAttributes(leaveLabelAttrs);
/* Add leave message to message log */
textArea.add(leaveLabel);
/* TODO: Better way with just removing one dude */
/* Remove the user form users list */
string[] newUsers;
foreach(string currentUser; usersString)
{
if(cmp(currentUser, username))
{
newUsers ~= currentUser;
}
}
usersString = newUsers;
/* Clear list */
users.removeAll();
foreach(string currentUser; usersString)
{
/* Create the user entry in the list */
UserNode userNode = new UserNode(connection, currentUser);
users.add(userNode.getBox());
}
}
public void sendMessage(string message)
{
/* TOOD: Pass in connection perhaps */
string username = "Yourself";
/* Create the MessageBox */
Box messageBox = new Box(GtkOrientation.VERTICAL, 1);
/* Create and add the username */
Label usernameLabel = new Label("");
usernameLabel.setMarkup("<b>"~username~"</b>");
usernameLabel.setHalign(GtkAlign.END);
messageBox.add(usernameLabel);
/* Create and add the message */
Label messageLabel = new Label(message);
messageLabel.setHalign(GtkAlign.END);
messageLabel.setSelectable(true);
messageBox.add(messageLabel);
/* Add the message to the log */
textArea.add(messageBox);
}
public void receiveMessage(string username, string message)
{
/* Create the MessageBox */
Box messageBox = new Box(GtkOrientation.VERTICAL, 1);
/* Create and add the username */
Label usernameLabel = new Label("");
usernameLabel.setMarkup("<b>"~username~"</b>");
usernameLabel.setHalign(GtkAlign.START);
messageBox.add(usernameLabel);
/* Create and add the message */
Label messageLabel = new Label(message);
messageLabel.setHalign(GtkAlign.START);
messageLabel.setSelectable(true);
messageBox.add(messageLabel);
// import gtk.Image;
// Image d = new Image("/home/deavmi/Downloads/5207740.jpg");
// messageBox.add(d);
/* Add the message to the log */
textArea.add(messageBox);
}
}

View File

@ -0,0 +1,25 @@
/**
* MessageArea
*
* Represents the binding of a text entry, send button, user list (sometimes)
* and message log - basically the place where you message a channel or someone
*
* The sub-classes are "Direct Message" and "Channel"
*/
module areas.MessageArea;
import gtk.Box;
public class MessageArea
{
/* TODO: Implement me */
/* The area's Box (where everything is contained) */
protected Box box;
public Box getBox()
{
return box;
}
}

215
source/areas/User.d Normal file
View File

@ -0,0 +1,215 @@
module areas.User;
import areas.MessageArea;
import gtk.Box;
import gtk.ListBox;
import gtk.Label;
import gtk.TextView;
import libdnet.client;
import gtk.Label;
import std.string;
import gtk.Button;
import gtk.Tooltip;
import gtk.Widget;
import gtk.ScrolledWindow;
import gtk.Button;
import gtk.Entry;
import UserNode;
import pango.PgAttributeList;
import pango.PgAttribute;
import Connection;
import gogga;
public final class User : MessageArea
{
private DClient client;
private Connection connection;
/**
* Username
*/
private string username;
/**
* UI components
*
*/
// private ListBox users;
private ListBox textArea;
private Entry textInput;
/* TODO: No mutexes should be needed (same precaution) as the GTK lock provides safety */
// private string[] usersString;
this(Connection connection, string username)
{
this.client = connection.getClient();
this.connection = connection;
this.username = username;
initializeBox();
}
public string getUsername()
{
return username;
}
private void initializeBox()
{
box = new Box(GtkOrientation.HORIZONTAL, 1);
// box.add(new Label("poes"));
/* The text box */
Box textBox = new Box(GtkOrientation.VERTICAL, 1);
/* Channel title */
Label channelTitleLabel = new Label(username);
channelTitleLabel.setMarkup("<span size=\"large\"><b>"~username~"</b></span>");
textBox.add(channelTitleLabel);
/* The messages box */
textArea = new ListBox();
ScrolledWindow scrollTextChats = new ScrolledWindow(textArea);
textBox.add(scrollTextChats);
/* The Box for the whole |attach button| text field| send button| */
Box textInputBox = new Box(GtkOrientation.HORIZONTAL, 1);
import gtk.Image;
/* The attachment button */
Button attachFileButton = new Button("Upload");
Image attachFileButtonIcon = new Image("user-available", GtkIconSize.BUTTON); /* TODO: Fix icon now showing */
attachFileButton.setImage(attachFileButtonIcon);
attachFileButton.addOnClicked(&uploadFileDialog);
textInputBox.add(attachFileButton);
/* The text input */
textInput = new Entry();
textInput.addOnActivate(&sendMessageEnter);
textInput.addOnChanged(&textChangd);
textInputBox.packStart(textInput,1,1,0);
/* The send button */
Button sendButton = new Button("Send");
sendButton.addOnClicked(&sendMessageBtn);
textInputBox.add(sendButton);
textBox.add(textInputBox);
box.add(textBox);
// box.packEnd(userBox,0,0,0);
textBox.setChildPacking(scrollTextChats, true, true, 0, GtkPackType.START);
box.setChildPacking(textBox, true, true, 0, GtkPackType.START);
}
import gtk.EditableIF;
private void textChangd(EditableIF)
{
/* If the text box just became empty stop ssending typing notifications */
/* Send typing stats */
// client.sendIsTyping(channelName, true);
/* TODO: Client implement wiht different tag? */
}
private void sendMessageEnter(Entry)
{
/* Retrieve the message */
string message = textInput.getBuffer().getText();
/* TODO: Add the message to our log (as it won't be delivered to us) */
sendMessage(message);
/* Send the message */
client.sendMessage(1, username, message);
/* Clear the text box */
textInput.getBuffer().setText("",0);
box.showAll();
}
private void sendMessageBtn(Button)
{
/* Retrieve the message */
string message = textInput.getBuffer().getText();
/* TODO: Add the message to our log (as it won't be delivered to us) */
sendMessage(message);
/* Send the message */
client.sendMessage(1, username, message);
/* Clear the text box */
textInput.getBuffer().setText("",0);
box.showAll();
}
public void sendMessage(string message)
{
/* TOOD: Pass in connection perhaps */
string username = "Yourself";
/* Create the MessageBox */
Box messageBox = new Box(GtkOrientation.VERTICAL, 1);
/* Create and add the username */
Label usernameLabel = new Label("");
usernameLabel.setMarkup("<b>"~username~"</b>");
usernameLabel.setHalign(GtkAlign.END);
messageBox.add(usernameLabel);
/* Create and add the message */
Label messageLabel = new Label(message);
messageLabel.setHalign(GtkAlign.END);
messageLabel.setSelectable(true);
messageBox.add(messageLabel);
/* Add the message to the log */
textArea.add(messageBox);
}
public void receiveMessage(string username, string message)
{
/* Create the MessageBox */
Box messageBox = new Box(GtkOrientation.VERTICAL, 1);
/* Create and add the username */
Label usernameLabel = new Label("");
usernameLabel.setMarkup("<b>"~username~"</b>");
usernameLabel.setHalign(GtkAlign.START);
messageBox.add(usernameLabel);
/* Create and add the message */
Label messageLabel = new Label(message);
messageLabel.setHalign(GtkAlign.START);
messageLabel.setSelectable(true);
messageBox.add(messageLabel);
// import gtk.Image;
// Image d = new Image("/home/deavmi/Downloads/5207740.jpg");
// messageBox.add(d);
/* Add the message to the log */
textArea.add(messageBox);
}
private void uploadFileDialog(Button e)
{
import gtk.FileChooserDialog; /* TODO: Set parent */
FileChooserDialog fileChooser = new FileChooserDialog("Send file to "~username, null, FileChooserAction.OPEN);
fileChooser.run();
gprintln("Selected file: "~fileChooser.getFilename());
}
}

View File

@ -13,21 +13,38 @@ import gtk.MenuItem;
import std.stdio;
import gtk.Statusbar;
import gtk.Toolbar;
import gtk.ToolButton;
import gtk.ScrolledWindow;
import gtk.SeparatorToolItem;
import gtk.ToolItem;
import gtk.SearchEntry;
import gtk.Image;
import Connection;
import areas.Channel;
import std.socket;
import std.conv;
public class GUI : Thread
{
/* Main window (GUI homepage) */
public MainWindow mainWindow;
private MenuBar menuBar;
private Toolbar toolbar;
private Box box;
private Box welcomeBox;
public Notebook notebook;
private Statusbar statusBar;
private Connection[] connections;
private ListBox list;
@ -41,8 +58,10 @@ public class GUI : Thread
private void worker()
{
initializeGUI();
te();
te();
tl();
writeln("brg");
while(true)
@ -54,16 +73,64 @@ public class GUI : Thread
private void initializeGUI()
{
initializeMainWindow();
}
/* Test adding a connection */
for(uint i = 0; i < 5; i++)
{
// connections ~= new Connection(this, parseAddress("0.0.0.0", 7777));
}
connections ~= new Connection(this, parseAddress("0.0.0.0", 7777), ["testGustav1", "bruh"]);
/**
* The welcome box is shown before
* you have added any connections
* (it takes place of the Notebook)
* and shows information about the
* application
*
* Once you make your first conneciton
* it is removed and its space is taken
* up by the Notebook
*/
private Box getWelcomeBox()
{
/* Create a vertically stacking Box */
Box welcomeBox = new Box(GtkOrientation.VERTICAL, 1);
/* Add the logo */
Image logo = new Image("user-available", GtkIconSize.DIALOG);
logo.setPixelSize(250);
welcomeBox.add(logo);
/* Create the welcome text */
Label title = new Label("<span size=\"100\">Gustav</span>");
title.setMarkup("<span font_desc=\"Open Sans Extrabold\" size=\"50000\">Gustav</span>");
welcomeBox.add(title);
/* Create the welcome tagline */
Label tagline = new Label("<span size=\"100\">Gustav</span>");
tagline.setMarkup("<span size=\"30000\">GTK+ graphical DNET client</span>");
welcomeBox.add(tagline);
Label findServersLabel = new Label("<a href=\"\">fok</a>");
findServersLabel.setMarkup("<a href=\"\">Find some servers</a>");
welcomeBox.add(findServersLabel);
Label configureConnectionsLabel = new Label("<a href=\"\">Configure connections</a>");
configureConnectionsLabel.setMarkup("<a href=\"\">Configure connections</a>");
configureConnectionsLabel.addOnActivateLink(&conifgureConnectionsAssistant);
welcomeBox.add(configureConnectionsLabel);
Label connectGenesisLabel = new Label("<a href=\"\">Connect to the genesis server</a>");
connectGenesisLabel.setMarkup("<span size=\"12000\"> <a href=\"\">Connect to the genesis server</a></span>");
connectGenesisLabel.addOnActivateLink(&welcomeGenesisLabelClick);
welcomeBox.add(connectGenesisLabel);
return welcomeBox;
}
private bool welcomeGenesisLabelClick(string, Label)
{
connectServer("0.0.0.0", 7777, ["testGustav"~to!(string)(connections.length), "bruh"]);
return 1;
}
/**
@ -86,7 +153,7 @@ public class GUI : Thread
* |component 1|
* |component 2|
*/
Box box = new Box(GtkOrientation.VERTICAL, 1);
box = new Box(GtkOrientation.VERTICAL, 1);
/**
* Add needed components
@ -99,12 +166,22 @@ public class GUI : Thread
toolbar = getToolbar();
box.add(toolbar);
notebook = new Notebook();
notebook.setScrollable(true);
box.add(notebook);
/* Create the welcome box and set it */
welcomeBox = getWelcomeBox();
box.add(welcomeBox);
statusBar = new Statusbar();
statusBar.add(new Label("Gustav: Bruh"));
box.setChildPacking(notebook, true, true, 0, GtkPackType.START);
// import gtk.IconView;
// IconView j = new IconView();
// j.set
// statusBar.add(d);
box.packEnd(statusBar, 0, 0, 0);
//notebook.add(createServerTab());
@ -124,68 +201,376 @@ public class GUI : Thread
private Toolbar getToolbar()
{
/* Create a new Toolbar */
Toolbar toolbar = new Toolbar();
/* Status selector dropdown */
import gtk.ComboBox;
import gtk.ToolButton;
// Menu menu = new Menu();
// menu.add(new MenuItem(""));
ComboBox statusBox = new ComboBox();
statusBox.setTitle("Status");
/* TODO */
/* Set available button */
ToolButton setAvail = new ToolButton("");
setAvail.setLabel("available");
setAvail.setIconName("user-available");
toolbar.add(setAvail);
/* Set away button */
ToolButton setAway = new ToolButton("");
setAway.setLabel("away");
setAway.setIconName("user-away");
toolbar.add(setAway);
/* Set busy button */
ToolButton setBusy = new ToolButton("");
setBusy.setLabel("busy");
setBusy.setIconName("user-busy");
toolbar.add(setBusy);
/* Assign actions */
setAvail.addOnClicked(&setStatus);
setAway.addOnClicked(&setStatus);
setBusy.addOnClicked(&setStatus);
/* The status box */
Entry statusBox = new Entry();
statusBox.addOnActivate(&setStatusMessage);
statusBox.setPlaceholderText("I'm currently...");
ToolItem statusBoxItem = new ToolItem();
statusBoxItem.add(statusBox);
toolbar.add(statusBoxItem);
/* Add a seperator */
toolbar.add(new SeparatorToolItem());
/* List channels button */
ToolButton channelListButton = new ToolButton("");
channelListButton.setIconName("emblem-documents");
channelListButton.setTooltipText("List channels");
channelListButton.addOnClicked(&listChannels);
toolbar.add(channelListButton);
/* TODO: Join channel button */
ToolButton joinChannelButton = new ToolButton("");
joinChannelButton.setIconName("document-new");
joinChannelButton.setTooltipText("Join channel");
toolbar.add(joinChannelButton);
/* TODO: Leave channel button */
//toolbar.add(new ToolButton("user-available,""Available"));
// toolbar.add(new ToolButton("Away"));
// toolbar.add(new ToolButton("Busy"));
// toolbar.add(new Label("Away"));
// toolbar.add(new Label("Busy"));
// import gtk.ToolItem;
SearchEntry dd = new SearchEntry();
ToolItem j = new ToolItem();
j.add(dd);
toolbar.add(j);
// ToolItem toolItem = new ToolItem();
// toolItem.add(new Label("Available"));
// statusBox.add()
//toolbar.add(statusBox);
return toolbar;
}
import gtk.ToolButton;
private void setStatus(ToolButton x)
import gtk.Entry;
import std.string;
private void setStatusMessage(Entry f)
{
/* If there are no connections */
if(!connections.length)
{
import gtk.MessageDialog;
MessageDialog errorDialog = new MessageDialog(mainWindow, GtkDialogFlags.MODAL, GtkMessageType.ERROR, GtkButtonsType.CLOSE, false, "Cannot set status\n\nYou are not connected to a server");
errorDialog.setIconName("user-available");
// errorDialog.set
errorDialog.run();
return;
}
/* Get the current connection */
Connection currentConnection = connections[notebook.getCurrentPage()];
/* Get the input text (removing leading and trailing whitespace) */
string statusTextInput = f.getBuffer().getText();
statusTextInput = strip(statusTextInput);
/* Set the text box to the stripped version */
//f.getBuffer().setText(statusTextInput, cast(int)statusTextInput.length);
/* If the status text is empty */
if(cmp(statusTextInput, "") == 0)
{
/* Delete the status property */
currentConnection.getClient().deleteProperty("status");
}
/* If the status text is non empty */
else
{
/* Set the status */
currentConnection.getClient().setProperty("status", statusTextInput);
}
//f.setInputHints(GtkInputHints.)
/* Defocus the currently focused widget which would always be me if you are hitting enter */
mainWindow.setFocus(null);
}
private void about(MenuItem)
{
import gtk.AboutDialog;
AboutDialog about = new AboutDialog();
about.setVersion("21893");
/* TODO: License */
/* TODO: Icon */
/* TODO: Buttons or close */
/* TODO: Set version based on compiler flag */
about.setLogoIconName("user-available");
about.setArtists(["i wonder if I could commision an artwork from her"]);
/* Set all the information */
about.setLicense("LICENSE GOES HERE");
about.setComments("A clean GTK+ graphical DNET client");
about.setWebsite("http://deavmi.assigned.network/docs/dnet/site");
about.setDocumenters(["ss","fdsfsd"]);
about.setAuthors(["Tristan B. Kildaire (Deavmi) - deavmi@disroot.org"]);
/* Show the about dialog */
about.showAll();
}
import gtk.Button;
/**
* Returns a Box which contains channel list item
*/
private class JoinButton : Button
{
private string channelName;
this(string channelName)
{
this.channelName = channelName;
}
public string getChannelName()
{
return channelName;
}
}
private Box channelItemList(Connection currentConnection, string channelName)
{
/* Create the main container */
Box containerMain = new Box(GtkOrientation.HORIZONTAL, 1);
/* Add the channel label */
Label channelLabel = new Label("");
channelLabel.setHalign(GtkAlign.START);
channelLabel.setMarkup("<b>"~channelName~"</b>");
/* Add the member count */
ulong memberCount = currentConnection.getClient().getMemberCount(channelName);
Label memberCountLabel = new Label("");
memberCountLabel.setHalign(GtkAlign.START);
memberCountLabel.setText(to!(string)(memberCount)~" members");
/* Create the channel box */
Box channelBox = new Box(GtkOrientation.VERTICAL, 1);
channelBox.add(channelLabel);
channelBox.add(memberCountLabel);
/* Join button */
JoinButton joinButton = new JoinButton(channelName);
joinButton.setLabel("Join");
/* Add this then a button */
containerMain.add(channelBox);
containerMain.packEnd(joinButton,0,0,0);
joinButton.addOnClicked(&selectChannel);
/* TODO: COnsider adding member list */
/* TODO: Seperate queue for dynamic updates to this list */
containerMain.setTooltipMarkup("<b>"~channelName~"</b>\n"~to!(string)(memberCount)~" members\n\n"~to!(string)(currentConnection.getClient().getMembers(channelName)));
return containerMain;
}
private class JoinButtonCustom : Button
{
private Entry channelInputBox;
this(Entry channelInputBox)
{
/* Set the button's text to "Join" */
super("Join");
/* Set the handler for the button */
addOnClicked(&handler);
this.channelInputBox = channelInputBox;
}
private void handler(Button)
{
/* Get the current connection */
Connection currentConnection = connections[notebook.getCurrentPage()];
/* Get the name of the channel selected */
string channelSelected = channelInputBox.getText();
/* Join the channel on this connection */
currentConnection.joinChannel(channelSelected);
}
}
/**
* List channels
*
* Brings up a window listing channels of the current server
*/
private void listChannels(ToolButton)
{
import gtk.Window;
/* Create the window */
Window win = new Window(GtkWindowType.TOPLEVEL);
/* Create the list of channels */
ListBox channelsList = new ListBox();
win.add(new ScrolledWindow(channelsList));
/* TODO: Temporary, REMOVE AFTWR TESTING (ADDED ON 27th of JAN 2021) */
Box box = new Box(GtkOrientation.HORIZONTAL, 1);
Entry customChannelEntry = new Entry();
box.packStart(customChannelEntry, 1, 1, 1);
box.add(new JoinButtonCustom(customChannelEntry));
channelsList.add(box);
/* If there are no available connections */
if(!connections.length)
{
import gtk.MessageDialog;
MessageDialog errorDialog = new MessageDialog(mainWindow, GtkDialogFlags.MODAL, GtkMessageType.ERROR, GtkButtonsType.CLOSE, false, "Cannot list channels\n\nYou are not connected to a server");
errorDialog.setIconName("user-available");
// errorDialog.set
errorDialog.run();
return;
}
/* Get the current connection */
Connection currentConnection = connections[notebook.getCurrentPage()];
/* Fetch the channels */
string[] channels = currentConnection.getClient().list();
/* Add each channel */
foreach(string channel; channels)
{
// channelsList.add(new Label(channel));
channelsList.add(channelItemList(currentConnection, channel));
writeln("bruh: "~channel);
channelsList.showAll();
}
/* TODO: Add handler for clicking label that lets you join the channel */
// channelsList.addOnSelectedRowsChanged(&selectChannel);
//channelsList.add
win.showAll();
}
/**
* Opens a new window for connecting to a server
*/
private void connect(MenuItem)
{
import gtk.Window;
/* Create the window */
Window win = new Window(GtkWindowType.TOPLEVEL);
//import gtk.Text
win.showAll();
}
/**
* Run when you select the 'Join' button next tio an already existing
* channel in the channels list
*/
private void selectChannel(Button s)
{
/* Get the current connection */
Connection currentConnection = connections[notebook.getCurrentPage()];
/* Set the status */
currentConnection.getClient().setStatus(x.getLabel());
/* Get the name of the channel selected */
string channelSelected = (cast(JoinButton)s).getChannelName(); //(cast(Label)(s.getSelectedRow().getChild())).getText();
/* Join the channel on this connection */
currentConnection.joinChannel(channelSelected);
}
private bool conifgureConnectionsAssistant(string, Label)
{
import ConnectionAssistant;
ConnectionAssistant ass = new ConnectionAssistant(this);
return 0;
}
private void setStatus(ToolButton x)
{
/* If there are any available connections */
if(connections.length)
{
/* Get the current connection */
Connection currentConnection = connections[notebook.getCurrentPage()];
/* Set the status */
currentConnection.getClient().setProperty("pres", x.getLabel());
}
/* If there are no connections */
else
{
import gtk.MessageDialog;
MessageDialog errorDialog = new MessageDialog(mainWindow, GtkDialogFlags.MODAL, GtkMessageType.ERROR, GtkButtonsType.CLOSE, false, "Cannot set prescence\n\nYou are not connected to a server");
errorDialog.setIconName("user-available");
// errorDialog.set
errorDialog.run();
}
}
private MenuBar initializeMenuBar()
@ -204,18 +589,40 @@ public class GUI : Thread
connectItem.addOnActivate(&connectButton);
gustavMenu.add(connectItem);
/* Connect v2 option */
MenuItem connectItem2 = new MenuItem();
connectItem2.setLabel("Connect");
connectItem2.addOnActivate(&connect);
gustavMenu.add(connectItem2);
/* Exit option */
MenuItem exitItem = new MenuItem();
exitItem.setLabel("Exit");
exitItem.addOnActivate(&exitButton);
gustavMenu.add(exitItem);
/* Help menu */
MenuItem helpMenuItem = new MenuItem();
helpMenuItem.setLabel("Help");
Menu helpMenu = new Menu();
helpMenuItem.setSubmenu(helpMenu);
/* About option */
MenuItem aboutItem = new MenuItem();
aboutItem.setLabel("About");
aboutItem.addOnActivate(&about);
helpMenu.add(aboutItem);
/* Add all menues */
menuBar.add(gustavMenuItem);
menuBar.add(helpMenuItem);
return menuBar;
}
@ -241,7 +648,41 @@ public class GUI : Thread
private void connectButton(MenuItem)
{
connections ~= new Connection(this, parseAddress("0.0.0.0", 7777), ["testGustav1", "bruh"]);
connectServer("0.0.0.0", 7777, ["testGustav"~to!(string)(connections.length), "bruh"]);
}
/**
* Connects to the provided server,
* add the tab as well
*
* NOTE: To be called only by a GTK signal
* handler
*/
public void connectServer(string address, ushort port, string[] authDetails)
{
/**
* If this is our first connection then
* create a new Notebook which will
* hold the connection/session tabs
* and remove the welcome page
*/
if(!notebook)
{
notebook = new Notebook();
notebook.setScrollable(true);
box.add(notebook);
box.setChildPacking(notebook, true, true, 0, GtkPackType.START);
box.remove(welcomeBox);
box.showAll();
}
/* Create the new Connection */
Connection newConnection = new Connection(this, parseAddress(address, port), authDetails);
connections ~= newConnection;
// import UserDirectory;
// UserDirectory d = new UserDirectory(newConnection);
}
private void shutdownConnections()