diff --git a/Gtkmm3_Mac/CMakeLists.txt b/Gtkmm3_Mac/CMakeLists.txt
index 9efa845..7d588fb 100644
--- a/Gtkmm3_Mac/CMakeLists.txt
+++ b/Gtkmm3_Mac/CMakeLists.txt
@@ -43,6 +43,7 @@ set(RESOURCE_LIST
STRIPBLANKS game1.ui
STRIPBLANKS game24.ui
STRIPBLANKS calcapp.ui
+ STRIPBLANKS text_menu.xml
style.css
reset.css
dock_style.css
diff --git a/Gtkmm3_Mac/res/text_menu.xml b/Gtkmm3_Mac/res/text_menu.xml
new file mode 100644
index 0000000..ae02db2
--- /dev/null
+++ b/Gtkmm3_Mac/res/text_menu.xml
@@ -0,0 +1,40 @@
+
+
+
+
\ No newline at end of file
diff --git a/Gtkmm3_Mac/src/apps/TextEditor.hh b/Gtkmm3_Mac/src/apps/TextEditor.hh
index e00604f..0542277 100644
--- a/Gtkmm3_Mac/src/apps/TextEditor.hh
+++ b/Gtkmm3_Mac/src/apps/TextEditor.hh
@@ -2,29 +2,57 @@
#include
-class TextEditor : public Gtk::Window{
+class TextEditor : public Gtk::ApplicationWindow{
public:
TextEditor();
private:
- //Child widgets
- Gtk::Box vbox,hbox,btnbox,*infobox;
+ //Header widgets
+ Gtk::HeaderBar header;
+ Gtk::MenuButton menubtn;
+ Gtk::Popover popover;
+ Gtk::ToggleButton search_button;
+ Glib::RefPtr menu_builder;
+
+ //SearchBar
+ Gtk::SearchBar searchbar;
+ Gtk::SearchEntry search_entry;
+ Gtk::Box searchbox;
+ Gtk::Button search_up, search_down;
+ Glib::RefPtr search_binding;
+ Gtk::TextIter curr_iter_up, curr_iter_down;
+
+ //Window widgets
+ Gtk::Box vbox,hbox,*infobox;
Gtk::ScrolledWindow sw1,sw2;
Glib::RefPtr buffer1;
Gtk::TextView textview1;
- Gtk::Button btn_copy,btn_paste,btn_open,btn_save,btn_clear;
Gtk::InfoBar infobar;
Gtk::Label label1;
+
//File Dialog
Glib::RefPtr dialog;
+ Glib::ustring curr_filename;
+ bool file_opened;
+
//Signal Handlers
+
+ // File Operation functions
void btnopen_clicked();
void opendialog_response(int response);
void btnsave_clicked();
+ void btnsaveas_clicked();
void savedialog_response(int response);
+
+ // Copy, Paste and text operations
void btncopy_clicked();
void btnpaste_clicked();
- void btnclear_clicked();
+ void btnclose_clicked();
void buffer1_changed();
void clipboard_receive(const Glib::ustring &text);
void infobar_response(int response);
+
+ // Search funtion
+ void search_entry_changed();
+ void search_forward();
+ void search_backward();
};
diff --git a/Gtkmm3_Mac/src/text_app/TextEditor.cc b/Gtkmm3_Mac/src/text_app/TextEditor.cc
index a58ba71..89e2a22 100644
--- a/Gtkmm3_Mac/src/text_app/TextEditor.cc
+++ b/Gtkmm3_Mac/src/text_app/TextEditor.cc
@@ -2,81 +2,112 @@
#include "text_types.hh"
#include
+// Only for build in this repository
+// #define text_globs supported_globs
+
TextEditor::TextEditor()
-:vbox(Gtk::ORIENTATION_VERTICAL,5),
-hbox(Gtk::ORIENTATION_HORIZONTAL,5),
-btnbox(Gtk::ORIENTATION_VERTICAL,5),
-btn_copy("Copy"),
-btn_paste("Paste"),
-btn_open("Open"),
-btn_save("Save"),
-btn_clear("Clear")
+ : vbox(Gtk::ORIENTATION_VERTICAL, 5),
+ hbox(Gtk::ORIENTATION_HORIZONTAL, 5),
+ searchbox(Gtk::ORIENTATION_HORIZONTAL, 5),
+ file_opened(false)
{
- //Initalize Window
- set_default_size(800,450);
+ // Initalize Window
+ set_default_size(800, 450);
set_icon_name("my_textedit");
- set_title("Simple Text Editor");
-
- //Initalize Text Buffers
- buffer1=textview1.get_buffer();
- buffer1->signal_changed().connect(sigc::mem_fun(*this,&TextEditor::buffer1_changed));
- //Pack Widgets
- sw1.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC);
+ // Initalize HeaderBar
+ header.set_decoration_layout("close,minimize,maximize:menu");
+ header.set_show_close_button();
+ menubtn.set_image_from_icon_name("open-menu");
+ search_button.set_image_from_icon_name("find");
+ header.pack_end(menubtn);
+ header.pack_end(search_button);
+ header.set_title("Simple Text Editor");
+ set_titlebar(header);
+
+ // Add a menu
+ menu_builder = Gtk::Builder::create_from_resource("/org/gtk/daleclack/text_menu.xml");
+ auto object = menu_builder->get_object("text_menu");
+ auto gmenu = Glib::RefPtr::cast_dynamic(object);
+ popover.bind_model(gmenu);
+ menubtn.set_popover(popover);
+
+ // Initalize Text Buffers
+ buffer1 = textview1.get_buffer();
+ buffer1->signal_changed().connect(sigc::mem_fun(*this, &TextEditor::buffer1_changed));
+
+ // Pack Widgets
+ sw1.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
sw1.add(textview1);
- btnbox.set_valign(Gtk::ALIGN_CENTER);
- btnbox.pack_start(btn_copy,Gtk::PACK_SHRINK);
- btnbox.pack_start(btn_paste,Gtk::PACK_SHRINK);
- btnbox.pack_start(btn_open,Gtk::PACK_SHRINK);
- btnbox.pack_start(btn_save,Gtk::PACK_SHRINK);
- btnbox.pack_start(btn_clear,Gtk::PACK_SHRINK);
hbox.pack_start(sw1);
- hbox.pack_start(btnbox,Gtk::PACK_SHRINK);
-
- btn_open.signal_clicked().connect(sigc::mem_fun(*this,&TextEditor::btnopen_clicked));
- btn_save.signal_clicked().connect(sigc::mem_fun(*this,&TextEditor::btnsave_clicked));
- btn_copy.signal_clicked().connect(sigc::mem_fun(*this,&TextEditor::btncopy_clicked));
- btn_paste.signal_clicked().connect(sigc::mem_fun(*this,&TextEditor::btnpaste_clicked));
- btn_clear.signal_clicked().connect(sigc::mem_fun(*this,&TextEditor::btnclear_clicked));
- //A InfoBar
- infobar.add_button("OK",Gtk::RESPONSE_OK);
- infobar.signal_response().connect(sigc::mem_fun(*this,&TextEditor::infobar_response));
- infobox=dynamic_cast(infobar.get_content_area());
+ // Add actions and signal handlers
+ add_action("text_open", sigc::mem_fun(*this, &TextEditor::btnopen_clicked));
+ add_action("text_save", sigc::mem_fun(*this, &TextEditor::btnsave_clicked));
+ add_action("text_saveas", sigc::mem_fun(*this, &TextEditor::btnsaveas_clicked));
+ add_action("text_copy", sigc::mem_fun(*this, &TextEditor::btncopy_clicked));
+ add_action("text_paste", sigc::mem_fun(*this, &TextEditor::btnpaste_clicked));
+ add_action("text_close", sigc::mem_fun(*this, &TextEditor::btnclose_clicked));
+
+ // Add searchbar and search up and down buttons
+ search_up.set_image_from_icon_name("up");
+ search_down.set_image_from_icon_name("down");
+
+ // Bind property and signals
+ search_binding = Glib::Binding::bind_property(search_button.property_active(),
+ searchbar.property_search_mode_enabled(),
+ Glib::BINDING_BIDIRECTIONAL);
+ search_entry.signal_changed().connect(sigc::mem_fun(*this, &TextEditor::search_entry_changed));
+ search_up.signal_clicked().connect(sigc::mem_fun(*this, &TextEditor::search_backward));
+ search_down.signal_clicked().connect(sigc::mem_fun(*this, &TextEditor::search_forward));
+
+ // Pack widgets
+ searchbox.pack_start(search_entry, Gtk::PACK_SHRINK);
+ searchbox.pack_start(search_up, Gtk::PACK_SHRINK);
+ searchbox.pack_start(search_down, Gtk::PACK_SHRINK);
+ searchbar.add(searchbox);
+ vbox.pack_start(searchbar, Gtk::PACK_SHRINK);
+
+ // A InfoBar
+ infobar.add_button("OK", Gtk::RESPONSE_OK);
+ infobar.signal_response().connect(sigc::mem_fun(*this, &TextEditor::infobar_response));
+ infobox = dynamic_cast(infobar.get_content_area());
infobox->pack_start(label1);
- vbox.pack_start(infobar,Gtk::PACK_SHRINK);
+ vbox.pack_start(infobar, Gtk::PACK_SHRINK);
- //Disable Copy button
- btn_copy.set_sensitive(false);
-
- //Show everything
+ // Show everything
vbox.pack_start(hbox);
add(vbox);
show_all_children();
infobar.hide();
}
-void TextEditor::btnopen_clicked(){
- //Create a dialog
- dialog=Gtk::FileChooserNative::create("Open a text file",*this,
- Gtk::FILE_CHOOSER_ACTION_OPEN,"OK","Cancel");
-
- dialog->signal_response().connect(sigc::mem_fun(*this,&TextEditor::opendialog_response));
+void TextEditor::btnopen_clicked()
+{
+ // Create a dialog
+ dialog = Gtk::FileChooserNative::create("Open a text file", *this,
+ Gtk::FILE_CHOOSER_ACTION_OPEN, "OK", "Cancel");
- //Add Filters
- auto filter=Gtk::FileFilter::create();
+ dialog->signal_response().connect(sigc::mem_fun(*this, &TextEditor::opendialog_response));
+
+ // Add Filters
+ auto filter = Gtk::FileFilter::create();
filter->set_name("Text Files");
- if(mimetype_supported()){
+ if (mimetype_supported())
+ {
filter->add_mime_type("text/*");
- }else{
- for(int i = 0; text_globs != NULL && text_globs[i] != NULL; i++){
+ }
+ else
+ {
+ for (int i = 0; text_globs != NULL && text_globs[i] != NULL; i++)
+ {
const char *glob = text_globs[i];
filter->add_pattern(glob);
}
}
dialog->add_filter(filter);
- auto filter_any=Gtk::FileFilter::create();
+ auto filter_any = Gtk::FileFilter::create();
filter_any->set_name("Any Files");
filter_any->add_pattern("*");
dialog->add_filter(filter_any);
@@ -84,40 +115,67 @@ void TextEditor::btnopen_clicked(){
dialog->show();
}
-void TextEditor::opendialog_response(int response){
- if(response==Gtk::RESPONSE_ACCEPT){
- //Load Contents of a file
- auto file=dialog->get_file();
- char * contents;
+void TextEditor::opendialog_response(int response)
+{
+ if (response == Gtk::RESPONSE_ACCEPT)
+ {
+ // Load Contents of a file
+ auto file = dialog->get_file();
+ curr_filename = file->get_path();
+ file_opened = true;
+ char *contents;
gsize length;
- if(file->load_contents(contents,length)){
+ if (file->load_contents(contents, length))
+ {
buffer1->set_text(contents);
}
}
dialog.reset();
}
-void TextEditor::btnsave_clicked(){
- //Create a dialog
- dialog=Gtk::FileChooserNative::create("Save file",*this,
- Gtk::FILE_CHOOSER_ACTION_SAVE,"OK","Cancel");
-
- dialog->signal_response().connect(sigc::mem_fun(*this,&TextEditor::savedialog_response));
+void TextEditor::btnsave_clicked()
+{
+ if (file_opened)
+ {
+ // Get Text
+ Glib::ustring text;
+ text = buffer1->get_text();
+ // Set file opened to true to use save mode
+ file_opened = true;
+ // Save to a file
+ std::ofstream outfile;
+ outfile.open(curr_filename, std::ios_base::out);
+ outfile << text;
+ outfile.close();
+ }
+}
- //Add Filters
- auto filter=Gtk::FileFilter::create();
+void TextEditor::btnsaveas_clicked()
+{
+ // Create a dialog
+ dialog = Gtk::FileChooserNative::create("Save file", *this,
+ Gtk::FILE_CHOOSER_ACTION_SAVE, "OK", "Cancel");
+
+ dialog->signal_response().connect(sigc::mem_fun(*this, &TextEditor::savedialog_response));
+
+ // Add Filters
+ auto filter = Gtk::FileFilter::create();
filter->set_name("Text Files");
- if(mimetype_supported()){
+ if (mimetype_supported())
+ {
filter->add_mime_type("text/*");
- }else{
- for(int i = 0; text_globs != NULL && text_globs[i] != NULL; i++){
+ }
+ else
+ {
+ for (int i = 0; text_globs != NULL && text_globs[i] != NULL; i++)
+ {
const char *glob = text_globs[i];
filter->add_pattern(glob);
}
}
dialog->add_filter(filter);
- auto filter_any=Gtk::FileFilter::create();
+ auto filter_any = Gtk::FileFilter::create();
filter_any->set_name("Any Files");
filter_any->add_pattern("*");
dialog->add_filter(filter_any);
@@ -125,69 +183,131 @@ void TextEditor::btnsave_clicked(){
dialog->show();
}
-void TextEditor::savedialog_response(int response){
- if(response==Gtk::RESPONSE_ACCEPT){
- //Get Filename
- auto file=dialog->get_file();
- std::string filename=file->get_path();
- //Get Text
+void TextEditor::savedialog_response(int response)
+{
+ if (response == Gtk::RESPONSE_ACCEPT)
+ {
+ // Get Filename
+ auto file = dialog->get_file();
+ std::string filename = file->get_path();
+ // Get Text
Glib::ustring text;
- text=buffer1->get_text();
- //Save to a file
+ text = buffer1->get_text();
+ // Save to a file
std::ofstream outfile;
- outfile.open(filename,std::ios_base::out);
- outfile<begin().forward_search(text, Gtk::TEXT_SEARCH_CASE_INSENSITIVE, start, end))
+ {
+ curr_iter_up = start;
+ curr_iter_down = end;
+ buffer1->select_range(start, end);
+ textview1.scroll_to(start);
+ }
+}
+
+void TextEditor::search_forward()
+{
+ // Get Text to search
+ const Glib::ustring search_text = search_entry.get_text();
+
+ Gtk::TextIter start, end;
+ // Get Text to search, down to the end of text
+ if (curr_iter_down.forward_search(search_text, Gtk::TEXT_SEARCH_CASE_INSENSITIVE, start, end))
+ {
+ curr_iter_up = start;
+ curr_iter_down = end;
+ buffer1->select_range(start, end);
+ textview1.scroll_to(start);
+ }
+}
+
+void TextEditor::search_backward()
+{
+ // Get Text to search, up to the start of text
+ const Glib::ustring search_text = search_entry.get_text();
+
+ Gtk::TextIter start, end;
+ // Get Text to search
+ if (curr_iter_up.backward_search(search_text, Gtk::TEXT_SEARCH_CASE_INSENSITIVE, start, end))
+ {
+ curr_iter_up = start;
+ curr_iter_down = end;
+ buffer1->select_range(start, end);
+ textview1.scroll_to(start);
+ }
+}
+
+void TextEditor::btncopy_clicked()
+{
+ // Get Text
Glib::ustring text;
- Gtk::TextBuffer::iterator start,end;
- if(buffer1->get_selection_bounds(start,end)){
- text=buffer1->get_text(start,end);
- }else{
- text=buffer1->get_text();
+ Gtk::TextBuffer::iterator start, end;
+ if (buffer1->get_selection_bounds(start, end))
+ {
+ text = buffer1->get_text(start, end);
+ }
+ else
+ {
+ text = buffer1->get_text();
}
- //Get Clipboard and set text
- auto refClipboard=Gtk::Clipboard::get();
+ // Get Clipboard and set text
+ auto refClipboard = Gtk::Clipboard::get();
refClipboard->set_text(text);
- //Show InfoBar
+ // Show InfoBar
label1.set_label("The Text is copyed");
infobar.show();
}
-void TextEditor::btnpaste_clicked(){
- //Get ClipBoard
- auto refClipboard=Gtk::Clipboard::get();
- refClipboard->request_text(sigc::mem_fun(*this,&TextEditor::clipboard_receive));
+void TextEditor::btnpaste_clicked()
+{
+ // Get ClipBoard
+ auto refClipboard = Gtk::Clipboard::get();
+ refClipboard->request_text(sigc::mem_fun(*this, &TextEditor::clipboard_receive));
}
-void TextEditor::clipboard_receive(const Glib::ustring &text){
- if(buffer1->insert_interactive_at_cursor(text)){
- //Show InfoBar
+void TextEditor::clipboard_receive(const Glib::ustring &text)
+{
+ if (buffer1->insert_interactive_at_cursor(text))
+ {
+ // Show InfoBar
label1.set_label("The Text is Pasted at cursor position");
infobar.show();
- }else{
- //Show InfoBar
+ }
+ else
+ {
+ // Show InfoBar
label1.set_label("Text Paste Error!");
infobar.show();
}
}
-void TextEditor::btnclear_clicked(){
+void TextEditor::btnclose_clicked()
+{
buffer1->set_text("");
+ file_opened = false;
}
-void TextEditor::infobar_response(int response){
+void TextEditor::infobar_response(int response)
+{
infobar.hide();
}