2019-10-25 21:09:16 +02:00
# include "CppLexer.h"
2019-11-10 21:45:32 +01:00
# include "CursorTool.h"
2019-10-27 12:55:10 +01:00
# include "Editor.h"
# include "EditorWrapper.h"
2019-10-23 21:13:08 +02:00
# include "FindInFilesWidget.h"
2019-11-08 20:55:58 +01:00
# include "FormEditorWidget.h"
2019-11-10 11:10:04 +01:00
# include "FormWidget.h"
2019-10-28 18:48:53 +01:00
# include "Locator.h"
2019-10-21 18:46:55 +02:00
# include "Project.h"
2019-10-21 20:17:32 +02:00
# include "TerminalWrapper.h"
2019-11-10 22:50:30 +01:00
# include "WidgetTool.h"
2019-10-21 18:46:55 +02:00
# include <LibCore/CFile.h>
2019-10-21 22:13:20 +02:00
# include <LibGUI/GAboutDialog.h>
2019-10-21 19:03:09 +02:00
# include <LibGUI/GAction.h>
2019-11-10 22:50:30 +01:00
# include <LibGUI/GActionGroup.h>
2019-10-21 18:46:55 +02:00
# include <LibGUI/GApplication.h>
# include <LibGUI/GBoxLayout.h>
2019-10-23 21:13:08 +02:00
# include <LibGUI/GButton.h>
2019-10-26 21:43:08 +02:00
# include <LibGUI/GFilePicker.h>
2019-10-21 19:03:09 +02:00
# include <LibGUI/GInputBox.h>
2019-10-27 12:55:10 +01:00
# include <LibGUI/GLabel.h>
2019-10-21 18:46:55 +02:00
# include <LibGUI/GListView.h>
2019-10-21 22:13:20 +02:00
# include <LibGUI/GMenu.h>
# include <LibGUI/GMenuBar.h>
2019-10-21 18:46:55 +02:00
# include <LibGUI/GMessageBox.h>
# include <LibGUI/GSplitter.h>
2019-11-08 20:55:58 +01:00
# include <LibGUI/GStackWidget.h>
2019-10-23 19:52:34 +02:00
# include <LibGUI/GTabWidget.h>
2019-11-08 21:48:58 +01:00
# include <LibGUI/GTableView.h>
2019-10-23 20:54:41 +02:00
# include <LibGUI/GTextBox.h>
2019-10-21 18:46:55 +02:00
# include <LibGUI/GTextEditor.h>
# include <LibGUI/GToolBar.h>
2019-11-08 21:48:58 +01:00
# include <LibGUI/GTreeView.h>
2019-10-21 18:46:55 +02:00
# include <LibGUI/GWidget.h>
# include <LibGUI/GWindow.h>
# include <stdio.h>
# include <unistd.h>
2019-10-27 13:10:37 +01:00
NonnullRefPtrVector < EditorWrapper > g_all_editor_wrappers ;
2019-10-27 12:55:10 +01:00
RefPtr < EditorWrapper > g_current_editor_wrapper ;
2019-10-22 21:38:58 +02:00
String g_currently_open_file ;
2019-10-23 20:54:41 +02:00
OwnPtr < Project > g_project ;
RefPtr < GWindow > g_window ;
RefPtr < GListView > g_project_list_view ;
2019-11-08 20:55:58 +01:00
RefPtr < GStackWidget > g_right_hand_stack ;
2019-11-08 21:19:49 +01:00
RefPtr < GSplitter > g_text_inner_splitter ;
RefPtr < GWidget > g_form_inner_container ;
2019-11-08 20:55:58 +01:00
RefPtr < FormEditorWidget > g_form_editor_widget ;
2019-10-22 21:38:58 +02:00
2019-11-05 20:44:39 +01:00
static RefPtr < GTabWidget > s_action_tab_widget ;
2019-10-27 12:55:10 +01:00
void add_new_editor ( GWidget & parent )
{
2019-11-05 20:44:39 +01:00
auto wrapper = EditorWrapper : : construct ( nullptr ) ;
if ( s_action_tab_widget ) {
parent . insert_child_before ( wrapper , * s_action_tab_widget ) ;
} else {
parent . add_child ( wrapper ) ;
}
2019-10-27 12:55:10 +01:00
g_current_editor_wrapper = wrapper ;
2019-10-27 13:10:37 +01:00
g_all_editor_wrappers . append ( wrapper ) ;
2019-11-05 20:44:39 +01:00
wrapper - > editor ( ) . set_focus ( true ) ;
2019-10-27 12:55:10 +01:00
}
2019-11-08 20:55:58 +01:00
enum class EditMode {
Text ,
Form ,
} ;
void set_edit_mode ( EditMode mode )
{
if ( mode = = EditMode : : Text ) {
2019-11-08 21:19:49 +01:00
g_right_hand_stack - > set_active_widget ( g_text_inner_splitter ) ;
2019-11-08 20:55:58 +01:00
} else if ( mode = = EditMode : : Form ) {
2019-11-08 21:19:49 +01:00
g_right_hand_stack - > set_active_widget ( g_form_inner_container ) ;
2019-11-08 20:55:58 +01:00
}
}
2019-10-27 12:55:10 +01:00
EditorWrapper & current_editor_wrapper ( )
{
ASSERT ( g_current_editor_wrapper ) ;
return * g_current_editor_wrapper ;
}
Editor & current_editor ( )
2019-10-25 10:25:42 +02:00
{
2019-10-27 12:55:10 +01:00
return current_editor_wrapper ( ) . editor ( ) ;
2019-10-25 10:25:42 +02:00
}
2019-10-22 22:15:43 +02:00
static void build ( TerminalWrapper & ) ;
2019-10-22 22:18:46 +02:00
static void run ( TerminalWrapper & ) ;
2019-10-23 21:13:08 +02:00
void open_file ( const String & ) ;
2019-10-22 22:15:43 +02:00
2019-10-21 18:46:55 +02:00
int main ( int argc , char * * argv )
{
GApplication app ( argc , argv ) ;
2019-11-05 21:07:39 +01:00
Function < void ( ) > update_actions ;
2019-10-23 20:54:41 +02:00
g_window = GWindow : : construct ( ) ;
g_window - > set_rect ( 100 , 100 , 800 , 600 ) ;
g_window - > set_title ( " HackStudio " ) ;
2019-10-21 18:46:55 +02:00
auto widget = GWidget : : construct ( ) ;
2019-10-23 20:54:41 +02:00
g_window - > set_main_widget ( widget ) ;
2019-10-21 18:46:55 +02:00
widget - > set_fill_with_background_color ( true ) ;
widget - > set_layout ( make < GBoxLayout > ( Orientation : : Vertical ) ) ;
widget - > layout ( ) - > set_spacing ( 0 ) ;
2019-10-22 21:38:58 +02:00
if ( chdir ( " /home/anon/little " ) < 0 ) {
2019-10-21 18:46:55 +02:00
perror ( " chdir " ) ;
return 1 ;
}
2019-10-23 20:54:41 +02:00
g_project = Project : : load_from_file ( " little.files " ) ;
ASSERT ( g_project ) ;
2019-10-21 18:46:55 +02:00
auto toolbar = GToolBar : : construct ( widget ) ;
2019-10-21 20:17:32 +02:00
auto outer_splitter = GSplitter : : construct ( Orientation : : Horizontal , widget ) ;
2019-10-23 20:54:41 +02:00
g_project_list_view = GListView : : construct ( outer_splitter ) ;
g_project_list_view - > set_model ( g_project - > model ( ) ) ;
g_project_list_view - > set_size_policy ( SizePolicy : : Fixed , SizePolicy : : Fill ) ;
2019-11-07 21:06:31 +01:00
g_project_list_view - > set_preferred_size ( 140 , 0 ) ;
2019-10-21 18:46:55 +02:00
2019-11-08 20:55:58 +01:00
g_right_hand_stack = GStackWidget : : construct ( outer_splitter ) ;
2019-11-08 21:19:49 +01:00
g_form_inner_container = GWidget : : construct ( g_right_hand_stack ) ;
g_form_inner_container - > set_layout ( make < GBoxLayout > ( Orientation : : Horizontal ) ) ;
auto form_widgets_toolbar = GToolBar : : construct ( Orientation : : Vertical , 26 , g_form_inner_container ) ;
form_widgets_toolbar - > set_preferred_size ( 38 , 0 ) ;
2019-11-08 20:55:58 +01:00
2019-11-10 22:50:30 +01:00
GActionGroup tool_actions ;
tool_actions . set_exclusive ( true ) ;
auto cursor_tool_action = GAction : : create ( " Cursor " , GraphicsBitmap : : load_from_file ( " /res/icons/widgets/Cursor.png " ) , [ & ] ( auto & ) {
2019-11-10 21:45:32 +01:00
g_form_editor_widget - > set_tool ( make < CursorTool > ( * g_form_editor_widget ) ) ;
2019-11-10 22:50:30 +01:00
} ) ;
cursor_tool_action - > set_checkable ( true ) ;
cursor_tool_action - > set_checked ( true ) ;
tool_actions . add_action ( cursor_tool_action ) ;
form_widgets_toolbar - > add_action ( cursor_tool_action ) ;
2019-11-10 11:00:55 +01:00
GWidgetClassRegistration : : for_each ( [ & ] ( const GWidgetClassRegistration & reg ) {
auto icon_path = String : : format ( " /res/icons/widgets/%s.png " , reg . class_name ( ) . characters ( ) ) ;
2019-11-10 11:10:04 +01:00
auto action = GAction : : create ( reg . class_name ( ) , GraphicsBitmap : : load_from_file ( icon_path ) , [ & reg ] ( auto & ) {
2019-11-10 21:45:32 +01:00
g_form_editor_widget - > set_tool ( make < WidgetTool > ( * g_form_editor_widget , reg ) ) ;
2019-11-10 11:10:04 +01:00
auto widget = reg . construct ( & g_form_editor_widget - > form_widget ( ) ) ;
widget - > set_relative_rect ( 30 , 30 , 30 , 30 ) ;
2019-11-10 11:00:55 +01:00
} ) ;
2019-11-10 22:50:30 +01:00
action - > set_checkable ( true ) ;
action - > set_checked ( false ) ;
tool_actions . add_action ( action ) ;
2019-11-10 11:00:55 +01:00
form_widgets_toolbar - > add_action ( move ( action ) ) ;
} ) ;
2019-11-08 21:19:49 +01:00
2019-11-08 21:48:58 +01:00
auto form_editor_inner_splitter = GSplitter : : construct ( Orientation : : Horizontal , g_form_inner_container ) ;
g_form_editor_widget = FormEditorWidget : : construct ( form_editor_inner_splitter ) ;
auto form_editing_pane_container = GSplitter : : construct ( Orientation : : Vertical , form_editor_inner_splitter ) ;
form_editing_pane_container - > set_size_policy ( SizePolicy : : Fixed , SizePolicy : : Fill ) ;
form_editing_pane_container - > set_preferred_size ( 170 , 0 ) ;
form_editing_pane_container - > set_layout ( make < GBoxLayout > ( Orientation : : Vertical ) ) ;
auto add_properties_pane = [ & ] ( auto & text , auto pane_widget ) {
auto wrapper = GWidget : : construct ( form_editing_pane_container . ptr ( ) ) ;
wrapper - > set_layout ( make < GBoxLayout > ( Orientation : : Vertical ) ) ;
auto label = GLabel : : construct ( text , wrapper ) ;
label - > set_fill_with_background_color ( true ) ;
label - > set_text_alignment ( TextAlignment : : CenterLeft ) ;
label - > set_font ( Font : : default_bold_font ( ) ) ;
label - > set_size_policy ( SizePolicy : : Fill , SizePolicy : : Fixed ) ;
label - > set_preferred_size ( 0 , 16 ) ;
wrapper - > add_child ( pane_widget ) ;
} ;
add_properties_pane ( " Form widget tree: " , GTreeView : : construct ( nullptr ) ) ;
add_properties_pane ( " Widget properties: " , GTableView : : construct ( nullptr ) ) ;
2019-11-08 21:19:49 +01:00
g_text_inner_splitter = GSplitter : : construct ( Orientation : : Vertical , g_right_hand_stack ) ;
g_text_inner_splitter - > layout ( ) - > set_margins ( { 0 , 3 , 0 , 0 } ) ;
add_new_editor ( * g_text_inner_splitter ) ;
2019-10-23 20:54:41 +02:00
2019-10-26 21:43:08 +02:00
auto new_action = GAction : : create ( " Add new file to project... " , { Mod_Ctrl , Key_N } , GraphicsBitmap : : load_from_file ( " /res/icons/16x16/new.png " ) , [ & ] ( const GAction & ) {
2019-10-26 21:27:57 +02:00
auto input_box = GInputBox : : construct ( " Enter name of new file: " , " Add new file to project " , g_window ) ;
if ( input_box - > exec ( ) = = GInputBox : : ExecCancel )
return ;
auto filename = input_box - > text_value ( ) ;
auto file = CFile : : construct ( filename ) ;
if ( ! file - > open ( ( CIODevice : : OpenMode ) ( CIODevice : : WriteOnly | CIODevice : : MustBeNew ) ) ) {
GMessageBox : : show ( String : : format ( " Failed to create '%s' " , filename . characters ( ) ) , " Error " , GMessageBox : : Type : : Error , GMessageBox : : InputType : : OK , g_window ) ;
return ;
}
if ( ! g_project - > add_file ( filename ) ) {
GMessageBox : : show ( String : : format ( " Failed to add '%s' to project " , filename . characters ( ) ) , " Error " , GMessageBox : : Type : : Error , GMessageBox : : InputType : : OK , g_window ) ;
// FIXME: Should we unlink the file here maybe?
return ;
}
open_file ( filename ) ;
2019-10-24 22:25:26 +02:00
} ) ;
2019-10-26 21:43:08 +02:00
auto add_existing_file_action = GAction : : create ( " Add existing file to project... " , GraphicsBitmap : : load_from_file ( " /res/icons/16x16/open.png " ) , [ & ] ( auto & ) {
auto result = GFilePicker : : get_open_filepath ( " Add existing file to project " ) ;
if ( ! result . has_value ( ) )
return ;
auto & filename = result . value ( ) ;
if ( ! g_project - > add_file ( filename ) ) {
GMessageBox : : show ( String : : format ( " Failed to add '%s' to project " , filename . characters ( ) ) , " Error " , GMessageBox : : Type : : Error , GMessageBox : : InputType : : OK , g_window ) ;
return ;
}
open_file ( filename ) ;
2019-10-24 22:25:26 +02:00
} ) ;
2019-10-27 13:10:37 +01:00
auto switch_to_next_editor = GAction : : create ( " Switch to next editor " , { Mod_Ctrl , Key_E } , [ & ] ( auto & ) {
if ( g_all_editor_wrappers . size ( ) < = 1 )
return ;
2019-11-05 20:55:50 +01:00
Vector < EditorWrapper * > wrappers ;
2019-11-08 21:19:49 +01:00
g_text_inner_splitter - > for_each_child_of_type < EditorWrapper > ( [ & ] ( auto & child ) {
2019-11-05 20:55:50 +01:00
wrappers . append ( & child ) ;
return IterationDecision : : Continue ;
} ) ;
for ( int i = 0 ; i < wrappers . size ( ) ; + + i ) {
if ( g_current_editor_wrapper . ptr ( ) = = wrappers [ i ] ) {
if ( i = = wrappers . size ( ) - 1 )
wrappers [ 0 ] - > editor ( ) . set_focus ( true ) ;
else
wrappers [ i + 1 ] - > editor ( ) . set_focus ( true ) ;
}
}
} ) ;
auto switch_to_previous_editor = GAction : : create ( " Switch to previous editor " , { Mod_Ctrl | Mod_Shift , Key_E } , [ & ] ( auto & ) {
if ( g_all_editor_wrappers . size ( ) < = 1 )
2019-10-27 13:10:37 +01:00
return ;
2019-11-05 20:55:50 +01:00
Vector < EditorWrapper * > wrappers ;
2019-11-08 21:19:49 +01:00
g_text_inner_splitter - > for_each_child_of_type < EditorWrapper > ( [ & ] ( auto & child ) {
2019-11-05 20:55:50 +01:00
wrappers . append ( & child ) ;
return IterationDecision : : Continue ;
} ) ;
for ( int i = wrappers . size ( ) - 1 ; i > = 0 ; - - i ) {
if ( g_current_editor_wrapper . ptr ( ) = = wrappers [ i ] ) {
if ( i = = 0 )
wrappers . last ( ) - > editor ( ) . set_focus ( true ) ;
else
wrappers [ i - 1 ] - > editor ( ) . set_focus ( true ) ;
}
2019-10-27 13:10:37 +01:00
}
} ) ;
2019-11-05 21:07:39 +01:00
auto remove_current_editor_action = GAction : : create ( " Remove current editor " , { Mod_Alt | Mod_Shift , Key_E } , [ & ] ( auto & ) {
2019-11-05 21:02:31 +01:00
if ( g_all_editor_wrappers . size ( ) < = 1 )
return ;
auto wrapper = g_current_editor_wrapper ;
switch_to_next_editor - > activate ( ) ;
2019-11-08 21:19:49 +01:00
g_text_inner_splitter - > remove_child ( * wrapper ) ;
2019-11-05 21:02:31 +01:00
g_all_editor_wrappers . remove_first_matching ( [ & ] ( auto & entry ) { return entry = = wrapper . ptr ( ) ; } ) ;
2019-11-05 21:07:39 +01:00
update_actions ( ) ;
2019-11-05 21:02:31 +01:00
} ) ;
2019-10-24 22:25:26 +02:00
auto save_action = GAction : : create ( " Save " , { Mod_Ctrl , Key_S } , GraphicsBitmap : : load_from_file ( " /res/icons/16x16/save.png " ) , [ & ] ( auto & ) {
if ( g_currently_open_file . is_empty ( ) )
return ;
2019-10-27 12:55:10 +01:00
current_editor ( ) . write_to_file ( g_currently_open_file ) ;
2019-10-24 22:25:26 +02:00
} ) ;
toolbar - > add_action ( new_action ) ;
2019-10-26 21:43:08 +02:00
toolbar - > add_action ( add_existing_file_action ) ;
2019-10-24 22:25:26 +02:00
toolbar - > add_action ( save_action ) ;
toolbar - > add_separator ( ) ;
2019-10-27 12:55:10 +01:00
toolbar - > add_action ( GCommonActions : : make_cut_action ( [ & ] ( auto & ) { current_editor ( ) . cut_action ( ) . activate ( ) ; } ) ) ;
toolbar - > add_action ( GCommonActions : : make_copy_action ( [ & ] ( auto & ) { current_editor ( ) . copy_action ( ) . activate ( ) ; } ) ) ;
toolbar - > add_action ( GCommonActions : : make_paste_action ( [ & ] ( auto & ) { current_editor ( ) . paste_action ( ) . activate ( ) ; } ) ) ;
2019-10-24 22:25:26 +02:00
toolbar - > add_separator ( ) ;
2019-10-27 12:55:10 +01:00
toolbar - > add_action ( GCommonActions : : make_undo_action ( [ & ] ( auto & ) { current_editor ( ) . undo_action ( ) . activate ( ) ; } ) ) ;
toolbar - > add_action ( GCommonActions : : make_redo_action ( [ & ] ( auto & ) { current_editor ( ) . redo_action ( ) . activate ( ) ; } ) ) ;
2019-10-24 22:25:26 +02:00
toolbar - > add_separator ( ) ;
2019-10-23 20:54:41 +02:00
g_project_list_view - > on_activation = [ & ] ( auto & index ) {
auto filename = g_project_list_view - > model ( ) - > data ( index ) . to_string ( ) ;
open_file ( filename ) ;
2019-10-21 18:46:55 +02:00
} ;
2019-11-08 21:19:49 +01:00
s_action_tab_widget = GTabWidget : : construct ( g_text_inner_splitter ) ;
2019-10-23 19:52:34 +02:00
2019-11-05 20:44:39 +01:00
s_action_tab_widget - > set_size_policy ( SizePolicy : : Fill , SizePolicy : : Fixed ) ;
s_action_tab_widget - > set_preferred_size ( 0 , 24 ) ;
2019-10-26 12:30:49 +02:00
auto reveal_action_tab = [ & ] ( auto & widget ) {
2019-11-05 20:44:39 +01:00
if ( s_action_tab_widget - > preferred_size ( ) . height ( ) < 200 )
s_action_tab_widget - > set_preferred_size ( 0 , 200 ) ;
s_action_tab_widget - > set_active_widget ( widget ) ;
2019-10-26 12:30:49 +02:00
} ;
auto hide_action_tabs = [ & ] {
2019-11-05 20:44:39 +01:00
s_action_tab_widget - > set_preferred_size ( 0 , 24 ) ;
2019-10-26 12:30:49 +02:00
} ;
auto hide_action_tabs_action = GAction : : create ( " Hide action tabs " , { Mod_Ctrl | Mod_Shift , Key_X } , [ & ] ( auto & ) {
hide_action_tabs ( ) ;
} ) ;
2019-11-05 20:44:39 +01:00
auto add_editor_action = GAction : : create ( " Add new editor " , { Mod_Ctrl | Mod_Alt , Key_E } , [ & ] ( auto & ) {
2019-11-08 21:19:49 +01:00
add_new_editor ( * g_text_inner_splitter ) ;
2019-11-05 21:07:39 +01:00
update_actions ( ) ;
2019-11-05 20:44:39 +01:00
} ) ;
2019-10-23 21:13:08 +02:00
auto find_in_files_widget = FindInFilesWidget : : construct ( nullptr ) ;
2019-11-05 20:44:39 +01:00
s_action_tab_widget - > add_widget ( " Find in files " , find_in_files_widget ) ;
2019-10-23 20:54:41 +02:00
2019-10-23 19:52:34 +02:00
auto terminal_wrapper = TerminalWrapper : : construct ( nullptr ) ;
2019-11-05 20:44:39 +01:00
s_action_tab_widget - > add_widget ( " Console " , terminal_wrapper ) ;
2019-10-21 20:17:32 +02:00
2019-10-28 18:48:53 +01:00
auto locator = Locator : : construct ( widget ) ;
auto open_locator_action = GAction : : create ( " Open Locator... " , { Mod_Ctrl , Key_K } , [ & ] ( auto & ) {
locator - > open ( ) ;
} ) ;
2019-10-21 22:13:20 +02:00
auto menubar = make < GMenuBar > ( ) ;
auto app_menu = make < GMenu > ( " HackStudio " ) ;
2019-10-24 22:25:26 +02:00
app_menu - > add_action ( save_action ) ;
2019-10-21 22:13:20 +02:00
app_menu - > add_action ( GCommonActions : : make_quit_action ( [ & ] ( auto & ) {
app . quit ( ) ;
} ) ) ;
menubar - > add_menu ( move ( app_menu ) ) ;
2019-10-26 21:43:08 +02:00
auto project_menu = make < GMenu > ( " Project " ) ;
project_menu - > add_action ( new_action ) ;
project_menu - > add_action ( add_existing_file_action ) ;
menubar - > add_menu ( move ( project_menu ) ) ;
2019-10-23 21:02:02 +02:00
auto edit_menu = make < GMenu > ( " Edit " ) ;
edit_menu - > add_action ( GAction : : create ( " Find in files... " , { Mod_Ctrl | Mod_Shift , Key_F } , [ & ] ( auto & ) {
2019-10-26 12:30:49 +02:00
reveal_action_tab ( find_in_files_widget ) ;
2019-10-23 21:13:08 +02:00
find_in_files_widget - > focus_textbox_and_select_all ( ) ;
2019-10-23 21:02:02 +02:00
} ) ) ;
menubar - > add_menu ( move ( edit_menu ) ) ;
2019-10-24 22:25:26 +02:00
auto build_action = GAction : : create ( " Build " , { Mod_Ctrl , Key_B } , GraphicsBitmap : : load_from_file ( " /res/icons/16x16/build.png " ) , [ & ] ( auto & ) {
2019-10-26 12:30:49 +02:00
reveal_action_tab ( terminal_wrapper ) ;
2019-10-22 22:15:43 +02:00
build ( terminal_wrapper ) ;
2019-10-24 22:25:26 +02:00
} ) ;
toolbar - > add_action ( build_action ) ;
auto run_action = GAction : : create ( " Run " , { Mod_Ctrl , Key_R } , GraphicsBitmap : : load_from_file ( " /res/icons/16x16/run.png " ) , [ & ] ( auto & ) {
2019-10-26 12:30:49 +02:00
reveal_action_tab ( terminal_wrapper ) ;
2019-10-22 22:18:46 +02:00
run ( terminal_wrapper ) ;
2019-10-24 22:25:26 +02:00
} ) ;
toolbar - > add_action ( run_action ) ;
auto build_menu = make < GMenu > ( " Build " ) ;
build_menu - > add_action ( build_action ) ;
build_menu - > add_action ( run_action ) ;
2019-10-22 22:15:43 +02:00
menubar - > add_menu ( move ( build_menu ) ) ;
2019-10-26 12:30:49 +02:00
auto view_menu = make < GMenu > ( " View " ) ;
view_menu - > add_action ( hide_action_tabs_action ) ;
2019-10-28 18:48:53 +01:00
view_menu - > add_action ( open_locator_action ) ;
2019-11-05 21:02:31 +01:00
view_menu - > add_separator ( ) ;
2019-11-05 20:44:39 +01:00
view_menu - > add_action ( add_editor_action ) ;
2019-11-05 21:07:39 +01:00
view_menu - > add_action ( remove_current_editor_action ) ;
2019-10-26 12:30:49 +02:00
menubar - > add_menu ( move ( view_menu ) ) ;
2019-10-21 22:13:20 +02:00
auto small_icon = GraphicsBitmap : : load_from_file ( " /res/icons/16x16/app-hack-studio.png " ) ;
auto help_menu = make < GMenu > ( " Help " ) ;
help_menu - > add_action ( GAction : : create ( " About " , [ & ] ( auto & ) {
2019-10-23 20:54:41 +02:00
GAboutDialog : : show ( " HackStudio " , small_icon , g_window ) ;
2019-10-21 22:13:20 +02:00
} ) ) ;
menubar - > add_menu ( move ( help_menu ) ) ;
app . set_menubar ( move ( menubar ) ) ;
2019-10-23 20:54:41 +02:00
g_window - > set_icon ( small_icon ) ;
2019-10-21 19:03:09 +02:00
2019-10-23 20:54:41 +02:00
g_window - > show ( ) ;
2019-10-26 10:32:12 +02:00
2019-11-05 21:07:39 +01:00
update_actions = [ & ] ( ) {
remove_current_editor_action - > set_enabled ( g_all_editor_wrappers . size ( ) > 1 ) ;
} ;
2019-11-08 21:19:49 +01:00
open_file ( " test.frm " ) ;
2019-11-05 21:07:39 +01:00
update_actions ( ) ;
2019-10-21 18:46:55 +02:00
return app . exec ( ) ;
}
2019-10-22 22:15:43 +02:00
void build ( TerminalWrapper & wrapper )
{
wrapper . run_command ( " make " ) ;
}
2019-10-22 22:18:46 +02:00
void run ( TerminalWrapper & wrapper )
{
wrapper . run_command ( " make run " ) ;
}
2019-10-23 20:54:41 +02:00
2019-10-26 00:18:35 +02:00
struct TextStyle {
Color color ;
const Font * font { nullptr } ;
} ;
static TextStyle style_for_token_type ( CppToken : : Type type )
2019-10-25 21:09:16 +02:00
{
switch ( type ) {
case CppToken : : Type : : Keyword :
2019-10-26 00:18:35 +02:00
return { Color : : Black , & Font : : default_bold_fixed_width_font ( ) } ;
2019-10-26 10:32:12 +02:00
case CppToken : : Type : : KnownType :
return { Color : : from_rgb ( 0x929200 ) , & Font : : default_bold_fixed_width_font ( ) } ;
2019-10-25 21:09:16 +02:00
case CppToken : : Type : : Identifier :
2019-10-26 21:47:51 +02:00
return { Color : : from_rgb ( 0x000092 ) } ;
2019-10-25 21:09:16 +02:00
case CppToken : : Type : : DoubleQuotedString :
case CppToken : : Type : : SingleQuotedString :
case CppToken : : Type : : Number :
2019-10-26 10:32:12 +02:00
return { Color : : from_rgb ( 0x920000 ) } ;
2019-10-25 21:09:16 +02:00
case CppToken : : Type : : PreprocessorStatement :
2019-10-26 10:32:12 +02:00
return { Color : : from_rgb ( 0x009292 ) } ;
2019-10-25 21:09:16 +02:00
case CppToken : : Type : : Comment :
2019-10-26 10:32:12 +02:00
return { Color : : from_rgb ( 0x009200 ) } ;
2019-10-25 21:09:16 +02:00
default :
2019-10-26 00:18:35 +02:00
return { Color : : Black } ;
2019-10-25 21:09:16 +02:00
}
}
2019-10-26 10:32:12 +02:00
static void rehighlight ( )
{
2019-10-27 12:55:10 +01:00
auto text = current_editor ( ) . text ( ) ;
2019-10-26 10:32:12 +02:00
CppLexer lexer ( text ) ;
auto tokens = lexer . lex ( ) ;
2019-10-27 16:10:07 +01:00
Vector < GTextDocumentSpan > spans ;
2019-10-26 10:32:12 +02:00
for ( auto & token : tokens ) {
# ifdef DEBUG_SYNTAX_HIGHLIGHTING
dbg ( ) < < token . to_string ( ) < < " @ " < < token . m_start . line < < " : " < < token . m_start . column < < " - " < < token . m_end . line < < " : " < < token . m_end . column ;
# endif
2019-10-27 16:10:07 +01:00
GTextDocumentSpan span ;
2019-10-26 15:32:12 +02:00
span . range . set_start ( { token . m_start . line , token . m_start . column } ) ;
span . range . set_end ( { token . m_end . line , token . m_end . column } ) ;
2019-10-26 10:32:12 +02:00
auto style = style_for_token_type ( token . m_type ) ;
span . color = style . color ;
span . font = style . font ;
spans . append ( span ) ;
}
2019-10-27 16:10:07 +01:00
current_editor ( ) . document ( ) . set_spans ( spans ) ;
2019-10-27 12:55:10 +01:00
current_editor ( ) . update ( ) ;
2019-10-26 10:32:12 +02:00
}
2019-10-23 20:54:41 +02:00
void open_file ( const String & filename )
{
2019-10-27 19:39:15 +01:00
auto file = g_project - > get_file ( filename ) ;
current_editor ( ) . set_document ( const_cast < GTextDocument & > ( file - > document ( ) ) ) ;
2019-10-25 21:09:16 +02:00
2019-10-28 17:44:53 +01:00
if ( filename . ends_with ( " .cpp " ) | | filename . ends_with ( " .h " ) ) {
2019-10-27 12:55:10 +01:00
current_editor ( ) . on_change = [ ] { rehighlight ( ) ; } ;
2019-10-26 10:32:12 +02:00
rehighlight ( ) ;
} else {
2019-10-27 12:55:10 +01:00
current_editor ( ) . on_change = nullptr ;
2019-10-25 21:09:16 +02:00
}
2019-10-26 10:32:12 +02:00
2019-11-08 20:55:58 +01:00
if ( filename . ends_with ( " .frm " ) ) {
set_edit_mode ( EditMode : : Form ) ;
} else {
set_edit_mode ( EditMode : : Text ) ;
}
2019-10-26 10:32:12 +02:00
g_currently_open_file = filename ;
g_window - > set_title ( String : : format ( " %s - HackStudio " , g_currently_open_file . characters ( ) ) ) ;
g_project_list_view - > update ( ) ;
2019-10-26 21:45:29 +02:00
2019-10-27 12:55:10 +01:00
current_editor_wrapper ( ) . filename_label ( ) . set_text ( filename ) ;
current_editor ( ) . set_focus ( true ) ;
2019-10-23 20:54:41 +02:00
}