2020-10-17 11:54:07 +00:00
module gui ;
import core.thread ;
import gtk.MainWindow ;
import gtk.ListBox ;
import gtk.Label ;
import gtk.Notebook ;
import gdk.Threads : te = threadsEnter , tl = threadsLeave ;
import gtk.MenuBar ;
import gtk.Box ;
import gtk.Menu ;
import gtk.MenuItem ;
import std.stdio ;
2020-10-17 13:58:09 +00:00
import gtk.Statusbar ;
2020-10-18 19:41:22 +00:00
import gtk.Toolbar ;
2020-10-19 14:23:00 +00:00
import gtk.ToolButton ;
2020-10-19 16:01:00 +00:00
import gtk.ScrolledWindow ;
2020-10-20 06:00:20 +00:00
import gtk.SeparatorToolItem ;
2020-10-23 12:02:07 +00:00
import gtk.ToolItem ;
import gtk.SearchEntry ;
2020-10-23 13:01:26 +00:00
import gtk.Image ;
2020-10-17 11:54:07 +00:00
import Connection ;
2020-10-19 16:32:53 +00:00
import Channel ;
2020-10-17 11:54:07 +00:00
import std.socket ;
2020-10-19 07:27:10 +00:00
import std.conv ;
2020-10-17 11:54:07 +00:00
public class GUI : Thread
{
/* Main window (GUI homepage) */
public MainWindow mainWindow ;
private MenuBar menuBar ;
2020-10-18 19:41:22 +00:00
private Toolbar toolbar ;
2020-10-23 12:39:12 +00:00
private Box box ;
private Box welcomeBox ;
2020-10-17 11:54:07 +00:00
public Notebook notebook ;
2020-10-23 12:39:12 +00:00
2020-10-17 13:58:09 +00:00
private Statusbar statusBar ;
2020-10-17 11:54:07 +00:00
2020-10-23 12:39:12 +00:00
2020-10-17 11:54:07 +00:00
private Connection [ ] connections ;
private ListBox list ;
this ( )
{
super ( & worker ) ;
}
private void worker ( )
{
initializeGUI ( ) ;
2020-10-23 15:10:44 +00:00
2020-10-17 11:54:07 +00:00
te ( ) ;
2020-10-23 12:39:12 +00:00
2020-10-17 11:54:07 +00:00
tl ( ) ;
writeln ( "brg" ) ;
while ( true )
{
}
}
private void initializeGUI ( )
{
initializeMainWindow ( ) ;
2020-10-23 12:39:12 +00:00
}
2020-10-17 11:54:07 +00:00
2020-10-17 13:58:09 +00:00
2020-10-23 13:01:26 +00:00
/ * *
* 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
* /
2020-10-23 12:39:12 +00:00
private Box getWelcomeBox ( )
{
2020-10-23 13:01:26 +00:00
/* Create a vertically stacking Box */
2020-10-23 12:39:12 +00:00
Box welcomeBox = new Box ( GtkOrientation . VERTICAL , 1 ) ;
2020-10-23 13:01:26 +00:00
/* 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>" ) ;
2020-10-23 13:17:00 +00:00
title . setMarkup ( "<span font_desc=\"Open Sans Extrabold\" size=\"50000\">Gustav</span>" ) ;
2020-10-23 13:01:26 +00:00
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 ) ;
2020-10-23 12:39:12 +00:00
2020-10-23 14:10:01 +00:00
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>" ) ;
2020-10-23 20:04:19 +00:00
configureConnectionsLabel . addOnActivateLink ( & conifgureConnectionsAssistant ) ;
2020-10-23 14:10:01 +00:00
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 ) ;
2020-10-23 13:17:00 +00:00
2020-10-23 12:39:12 +00:00
return welcomeBox ;
2020-10-17 11:54:07 +00:00
}
2020-10-23 14:10:01 +00:00
private bool welcomeGenesisLabelClick ( string , Label )
{
connectServer ( "0.0.0.0" , 7777 ) ;
return 1 ;
}
2020-10-17 11:54:07 +00:00
/ * *
* Initializes the main home screen window
* /
private void initializeMainWindow ( )
{
/* Get GTK lock */
te ( ) ;
/* Create a window */
mainWindow = new MainWindow ( "unamed" ) ;
/ * *
* Create a Box in vertical layout mode
* and adds it to the window
*
* This lays out components like so :
*
* | component 1 |
* | component 2 |
* /
2020-10-23 12:39:12 +00:00
box = new Box ( GtkOrientation . VERTICAL , 1 ) ;
2020-10-17 11:54:07 +00:00
/ * *
* Add needed components
*
* Menubar , tabbed pane switcher , statusbar
* /
menuBar = initializeMenuBar ( ) ;
box . add ( menuBar ) ;
2020-10-18 19:41:22 +00:00
toolbar = getToolbar ( ) ;
box . add ( toolbar ) ;
2020-10-23 13:01:26 +00:00
/* Create the welcome box and set it */
welcomeBox = getWelcomeBox ( ) ;
2020-10-23 12:39:12 +00:00
box . add ( welcomeBox ) ;
2020-10-19 12:57:16 +00:00
2020-10-17 13:58:09 +00:00
statusBar = new Statusbar ( ) ;
statusBar . add ( new Label ( "Gustav: Bruh" ) ) ;
2020-10-23 12:20:36 +00:00
// import gtk.IconView;
// IconView j = new IconView();
// j.set
// statusBar.add(d);
2020-10-19 12:57:16 +00:00
2020-10-23 12:39:12 +00:00
2020-10-17 13:58:09 +00:00
box . packEnd ( statusBar , 0 , 0 , 0 ) ;
2020-10-17 11:54:07 +00:00
//notebook.add(createServerTab());
2020-10-17 18:43:20 +00:00
2020-10-17 11:54:07 +00:00
/* Add the Box to main window */
mainWindow . add ( box ) ;
mainWindow . showAll ( ) ;
/* Unlock GTK lock */
tl ( ) ;
writeln ( "unlock gui setup" ) ;
}
2020-10-18 19:41:22 +00:00
private Toolbar getToolbar ( )
{
2020-10-23 12:02:07 +00:00
/* Create a new Toolbar */
2020-10-18 19:41:22 +00:00
Toolbar toolbar = new Toolbar ( ) ;
/* Status selector dropdown */
2020-10-23 12:02:07 +00:00
/* TODO */
2020-10-18 19:41:22 +00:00
2020-10-19 16:22:48 +00:00
/* Set available button */
2020-10-18 19:41:22 +00:00
ToolButton setAvail = new ToolButton ( "" ) ;
setAvail . setLabel ( "available" ) ;
setAvail . setIconName ( "user-available" ) ;
toolbar . add ( setAvail ) ;
2020-10-19 16:22:48 +00:00
/* Set away button */
2020-10-18 19:41:22 +00:00
ToolButton setAway = new ToolButton ( "" ) ;
setAway . setLabel ( "away" ) ;
setAway . setIconName ( "user-away" ) ;
toolbar . add ( setAway ) ;
2020-10-19 16:22:48 +00:00
/* Set busy button */
2020-10-18 19:41:22 +00:00
ToolButton setBusy = new ToolButton ( "" ) ;
setBusy . setLabel ( "busy" ) ;
setBusy . setIconName ( "user-busy" ) ;
toolbar . add ( setBusy ) ;
2020-10-19 16:22:48 +00:00
/* Assign actions */
2020-10-18 19:44:50 +00:00
setAvail . addOnClicked ( & setStatus ) ;
setAway . addOnClicked ( & setStatus ) ;
2020-10-18 19:41:22 +00:00
setBusy . addOnClicked ( & setStatus ) ;
2020-10-19 12:57:16 +00:00
2020-10-23 12:02:07 +00:00
/* 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 ) ;
2020-10-20 06:00:20 +00:00
/* Add a seperator */
2020-10-19 12:57:16 +00:00
toolbar . add ( new SeparatorToolItem ( ) ) ;
2020-10-23 12:02:07 +00:00
2020-10-19 16:22:48 +00:00
/* List channels button */
2020-10-19 16:01:00 +00:00
ToolButton channelListButton = new ToolButton ( "" ) ;
channelListButton . setIconName ( "emblem-documents" ) ;
2020-10-19 12:57:16 +00:00
channelListButton . setTooltipText ( "List channels" ) ;
2020-10-19 14:23:00 +00:00
channelListButton . addOnClicked ( & listChannels ) ;
2020-10-19 12:57:16 +00:00
toolbar . add ( channelListButton ) ;
2020-10-20 10:16:44 +00:00
2020-10-23 12:02:07 +00:00
2020-10-20 10:16:44 +00:00
2020-10-23 12:02:07 +00:00
SearchEntry dd = new SearchEntry ( ) ;
ToolItem j = new ToolItem ( ) ;
j . add ( dd ) ;
toolbar . add ( j ) ;
2020-10-20 10:16:44 +00:00
2020-10-18 19:41:22 +00:00
return toolbar ;
}
2020-10-20 10:16:44 +00:00
import gtk.Entry ;
2020-10-20 12:02:05 +00:00
import std.string ;
2020-10-20 10:16:44 +00:00
private void setStatusMessage ( Entry f )
{
/* Get the current connection */
Connection currentConnection = connections [ notebook . getCurrentPage ( ) ] ;
2020-10-20 12:02:05 +00:00
/* 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 ) ;
}
2020-10-20 10:16:44 +00:00
//f.setInputHints(GtkInputHints.)
2020-10-20 12:02:05 +00:00
/* Defocus the currently focused widget which would always be me if you are hitting enter */
mainWindow . setFocus ( null ) ;
2020-10-20 10:16:44 +00:00
}
2020-10-19 14:14:28 +00:00
private void about ( MenuItem )
2020-10-19 14:09:08 +00:00
{
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" ) ;
2020-10-19 14:11:24 +00:00
about . setArtists ( [ "i wonder if I could commision an artwork from her" ] ) ;
2020-10-19 14:09:08 +00:00
/* 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 ( ) ;
}
2020-10-20 13:36:18 +00:00
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 ( "" ) ;
2020-10-20 17:23:54 +00:00
channelLabel . setHalign ( GtkAlign . START ) ;
2020-10-20 13:36:18 +00:00
channelLabel . setMarkup ( "<b>" ~ channelName ~ "</b>" ) ;
/* Add the member count */
ulong memberCount = currentConnection . getClient ( ) . getMemberCount ( channelName ) ;
Label memberCountLabel = new Label ( "" ) ;
2020-10-20 17:23:54 +00:00
memberCountLabel . setHalign ( GtkAlign . START ) ;
2020-10-20 13:36:18 +00:00
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 ) ;
2020-10-20 17:23:54 +00:00
containerMain . packEnd ( joinButton , 0 , 0 , 0 ) ;
2020-10-20 13:36:18 +00:00
joinButton . addOnClicked ( & selectChannel ) ;
2020-10-23 15:12:56 +00:00
/* 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 ) ) ) ;
2020-10-23 15:10:44 +00:00
2020-10-20 13:36:18 +00:00
return containerMain ;
}
2020-10-19 14:09:08 +00:00
/ * *
* List channels
*
* Brings up a window listing channels of the current server
* /
2020-10-19 14:23:00 +00:00
private void listChannels ( ToolButton )
2020-10-19 14:09:08 +00:00
{
import gtk.Window ;
2020-10-19 14:23:00 +00:00
/* Create the window */
Window win = new Window ( GtkWindowType . TOPLEVEL ) ;
/* Create the list of channels */
ListBox channelsList = new ListBox ( ) ;
2020-10-19 16:01:00 +00:00
win . add ( new ScrolledWindow ( channelsList ) ) ;
2020-10-19 14:23:00 +00:00
/* Get the current connection */
Connection currentConnection = connections [ notebook . getCurrentPage ( ) ] ;
/* Fetch the channels */
string [ ] channels = currentConnection . getClient ( ) . list ( ) ;
/* Add each channel */
foreach ( string channel ; channels )
{
2020-10-20 13:36:18 +00:00
// channelsList.add(new Label(channel));
channelsList . add ( channelItemList ( currentConnection , channel ) ) ;
2020-10-20 16:59:10 +00:00
writeln ( "bruh: " ~ channel ) ;
2020-10-19 14:23:00 +00:00
channelsList . showAll ( ) ;
}
2020-10-19 16:22:48 +00:00
/* TODO: Add handler for clicking label that lets you join the channel */
2020-10-20 13:36:18 +00:00
// channelsList.addOnSelectedRowsChanged(&selectChannel);
2020-10-20 09:34:22 +00:00
//channelsList.add
2020-10-19 16:22:48 +00:00
win . showAll ( ) ;
}
2020-10-20 06:00:20 +00:00
/ * *
* 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 ( ) ;
}
2020-10-20 13:36:18 +00:00
private void selectChannel ( Button s )
2020-10-19 16:22:48 +00:00
{
2020-10-19 16:32:53 +00:00
/* Get the current connection */
Connection currentConnection = connections [ notebook . getCurrentPage ( ) ] ;
/* Get the name of the channel selected */
2020-10-20 13:36:18 +00:00
string channelSelected = ( cast ( JoinButton ) s ) . getChannelName ( ) ; //(cast(Label)(s.getSelectedRow().getChild())).getText();
2020-10-19 16:32:53 +00:00
2020-10-19 17:07:56 +00:00
/* Join the channel on this connection */
currentConnection . joinChannel ( channelSelected ) ;
2020-10-19 14:09:08 +00:00
}
2020-10-23 20:04:19 +00:00
private bool conifgureConnectionsAssistant ( string , Label )
{
setupConnection ( ) ;
return 0 ;
}
private void setupConnection ( )
{
import gtk.Assistant ;
Assistant connectionAssistant = new Assistant ( ) ;
Label hello = new Label ( "" ) ;
hello . setMarkup ( "<span size=\"15000\">Welcome to the connection setup</span>" ) ;
connectionAssistant . insertPage ( hello , 0 ) ;
connectionAssistant . showAll ( ) ;
}
2020-10-19 14:09:08 +00:00
2020-10-18 19:41:22 +00:00
private void setStatus ( ToolButton x )
{
2020-10-23 20:04:19 +00:00
/* If there are any available connections */
if ( connections . length )
{
/* Get the current connection */
Connection currentConnection = connections [ notebook . getCurrentPage ( ) ] ;
/* Set the status */
2020-10-23 20:05:17 +00:00
currentConnection . getClient ( ) . setProperty ( "pres" , x . getLabel ( ) ) ;
2020-10-23 20:04:19 +00:00
}
/* If there are no connections */
else
{
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 ( ) ;
}
2020-10-18 19:41:22 +00:00
}
2020-10-17 11:54:07 +00:00
private MenuBar initializeMenuBar ( )
{
MenuBar menuBar = new MenuBar ( ) ;
/* Gustav menu */
MenuItem gustavMenuItem = new MenuItem ( ) ;
gustavMenuItem . setLabel ( "Gustav" ) ;
Menu gustavMenu = new Menu ( ) ;
gustavMenuItem . setSubmenu ( gustavMenu ) ;
2020-10-17 13:58:09 +00:00
/* Connect option */
MenuItem connectItem = new MenuItem ( ) ;
connectItem . setLabel ( "Connect" ) ;
2020-10-17 17:32:31 +00:00
connectItem . addOnActivate ( & connectButton ) ;
2020-10-17 13:58:09 +00:00
gustavMenu . add ( connectItem ) ;
2020-10-20 06:00:20 +00:00
/* Connect v2 option */
MenuItem connectItem2 = new MenuItem ( ) ;
connectItem2 . setLabel ( "Connect" ) ;
connectItem2 . addOnActivate ( & connect ) ;
gustavMenu . add ( connectItem2 ) ;
2020-10-17 13:58:09 +00:00
/* Exit option */
2020-10-17 11:54:07 +00:00
MenuItem exitItem = new MenuItem ( ) ;
exitItem . setLabel ( "Exit" ) ;
exitItem . addOnActivate ( & exitButton ) ;
gustavMenu . add ( exitItem ) ;
2020-10-19 14:14:28 +00:00
/* 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 ) ;
2020-10-19 14:15:01 +00:00
helpMenu . add ( aboutItem ) ;
2020-10-19 14:14:28 +00:00
2020-10-17 11:54:07 +00:00
2020-10-17 13:58:09 +00:00
2020-10-17 11:54:07 +00:00
/* Add all menues */
menuBar . add ( gustavMenuItem ) ;
2020-10-19 14:14:28 +00:00
menuBar . add ( helpMenuItem ) ;
2020-10-17 11:54:07 +00:00
return menuBar ;
}
private void exitButton ( MenuItem )
{
writeln ( "bruh" ) ;
/* TODO: Implement exit */
// tl();
//te();
shutdownConnections ( ) ;
// mainWindow.showAll();
// tl();
}
2020-10-17 17:32:31 +00:00
private void connectButton ( MenuItem )
{
2020-10-23 13:04:46 +00:00
connectServer ( "0.0.0.0" , 7777 ) ;
}
/ * *
* Connects to the provided server ,
* add the tab as well
2020-10-23 13:05:13 +00:00
*
* NOTE : To be called only by a GTK signal
* handler
2020-10-23 13:04:46 +00:00
* /
private void connectServer ( string address , ushort port )
{
/ * *
* If this is our first connection then
* create a new Notebook which will
* hold the connection / session tabs
* and remove the welcome page
* /
2020-10-23 12:39:12 +00:00
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 */
2020-10-23 20:04:19 +00:00
Connection newConnection = new Connection ( this , parseAddress ( address , port ) , [ "testGustav" ~ to ! ( string ) ( connections . length ) , "bruh" ] ) ;
connections ~ = newConnection ;
// import UserDirectory;
// UserDirectory d = new UserDirectory(newConnection);
2020-10-17 17:32:31 +00:00
}
2020-10-17 11:54:07 +00:00
private void shutdownConnections ( )
{
foreach ( Connection connection ; connections )
{
/ * *
* TODO : This is called by signal handler , we need no mutexes for signal handler
* hence it means that connection
* /
connection . shutdown ( ) ;
Thread . sleep ( dur ! ( "seconds" ) ( 2 ) ) ;
}
}
private void newServer ( )
{
}
private Box createServerTab ( )
{
Box serverTab = new Box ( GtkOrientation . HORIZONTAL , 1 ) ;
serverTab . add ( new Label ( "hello" ) ) ;
// serverTab.add();
return serverTab ;
}
}