/* 
 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */


#include "form_view_base.h"
#include "plugin_editor_base.h"
#include <gtkmm/box.h>
#include <gtkmm/label.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/window.h>
#include "active_label.h"
#include "grt/grt_manager.h"
#include "mforms/toolbar.h"

bool FormViewBase::close_plugin_tab(PluginEditorBase *editor)
{
  if (editor->can_close())
  {
    _close_editor(editor);
    remove_plugin_tab(editor);
  }
  else
    return false;

  bool has_visible_tabs = false;
  for (int c= _editor_note->get_n_pages(), i= 0; i < c; i++)
  {
    if (_editor_note->get_nth_page(i)->is_visible())
    {
      has_visible_tabs = true;
      break;
    }
  }
  if (!has_visible_tabs)
    _editor_note->hide();

  return true;
}


void FormViewBase::set_close_editor_callback(const sigc::slot<void, PluginEditorBase*> &handler)
{
  _close_editor = handler;
}
  

void FormViewBase::add_plugin_tab(PluginEditorBase *plugin)
{
  if (_editor_note)
  {
    ActiveLabel* label = Gtk::manage(new ActiveLabel(plugin->get_title(), sigc::hide_return(sigc::bind(sigc::mem_fun(this, &FormViewBase::close_plugin_tab), plugin))));

    int page_num = _editor_note->append_page(*plugin, *label);

    plugin->signal_title_changed().connect(sigc::mem_fun(label, &ActiveLabel::set_text));

    if (!_editor_note->is_visible())
    {
      _editor_note->show();
      reset_layout();
    }

    plugin_tab_added(plugin);

    Glib::signal_idle().connect_once(sigc::bind(sigc::mem_fun(_editor_note, &Gtk::Notebook::set_current_page), page_num));

  }
  else
    g_warning("active form doesn't support editor tabs");
}



void FormViewBase::remove_plugin_tab(PluginEditorBase *plugin)
{
  if (_editor_note)
  {
    _editor_note->remove_page(*plugin);
    
    //  Make the plugin manager forget about this plugin
    GUIPluginBase *base = dynamic_cast<GUIPluginBase *>(plugin);
    _grtm->get_plugin_manager()->close_and_forget_gui_plugin(reinterpret_cast<NativeHandle>(base));

    if (_editor_note->get_n_pages() == 0)
      _editor_note->hide();
  }
}


bool FormViewBase::close_editors_for_object(const std::string &id)
{
  for (int i= _editor_note->get_n_pages()-1; i >= 0; --i)
  {
    Gtk::Widget *panel= _editor_note->get_nth_page(i);
    PluginEditorBase* editor;
    if ((editor= dynamic_cast<PluginEditorBase*>(panel))
        && (id.empty() || editor->should_close_on_delete_of(id)))
    {
      remove_plugin_tab(editor);
      return true;
    }
  }

  return false;
}


PluginEditorBase *FormViewBase::get_focused_plugin_tab()
{
  if (_editor_note)
  {
    Gtk::Widget *focused= dynamic_cast<Gtk::Window*>(_editor_note->get_toplevel())->get_focus();

    // go up the hierarchy to see if the focused widget is inside _editor_note
    while (focused && focused != _editor_note)
      focused= focused->get_parent();
    
    if (focused)
    {
      int page= _editor_note->get_current_page();
      if (page >= 0)
      {
        Gtk::Widget *tab= _editor_note->get_nth_page(page);
        return dynamic_cast<PluginEditorBase*>(tab);
      }
    }
  }

  return 0;
}


bool FormViewBase::close_focused_tab()
{
  PluginEditorBase *active = get_focused_plugin_tab();

  if (active)
  {
    close_plugin_tab(active);
    return true;
  }

  return false;
}


void FormViewBase::restore_sidebar_layout()
{
  if (_sidebar1_pane)
  {
    int w = _grtm->get_app_option_int(_panel_savename+":SidebarWidth", 200);
    _sidebar1_pane->set_position(w);
    if (_grtm->get_app_option_int(_panel_savename+":SidebarHidden", 0))
    {
      _toolbar->set_item_checked("wb.toggleSidebar", false);
      _sidebar1_pane->get_child1()->hide();
    }
    else
      _toolbar->set_item_checked("wb.toggleSidebar", true);

    _sidebar1_pane->property_position().signal_changed().connect(sigc::bind(sigc::mem_fun(this, &FormViewBase::sidebar_resized), true));
  }

  if (_sidebar2_pane)
  {
    int w = _grtm->get_app_option_int(_panel_savename+":SecondarySidebarWidth", 200);
    _sidebar2_pane->set_position(_sidebar2_pane->get_width()-w);
    if (_grtm->get_app_option_int(_panel_savename+":SecondarySidebarHidden", 0))
    {
      _toolbar->set_item_checked("wb.toggleSecondarySidebar", false);
      _sidebar2_pane->get_child2()->hide();
    }
    else
      _toolbar->set_item_checked("wb.toggleSecondarySidebar", true);     

    _sidebar2_pane->property_position().signal_changed().connect(sigc::bind(sigc::mem_fun(this, &FormViewBase::sidebar_resized), false));
  }
}


void FormViewBase::toggle_sidebar(bool show)
{
  if (_sidebar1_pane)
  {
    Gtk::Widget *w = _sidebar1_pane->get_child1();
    if (show)
      w->show();
    else
      w->hide();
  }
}


void FormViewBase::toggle_secondary_sidebar(bool show)
{
  if (_sidebar2_pane)
  {
    Gtk::Widget *w = _sidebar2_pane->get_child2();
    if (show)
      w->show();
    else
      w->hide();
  }
}


void FormViewBase::sidebar_resized(bool primary)
{
  if (primary)
    _grtm->set_app_option(_panel_savename+":SidebarWidth", grt::IntegerRef(_sidebar1_pane->get_position()));
  else
    _grtm->set_app_option(_panel_savename+":SecondarySidebarWidth", grt::IntegerRef(_sidebar2_pane->get_width() - _sidebar2_pane->get_position()));
}


bool FormViewBase::perform_command(const std::string &cmd)
{
  if (cmd == "wb.toggleSidebar")
  {
    bool hidden = !_toolbar->get_item_checked(cmd);
    _grtm->set_app_option(_panel_savename+":SidebarHidden", grt::IntegerRef(hidden));
    toggle_sidebar(!hidden);
    return true;
  }
  else if (cmd == "wb.toggleSecondarySidebar")
  {
    bool hidden = !_toolbar->get_item_checked(cmd);
    _grtm->set_app_option(_panel_savename+":SecondarySidebarHidden", grt::IntegerRef(hidden));
    toggle_secondary_sidebar(!hidden);
    return true;
  }
  return false;
}

