/* 
 * © 2007-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "stdafx.h"

#include "editor_base.h"


using namespace bec;






UndoObjectChangeGroup::UndoObjectChangeGroup(const std::string &object_id, const std::string &member)
  : _object_id(object_id), _member(member)
{
}


bool UndoObjectChangeGroup::matches_group(UndoGroup *group) const
{
  UndoObjectChangeGroup *other= dynamic_cast<UndoObjectChangeGroup*>(group);
  if (!other)
    return false;

  return other->_object_id == _object_id && _member == other->_member;
}


//--------------------------------------------------------------------------------

RefreshCentry::RefreshCentry(BaseEditor &editor) : _editor(editor)
{
  _editor.block_auto_refresh();
};

RefreshCentry::~RefreshCentry()
{
  _editor.unblock_auto_refresh();
}


//--------------------------------------------------------------------------------


BaseEditor::BaseEditor(GRTManager *grtm, const grt::Ref<GrtObject> &object)
: _grtm(grtm), _object(object), _locked(false)
{
  if (object.is_valid())
    add_listeners(object);
}


BaseEditor::~BaseEditor()
{
}


std::string BaseEditor::get_form_context_name() const
{
  return "editor"; //WB_CONTEXT_EDITOR;
}


void BaseEditor::add_listeners(const grt::Ref<GrtObject> &object)
{
  object->signal_changed().connect(sigc::mem_fun(this, &BaseEditor::object_member_changed));
  object->signal_list_changed().connect(sigc::hide(sigc::hide(sigc::hide(sigc::mem_fun(this, &BaseEditor::on_object_changed)))));
}


void BaseEditor::object_member_changed(const std::string &member, const grt::ValueRef &ovalue)
{
  if (_ignored_object_fields_for_ui_refresh.find(member) == _ignored_object_fields_for_ui_refresh.end())    
    on_object_changed();
}


void BaseEditor::on_object_changed()
{
  // calling ui_refresh from here will cause refresh to be called from the GRT thread
  // which must not happen. delaying it to be executing when idle will make it 
  // get called on main thread

//  do_ui_refresh();
  //if (_refresh_ui)
  //  _refresh_ui();

  if (_grtm->in_main_thread())
    do_ui_refresh();
  else
    _grtm->run_when_idle(sigc::bind_return<bool>(sigc::mem_fun(this, &RefreshUI::do_ui_refresh), false));
}


void BaseEditor::undo_applied()
{
  _grtm->run_when_idle(sigc::bind_return<bool>(sigc::mem_fun(this, &RefreshUI::do_ui_refresh), false));
}



void BaseEditor::run_from_grt(const sigc::slot<void> &slot)
{
  GRTDispatcher *disp= _grtm->get_dispatcher();

  disp->execute_simple_function("editor action",
    sigc::bind_return<grt::ValueRef>(sigc::hide(slot), grt::ValueRef()));
}


/** 
 ****************************************************************************
 * @brief Marks the editor as in use by the frontend.
 *
 * When the frontend starts displaying data from the editor backend,
 * it should lock it and when it's done with it, it should unlock it.
 * If the editor backend is unlocked and there are no unapplied changes to it,
 * it will emit a "unlocked" signal, which will normally release the backend.
 *
 *****************************************************************************/
void BaseEditor::lock()
{
  _locked= true;
}


void BaseEditor::unlock()
{
  _locked= false;

  _unlocked_signal.emit(this);
}

