#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "mainview/edi_mainview_item.h" #include "mainview/edi_mainview_panel.h" #include "mainview/edi_mainview.h" #include "edi_filepanel.h" #include "editor/edi_editor.h" #include "edi_content_provider.h" #include "edi_private.h" #include "edi_config.h" typedef struct _Edi_Mainview_State { Edi_Mainview_Panel *panel; char *path; } Edi_Mainview_State; static Edi_Mainview_State *_cached = NULL; static Evas_Object *_main_win; static Evas_Object *_edi_mainview_goto_popup; static void dummy() {} static void _edi_mainview_panel_cache_set(void) { Edi_Mainview_Item *item; if (!_cached) _cached = calloc(1, sizeof(Edi_Mainview_State)); if (_cached->path) { free(_cached->path); _cached->path = NULL; } _cached->panel = edi_mainview_panel_current_get(); item = edi_mainview_item_current_get(); if (item) _cached->path = strdup(item->path); } static Edi_Mainview_State * _edi_mainview_panel_cache_get(void) { if (!_cached || !_cached->panel || !_cached->path) return NULL; return _cached; } static Edi_Mainview_Item * _get_item_for_path(Edi_Mainview_Panel *panel, const char *path) { Eina_List *item; Edi_Mainview_Item *it; if (!panel || !path) return NULL; EINA_LIST_FOREACH(panel->items, item, it) { if (it && !strcmp(it->path, path)) return it; } return NULL; } unsigned int edi_mainview_panel_item_count(Edi_Mainview_Panel *panel) { return eina_list_count(panel->items); } Edi_Mainview_Item * edi_mainview_panel_item_current_get(Edi_Mainview_Panel *panel) { if (!panel) return NULL; return panel->current; } unsigned int edi_mainview_panel_item_current_tab_get(Edi_Mainview_Panel *panel) { Eina_List *item; Edi_Mainview_Item *it; unsigned int i = 0; EINA_LIST_FOREACH(panel->items, item, it) { if (!it->win) i++; if (it && it == panel->current) break; } return i; } static void _edi_mainview_panel_current_tab_hide(Edi_Mainview_Panel *panel) { Edi_Editor *editor; edi_mainview_panel_focus(panel); if (!panel || !panel->current) return; editor = (Edi_Editor *)evas_object_data_get(panel->current->view, "editor"); if (editor) { elm_object_focus_set(editor->entry, EINA_FALSE); evas_object_hide(editor->entry); } } static void _edi_mainview_panel_current_tab_show(Edi_Mainview_Panel *panel) { Edi_Editor *editor; edi_mainview_panel_focus(panel); if (!panel || !panel->current) return; editor = (Edi_Editor *)evas_object_data_get(panel->current->view, "editor"); if (editor) { evas_object_show(editor->entry); elm_object_focus_set(editor->entry, EINA_TRUE); } } Edi_Mainview_Item * _edi_mainview_panel_item_for_view_get(Edi_Mainview_Panel *panel, Evas_Object *view) { Eina_List *item; Edi_Mainview_Item *it; EINA_LIST_FOREACH(panel->items, item, it) { if (it->view == view) return it; } return NULL; } Eina_Bool edi_mainview_panel_item_contains(Edi_Mainview_Panel *panel, Edi_Mainview_Item *item) { Eina_List *it; Edi_Mainview_Item *panel_item; EINA_LIST_FOREACH(panel->items, it, panel_item) { if (panel_item == item) return EINA_TRUE; } return EINA_FALSE; } void edi_mainview_panel_item_prev(Edi_Mainview_Panel *panel) { Eina_List *item; Edi_Mainview_Item *it, *first, *prev = NULL; first = (Edi_Mainview_Item *)eina_list_nth(panel->items, 0); if (first == panel->current) { prev = eina_list_nth(panel->items, eina_list_count(panel->items)-1); if (prev) edi_mainview_panel_item_select(panel, prev); return; } EINA_LIST_FOREACH(panel->items, item, it) { if (it && it == panel->current) { if (prev) edi_mainview_panel_item_select(panel, prev); return; } prev = it; } } void edi_mainview_panel_item_next(Edi_Mainview_Panel *panel) { Eina_List *item; Edi_Mainview_Item *it, *last, *next; Eina_Bool open_next = EINA_FALSE; last = eina_list_nth(panel->items, eina_list_count(panel->items)-1); if (last == panel->current) { next = eina_list_nth(panel->items, 0); if (next) edi_mainview_panel_item_select(panel, next); return; } EINA_LIST_FOREACH(panel->items, item, it) { if (it && open_next) { edi_mainview_panel_item_select(panel, it); return; } if (it && it == panel->current) open_next = EINA_TRUE; } } void edi_mainview_panel_tab_select(Edi_Mainview_Panel *panel, unsigned int id) { Eina_List *item; Edi_Mainview_Item *it; unsigned int i = 0; EINA_LIST_FOREACH(panel->items, item, it) { if (!it->win) i++; if (i == id) edi_mainview_panel_item_select(panel, it); } } static void _edi_mainview_panel_show(Edi_Mainview_Panel *panel, Evas_Object *view) { if (panel->current) { elm_box_unpack(panel->content, panel->current->view); evas_object_hide(panel->current->view); } else { elm_box_unpack(panel->content, panel->welcome); evas_object_hide(panel->welcome); } panel->current = _edi_mainview_panel_item_for_view_get(panel, view); elm_box_pack_end(panel->content, view); evas_object_show(view); } static void _content_load(Edi_Mainview_Item *item) { Edi_Content_Provider *provider; Evas_Object *child; provider = edi_content_provider_for_id_get(item->editortype); if (!provider) { ERR("No content provider found for type %s", item->editortype); return; } child = provider->content_ui_add(item->container, item); evas_object_size_hint_weight_set(child, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(child, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(item->container, child); evas_object_show(child); item->loaded = EINA_TRUE; } void edi_mainview_panel_item_close(Edi_Mainview_Panel *panel, Edi_Mainview_Item *item) { int item_index; Eina_Bool current; if (!item) return; current = (item == panel->current); item_index = eina_list_data_idx(panel->items, item); if (item->view) evas_object_del(item->view); elm_box_unpack(panel->tabs, item->tab->button); evas_object_del(item->tab->button); panel->items = eina_list_remove(panel->items, item); _edi_project_config_tab_remove(item->path, EINA_FALSE, edi_mainview_panel_index_get(panel)); eina_stringshare_del(item->path); if (item->tab->path) free(item->tab->path); free(item->tab); free(item); if (!current) return; if (eina_list_count(panel->items) == 0) { _edi_mainview_panel_show(panel, panel->welcome); return; } if (item_index) item = eina_list_nth(panel->items, item_index - 1); else item = eina_list_nth(panel->items, item_index); edi_mainview_panel_item_select(panel, item); _edi_mainview_panel_current_tab_show(panel); } void edi_mainview_panel_item_select(Edi_Mainview_Panel *panel, Edi_Mainview_Item *item) { Eina_List *list; Edi_Mainview_Item *it; Evas_Coord tabw, region_x = 0, w, total_w = 0; if (item->win) { elm_win_raise(item->win); } else { EINA_LIST_FOREACH(panel->items, list, it) { elm_object_signal_emit(it->tab->button, "mouse,up,1", "base"); evas_object_geometry_get(it->tab->button, NULL, NULL, &w, NULL); if (item == it) region_x = total_w; total_w += w; } if (!item->loaded) _content_load(item); _edi_mainview_panel_show(panel, item->view); elm_object_signal_emit(item->tab->button, "mouse,down,1", "base"); evas_object_geometry_get(item->tab->button, NULL, NULL, &tabw, NULL); elm_scroller_region_bring_in(efl_parent_get(panel->tabs), region_x, 0, tabw, 0); _edi_project_config_tab_current_set(edi_mainview_panel_index_get(panel), edi_mainview_panel_item_current_tab_get(panel)); _edi_project_config_save_no_notify(); } edi_mainview_panel_focus(panel); ecore_event_add(EDI_EVENT_TAB_CHANGED, NULL, NULL, NULL); } static void _promote(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source) { Edi_Mainview_Panel *panel; Edi_Mainview_Item *item = (Edi_Mainview_Item *) data; // ignore if we clicked the delete part of the button if (!strcmp(source, "del")) return; panel = edi_mainview_panel_for_item_get(item); _edi_mainview_panel_cache_set(); _edi_mainview_panel_current_tab_hide(panel); edi_mainview_panel_item_select(panel, item); _edi_mainview_panel_current_tab_show(panel); edi_filepanel_select_path(item->path); } static void _closetab(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { Edi_Mainview_Panel *panel; Edi_Mainview_Item *item; Edi_Mainview_State *last; Edi_Editor *editor; int index; item = (Edi_Mainview_Item *) data; panel = edi_mainview_panel_for_item_get(item); editor = (Edi_Editor *) evas_object_data_get(panel->current->view, "editor"); if (editor && eina_list_count(editor->split_views)) { Elm_Code *code; const char *path; Elm_Code_Widget *widget = eina_list_nth(editor->split_views, 0); elm_box_unpack(panel->current->container, widget); code = elm_code_widget_code_get(editor->entry); path = elm_code_file_path_get(code->file); editor->split_views = eina_list_remove(editor->split_views, widget); _edi_project_config_tab_split_view_count_set(path, edi_mainview_panel_id(panel), eina_list_count(editor->split_views)); evas_object_del(widget); return; } edi_mainview_panel_item_close(panel, item); if (eina_list_count(panel->items)== 0 && edi_mainview_panel_count() > 1) { edi_mainview_panel_remove(panel); index = edi_mainview_panel_count() - 1; panel = edi_mainview_panel_by_index(index); } edi_mainview_panel_focus(panel); /* When closing tabs keep current tab */ last = _edi_mainview_panel_cache_get(); if (last && last->panel == panel && last->path) { item = _get_item_for_path(panel, last->path); if (item) { _edi_mainview_panel_current_tab_hide(panel); edi_mainview_panel_item_select(panel, item); } } if (eina_list_count(panel->items)) _edi_mainview_panel_current_tab_show(panel); if (eina_list_count(panel->items) == 0 && edi_mainview_panel_count() == 1) { edi_main_win_title_reset(); } } static Evas_Object * _edi_mainview_panel_content_create(Edi_Mainview_Item *item, Evas_Object *parent) { Evas_Object *container; container = elm_box_add(parent); evas_object_size_hint_weight_set(container, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(container, EVAS_HINT_FILL, EVAS_HINT_FILL); item->loaded = EINA_FALSE; item->container = container; return container; } static int _font_width_get(Evas_Object *parent, const char *text) { int w = 0; Evas_Object *textblock = evas_object_text_add(parent); evas_object_size_hint_weight_set(textblock, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(textblock, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(textblock); evas_object_text_font_set(textblock, "sans", 12); evas_object_text_text_set(textblock, text); evas_object_geometry_get(textblock, NULL, NULL, &w, NULL); evas_object_del(textblock); if (w < 120) w = 120; return w; } // TODO: Allow tab moving between panels. static char *_tab_move_src_path = NULL; static void _tab_swap(const char *path1, const char *path2) { Edi_Mainview_Panel *panel, *p1, *p2; Edi_Mainview_Item *item, *it1, *it2; Edi_Mainview_Item *tmp1, *tmp2; Eina_List *l, *l_next; it1 = it2 = NULL; if (!strcmp(path1, path2)) return; int count = edi_mainview_panel_count(); for (int i = 0; i < count; i++) { panel = edi_mainview_panel_by_index(i); EINA_LIST_FOREACH(panel->items, l, item) { if (!strcmp(item->path, path1)) { it1 = item; p1 = panel; } else if (!strcmp(item->path, path2)) { it2 = item; p2 = panel; } if (it1 && it2) break; } } if ((!it1 || !it2) || (p1 != p2)) return; tmp1 = it1; tmp2 = it2; panel = p1; EINA_LIST_FOREACH_SAFE(panel->items, l, l_next, item) { if (item == it1) l = eina_list_data_set(l, tmp2); if (item == it2) l = eina_list_data_set(l, tmp1); } elm_box_unpack_all(panel->tabs); EINA_LIST_FOREACH(panel->items, l, item) { elm_box_pack_end(panel->tabs, item->tab->button); } elm_box_recalculate(panel->tabs); edi_mainview_panel_item_select_path(panel, path2); } static void _tab_move_display_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Move *ev; Edi_Mainview_Item_Tab *tab = data; if (!tab) return; ev = event_info; elm_object_tooltip_hide(tab->button); evas_object_move(tab->button_drag, ev->cur.canvas.x, ev->cur.canvas.y); evas_object_show(tab->button_drag); } static void _tab_move_done_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Edi_Mainview_Item_Tab *tab = data; if (!tab) return; evas_object_event_callback_del(tab->button, EVAS_CALLBACK_MOUSE_UP, _tab_move_done_cb); evas_object_event_callback_del(tab->toolbar, EVAS_CALLBACK_MOUSE_MOVE, _tab_move_display_cb); evas_object_del(tab->button_drag); if (_tab_move_src_path) { free(_tab_move_src_path); _tab_move_src_path = NULL; } } static void _tab_move_begin_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Down *ev; Evas_Object *btn; Edi_Mainview_Item_Tab *tab; Evas_Coord w, h; tab = data; if (!tab || _tab_move_src_path) return; ev = event_info; /* Duplicate our tab visually in a box we can drag. */ evas_object_geometry_get(obj, NULL, NULL, &w, &h); tab->button_drag = elm_box_add(edi_main_win_get()); btn = elm_button_add(tab->button_drag); elm_box_pack_end(tab->button_drag, btn); elm_layout_theme_set(btn, "multibuttonentry", "btn", "default"); evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_part_text_set(btn, "elm.btn.text", elm_object_part_text_get(obj, "elm.btn.text")); elm_object_focus_set(btn, EINA_TRUE); evas_object_show(btn); evas_object_move(tab->button_drag, ev->output.x, ev->output.y); evas_object_resize(tab->button_drag, w, h); _tab_move_src_path = strdup(tab->path); evas_object_event_callback_add(tab->toolbar, EVAS_CALLBACK_MOUSE_MOVE, _tab_move_display_cb, tab); evas_object_event_callback_add(tab->button, EVAS_CALLBACK_MOUSE_UP, _tab_move_done_cb, tab); } static void _tab_mouse_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Edi_Mainview_Item_Tab *tab = data; if (!tab || !tab->path || !_tab_move_src_path) return; _tab_swap(tab->path, _tab_move_src_path); } static void _edi_mainview_panel_item_tab_add(Edi_Mainview_Panel *panel, Edi_Path_Options *options, const char *mime) { Evas_Object *content, *btn; Edi_Mainview_Item *item; Edi_Editor *editor; Elm_Code *code; int h, width; const char *path; if (!panel) return; int id = edi_mainview_panel_id(panel); if (panel == edi_mainview_panel_current_get()) { if (eina_list_count(panel->items)) _edi_mainview_panel_current_tab_hide(panel); } item = edi_mainview_item_add(options, mime, NULL, NULL); content = _edi_mainview_panel_content_create(item, panel->content); item->view = content; panel->items = eina_list_append(panel->items, item); _edi_mainview_panel_show(panel, content); evas_object_geometry_get(panel->tabs, NULL, NULL, NULL, &h); btn = elm_button_add(panel->tabs); evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(btn, 0.0, EVAS_HINT_FILL); elm_object_focus_allow_set(btn, EINA_FALSE); path = strstr(item->path, edi_project_get()); if (path) path += 1 + strlen(edi_project_get()); else path = item->path; elm_object_tooltip_text_set(btn, path); elm_object_tooltip_window_mode_set(btn, EINA_TRUE); elm_layout_theme_set(btn, "multibuttonentry", "btn", "default"); elm_object_part_text_set(btn, "elm.btn.text", eina_slstr_printf("