From bbe3f0f65f3cb40de548b8e351da60018557eacd Mon Sep 17 00:00:00 2001
From: Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
Date: Fri, 9 Aug 2013 23:40:19 -0300
Subject: [PATCH] support appmenu.

appmenu will show out of window if wm supports it (e18 module + shelf
gadget), or inside window otherwise. It will offer the actions we have
with right-click "controls", but in a more standard way.

Current efl theme looks ugly, so one can disable it with
ELM_DISABLE_EXTERNAL_MENU=1.
---
 src/bin/main.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/bin/win.c  |  91 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 224 insertions(+), 3 deletions(-)

diff --git a/src/bin/main.c b/src/bin/main.c
index 5b5dd47..d4071fe 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -90,11 +90,60 @@ static Config *main_config = NULL;
 static void _term_media_update(Term *term, const Config *config);
 static void _popmedia_queue_process(Term *term);
 static void main_win_free(Win *wn);
+static Term *main_win_focused_term_get(Win *wn);
 static void main_term_free(Term *term);
 static void main_term_bg_redo(Term *term);
 static Term *main_term_new(Win *wn, Config *config, const char *cmd, Eina_Bool login_shell, const char *cd, int size_w, int size_h, Eina_Bool hold);
 static void _term_focus(Term *term);
+static void _term_focus_show(Split *sp, Term *term);
 static void _sel_restore(Split *sp);
+static void _sel_go(Split *sp, Term *term);
+static void _cb_options_done(void *data);
+static Split *_split_find(Evas_Object *win, Evas_Object *term);
+
+
+static void
+_tab_selected_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                  void *event_info EINA_UNUSED)
+{
+   Term *term_new = data;
+   Term *term_old = main_win_focused_term_get(term_new->wn);
+   Split *sp_new = _split_find(term_new->wn->win, term_new->term);
+   Split *sp_old = _split_find(term_old->wn->win, term_old->term);
+
+   if (sp_new == sp_old)
+     _sel_go(sp_new, term_new);
+   else
+     {
+        _term_focus(term_new);
+        if (sp_new) _term_focus_show(sp_new, term_new);
+     }
+}
+
+static void
+main_tabs_update(Win *wn)
+{
+   Evas_Object *menu;
+   Elm_Object_Item *mi, *smi;
+   Eina_List *clearlist;
+   const Eina_List *l;
+   const Term *term;
+
+   mi = evas_object_data_get(wn->win, "main_menu:tabs");
+   if (!mi) return;
+
+   clearlist = eina_list_clone(elm_menu_item_subitems_get(mi));
+   EINA_LIST_FREE(clearlist, smi)
+     elm_object_item_del(smi);
+
+   menu = elm_win_main_menu_get(wn->win);
+   EINA_LIST_FOREACH(wn->terms, l, term)
+     {
+        const char *title = termio_title_get(term->term);
+        if (!title) title = "Untitled";
+        elm_menu_item_add(menu, mi, NULL, title, _tab_selected_cb, term);
+     }
+}
 
 static void
 _split_free(Split *sp)
@@ -704,6 +753,70 @@ _cb_focus_out(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
 }
 
 static void
+_cb_terminology_settings(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   options_toggle(wn->win, wn->base, term->term, _cb_options_done, wn);
+}
+
+static void
+_cb_terminology_about(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   about_toggle(wn->win, wn->base, term->term, _cb_options_done, wn);
+}
+
+static void
+_cb_terminal_new(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   main_new(wn->win, term->term);
+}
+
+static void
+_cb_terminal_split_h(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   main_split_h(wn->win, term->term);
+}
+
+static void
+_cb_terminal_split_v(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   main_split_v(wn->win, term->term);
+}
+
+static void
+_cb_terminal_close(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   main_close(wn->win, term->term);
+}
+
+static void
+_cb_edit_copy(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   termio_copy_clipboard(term->term);
+}
+
+static void
+_cb_edit_paste(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Win *wn = data;
+   Term *term = main_win_focused_term_get(wn);
+   termio_paste_clipboard(term->term);
+}
+
+static void
 _cb_term_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event )
 {
    Evas_Event_Mouse_Down *ev = event;
@@ -1405,6 +1518,7 @@ _cb_title(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
    Term *term = data;
    if (term->focused)
      elm_win_title_set(term->wn->win, termio_title_get(term->term));
+   main_tabs_update(term->wn);
 }
 
 static void
@@ -1941,7 +2055,22 @@ main_win_new(const char *name, const char *role, const char *title,
 
    evas_object_smart_callback_add(wn->win, "focus,in", _cb_focus_in, wn);
    evas_object_smart_callback_add(wn->win, "focus,out", _cb_focus_out, wn);
-   
+
+   evas_object_smart_callback_add(wn->win, "terminology,settings",
+                                  _cb_terminology_settings, wn);
+   evas_object_smart_callback_add(wn->win, "terminology,about",
+                                  _cb_terminology_about, wn);
+   evas_object_smart_callback_add(wn->win, "terminal,new",
+                                  _cb_terminal_new, wn);
+   evas_object_smart_callback_add(wn->win, "terminal,split-h",
+                                  _cb_terminal_split_h, wn);
+   evas_object_smart_callback_add(wn->win, "terminal,split-v",
+                                  _cb_terminal_split_v, wn);
+   evas_object_smart_callback_add(wn->win, "terminal,close",
+                                  _cb_terminal_close, wn);
+   evas_object_smart_callback_add(wn->win, "edit,copy", _cb_edit_copy, wn);
+   evas_object_smart_callback_add(wn->win, "edit,paste", _cb_edit_paste, wn);
+
    wins = eina_list_append(wins, wn);
    return wn;
 }
@@ -1949,6 +2078,7 @@ main_win_new(const char *name, const char *role, const char *title,
 static void
 main_term_free(Term *term)
 {
+   Win *wn = term->wn;
    const char *s;
    
    EINA_LIST_FREE(term->popmedia_queue, s)
@@ -1979,6 +2109,8 @@ main_term_free(Term *term)
    if (term->config) config_del(term->config);
    term->config = NULL;
    free(term);
+
+   main_tabs_update(wn);
 }
 
 static void
@@ -2182,6 +2314,8 @@ main_term_new(Win *wn, Config *config, const char *cmd,
      }
    wn->terms = eina_list_append(wn->terms, term);
    
+   main_tabs_update(wn);
+
    return term;
 }
 
diff --git a/src/bin/win.c b/src/bin/win.c
index f5ca624..78b5c6f 100644
--- a/src/bin/win.c
+++ b/src/bin/win.c
@@ -2,11 +2,76 @@
 #include "win.h"
 #include "config.h"
 
+static void
+_menu_settings_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                  void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "terminology,settings", NULL);
+}
+
+static void
+_menu_about_cb(void *data, Evas_Object *obj EINA_UNUSED,
+               void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "terminology,about", NULL);
+}
+
+static void
+_menu_new_cb(void *data, Evas_Object *obj EINA_UNUSED,
+             void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "terminal,new", NULL);
+}
+
+static void
+_menu_split_h_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                 void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "terminal,split-h", NULL);
+}
+
+static void
+_menu_split_v_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                 void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "terminal,split-v", NULL);
+}
+
+static void
+_menu_close_cb(void *data, Evas_Object *obj EINA_UNUSED,
+               void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "terminal,close", NULL);
+}
+
+static void
+_menu_copy_cb(void *data, Evas_Object *obj EINA_UNUSED,
+              void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "edit,copy", NULL);
+}
+
+static void
+_menu_paste_cb(void *data, Evas_Object *obj EINA_UNUSED,
+               void *event_info EINA_UNUSED)
+{
+   Evas_Object *win = data;
+   evas_object_smart_callback_call(win, "edit,paste", NULL);
+}
+
 Evas_Object *
 tg_win_add(const char *name, const char *role, const char *title, const char *icon_name)
 {
-   Evas_Object *win, *o;
-   char buf[4096];
+   Evas_Object *win, *o, *menu;
+   Elm_Object_Item *mi;
+   char buf[4096], *s;
 
    if (!name) name = "main";
    if (!title) title = "Terminology";
@@ -25,5 +90,27 @@ tg_win_add(const char *name, const char *role, const char *title, const char *ic
    evas_object_image_file_set(o, buf, NULL);
    elm_win_icon_object_set(win, o);
 
+   s = getenv("ELM_DISABLE_EXTERNAL_MENU");
+   if ((s) && (atoi(s))) return win;
+
+   menu = elm_win_main_menu_get(win);
+
+   mi = elm_menu_item_add(menu, NULL, NULL, "Terminology", NULL, NULL);
+   elm_menu_item_add(menu, mi, "settings", "Settings", _menu_settings_cb, win);
+   elm_menu_item_add(menu, mi, "about", "About", _menu_about_cb, win);
+
+   mi = elm_menu_item_add(menu, NULL, NULL, "Terminal", NULL, NULL);
+   elm_menu_item_add(menu, mi, "new", "New", _menu_new_cb, win);
+   elm_menu_item_add(menu, mi, "split-v", "Split V", _menu_split_v_cb, win);
+   elm_menu_item_add(menu, mi, "split-h", "Split H", _menu_split_h_cb, win);
+   elm_menu_item_add(menu, mi, "close", "Close", _menu_close_cb, win);
+
+   mi = elm_menu_item_add(menu, NULL, NULL, "Edit", NULL, NULL);
+   elm_menu_item_add(menu, mi, "copy", "Copy", _menu_copy_cb, win);
+   elm_menu_item_add(menu, mi, "Paste", "Paste", _menu_paste_cb, win);
+
+   mi = elm_menu_item_add(menu, NULL, NULL, "Tabs", NULL, NULL);
+   evas_object_data_set(win, "main_menu:tabs", mi);
+
    return win;
 }
-- 
1.8.3.4

