/* Copyright (C) 2004 MySQL AB

   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; either version 2 of the License, or
   (at your option) any later version.

   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "myx_gc.h"
#include "myx_grt_gc_bridge.h"

//----------------- General initialization and finalization functions --------------------------------------------------

/**
 * Registers a new GRT-to-GC bridge (as new built-in module) with the given GRT.
 *
 * @param grt The runtime structure with which the bridge should be registered.
 * @return Either MYX_GRT_NO_ERROR if all went fine, otherwise an error code.
 */
MYX_GRT_ERROR myx_register_grt_gc_module(MYX_GRT* runtime)
{
  CGrtToGcBridge* bridge = new CGrtToGcBridge(runtime);

  // Register the new module and keep a reference to it.
  MYX_GRT_MODULE* module = myx_grt_module_register_builtin(runtime, &grt_module_grt_gc, bridge);
  bridge->module(module);

  if (module != NULL)
    return MYX_GRT_NO_ERROR;
  else                                 
    return MYX_GRT_MODULE_INIT_ERROR;
}

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

/**
 * Removes the GRT-to-GC bridge from the given grt.
 *
 * @param runtime The runtime structure from which the bridge should be unregistered.
 */
void myx_unregister_grt_gc_module(MYX_GRT* runtime)
{
  // Look if there is a module with that name.
  MYX_GRT_MODULE* module = myx_grt_find_module(runtime, grt_module_grt_gc.name);

  if (module != NULL)
  {
    CGrtToGcBridge* bridge = (CGrtToGcBridge*) module->priv;
    myx_grt_module_unregister_builtin(runtime, module);
    delete bridge;
  };
}

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

/**
 * Initializes a new mapping between the given canvas and path.
 *
 * @param runtime The runtime in which the resulting proxy is to be insterted.
 * @param Canvas The canvas that is used for the mapping.
 * @param Path The (absolute) target path for the resulting proxy object.
 */
void myx_grt_gc_bridge_initialize(MYX_GRT *runtime, CGenericCanvas *Canvas, const char *Path)
{
  // Look if there is a module with that name.
  MYX_GRT_MODULE* module = myx_grt_find_module(runtime, grt_module_grt_gc.name);

  if (module != NULL)
  {
    CGrtToGcBridge* bridge = (CGrtToGcBridge*) module->priv;

    // This creation will trigger a recursive initialization call chain, which fully creates the whole
    // GRT tree for that canvas (only default entries, optional entries are left out).
    MYX_GRT_VALUE* value = myx_grt_bridge_dict_new(runtime, "canvas.Canvas", (CGCBase*) Canvas);
    myx_grt_value_bridge_module_set(value, module);
    myx_grt_dict_item_set_by_path(myx_grt_get_root(runtime), Path, value);

    // Explicitely set the parent id as owner reference for the canvas.
    char* parentPath = myx_get_parent_path(Path);
    MYX_GRT_VALUE* parent = myx_grt_dict_item_get_by_path(myx_grt_get_root(runtime), parentPath);
    const char* id = myx_grt_dict_id_item_as_string(parent);
    myx_grt_dict_item_set_value_from_string(value, "owner", id);
    g_free(parentPath);

    bridge->addMapping(value, Canvas);

    // After that we can release the value once (it was retained once when it was created).
    myx_grt_value_release(value);
  };
}

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

void myx_grt_gc_bridge_free(MYX_GRT *runtime, CGenericCanvas *Canvas, const char *Path)
{
  // Look if there is a module with that name.
  MYX_GRT_MODULE* module = myx_grt_find_module(runtime, grt_module_grt_gc.name);

  if (module != NULL)
  {
    CGrtToGcBridge* bridge = (CGrtToGcBridge*) module->priv;

    MYX_GRT_VALUE* value = myx_grt_dict_item_get_by_path(myx_grt_get_root(runtime), Path);
    if (value != NULL)
    {
      myx_grt_value_bridge_data_object_set(value, NULL);
      bridge->removeMapping(Canvas);
    };
  };
}


//----------------- module internal functions --------------------------------------------------------------------------

/**
 * Called by GRT when a dict or list object has been created and must be initialized. The task of the bridge is to 
 * create the canvas object and attach it to the GRT value.
 *
 * @param value The GRT object that has just been created and to which the canvas object must be attached.
 * @param data Pointer to the bridge.
 * 
 * @return NULL if initialization goes fine, otherwise a GRT value containing an integer error code.
 */
MYX_GRT_VALUE* grt_gc_init(MYX_GRT_VALUE *value, void *data)
{
  MYX_GRT_VALUE *result = NULL;

  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  
  if (!bridge->initObject(value))
    result = myx_grt_value_from_int(1);

  return result;
}

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

/**
 * Called by GRT when a dict or list object has changed and the attached GC object must be updated.
 *
 * @param value The GRT object that requires a synchronization.
 * @param data Pointer to the bridge.
 * 
 * @return NULL if update goes fine, otherwise a GRT value containing an integer error code.
 */
MYX_GRT_VALUE* grt_gc_update(MYX_GRT_VALUE *value, void *data)
{
  MYX_GRT_VALUE *result = NULL;
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  if (!bridge->updateObject(value))
    result = myx_grt_value_from_int(1);

  return result;
}

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

/**
 * Called by GRT when a simple value has changed there and the corresponding GC value must be updated.
 *
 * @param value The GRT value that contains the new value to set.
 * @param data Pointer to the bridge.
 * 
 * @return NULL if update goes fine, otherwise a GRT value containing an integer error code.
 */
MYX_GRT_VALUE* grt_gc_value_from_grt(MYX_GRT_VALUE *value, void *data)
{
  MYX_GRT_VALUE* result = NULL;
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  if (!bridge->writeValue(value))
    // "2" indicates the property does not exist anymore (or a wrong name was specified).
    result = myx_grt_value_from_int(2);

  return result;
}

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

/**
 * Called by GRT when a simple GRT value is read and it must be made sure that it contains the latest value from the 
 * corresponding GC property (value).
 *
 * @param value The GRT object that must kept updated.
 * @param data Pointer to the bridge.
 * 
 * @return NULL if update goes fine, otherwise a GRT value containing an integer error code.
 */
MYX_GRT_VALUE* grt_gc_value_to_grt(MYX_GRT_VALUE *value, void *data)
{
  MYX_GRT_VALUE *result = NULL;
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  if (!bridge->updateValue(value))
    // "2" indicates the property does not exist anymore (or a wrong name was specified).
    result = myx_grt_value_from_int(2);

  return result;
}

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

/**
 * Called by GRT when a dict or list object is about to be destroyed. The bridge must now detach the corresponding
 * GC object and destroy that too if necessary.
 *
 * @param value The GRT object that is about to be destroyed.
 * @param data Pointer to the bridge.
 * 
 * @return NULL if deletion goes fine, otherwise a GRT value containing an integer error code.
 */
MYX_GRT_VALUE* grt_gc_delete(MYX_GRT_VALUE *value, void *data)
{
  MYX_GRT_VALUE *result = NULL;
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  if (!bridge->deleteObject(value))
    result = myx_grt_value_from_int(1);

  return result;
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_addFigureInstance(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->addFigureInstance(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_addLayer(MYX_GRT_VALUE *value, void *data) 
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->addLayer(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_addLayoutsFromFile(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->addLayoutsFromFile(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_addStylesFromFile(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->addStylesFromFile(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_addToSelection(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->addToSelection(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_beginUpdate(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->beginUpdate(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_checkError(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->checkError(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_clearContent(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->clearContent(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_clearLayouts(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->clearLayouts(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_clearSelection(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->clearSelection(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_clearStyles(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->clearStyles(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_containsPoint(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->containsPoint(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_createFigure(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->createFigure(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_createFigureInstance(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->createFigureInstance(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_createLayer(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->createLayer(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_createView(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->createView(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_endUpdate(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->endUpdate(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_getCurrentView(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->getCurrentView(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_grtFigureDelete(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->grtFigureDelete(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_grtFigureUpdate(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->grtFigureUpdate(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_grtGetFigureCreator(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->grtGetFigureCreator(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_grtGetFigureElement(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->grtGetFigureElement(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_grtToFigure(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->grtToFigure(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_layerByName(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->layerByName(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_refresh(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->refresh(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_release(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->release(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_removeFigureInstance(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->removeFigureInstance(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_removeFromSelection(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->removeFromSelection(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_removeLayer(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->removeLayer(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_removeView(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->removeView(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_setCurrentView(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->setCurrentView(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_showSelection(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->showSelection(value);
}

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

/**
 * Calls a function in the bridge with the given parameters. 
 * Read more in the implementation of the called function.
 *
 * @param value A GRT LIST containing the parameters for the call.
 * @param data Pointer to the bridge.
 * @return The result given by the bridge.
 */
MYX_GRT_VALUE* grt_gc_viewByName(MYX_GRT_VALUE *value, void *data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  return bridge->viewByName(value);
}

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

/**
 * This callback method is called by the GRT if certain things happen with a GRT value.
 */
int valueCallback(MYX_GRT* grt, MYX_GRT_VALUE* value, MYX_GRT_VALUE_CALLBACK_REASON reason, void* data)
{
  CGrtToGcBridge* bridge = (CGrtToGcBridge*) data;
  if (bridge != NULL)
    bridge->notification(value, reason);

  return 0;
}

//----------------- CGcObjectListener ------------------------------------------------------------------------------

void CGcObjectListener::onChange(CGCBase* sender, CGCBase* origin, TGCChangeReason reason)
{
}

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

void CGcObjectListener::onDestroy(CGCBase* sender)
{
  if (bridge != NULL)
    bridge->freeNotification(sender);
}

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

void CGcObjectListener::onError(CGCBase* sender, CGCBase* origin, const char* message)
{
  if (bridge != NULL)
    bridge->generateError("Module GenericCanvas returned an error", message);
}

//----------------- CGrtToGcBridge -------------------------------------------------------------------------------------

CGrtToGcBridge::CGrtToGcBridge(MYX_GRT* runtime)
{
  FUpdateCount = 0;
  FRuntime = runtime;

  FListener.bridge = this;
}

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

CGrtToGcBridge::~CGrtToGcBridge(void)
{
  // Remove our listener from all GC objects.
  for (CGcGrtMapper::iterator iterator = FGcToGrtMapper.begin(); iterator != FGcToGrtMapper.end(); ++iterator)
  {
    CGCBase* object = iterator->first;
    MYX_GRT_VALUE* value = iterator->second;
    myx_grt_value_release(value);
    object->removeListener(&FListener);
  };
}

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

/**
 * Adds a new forward and back mapping for id and object.
 *
 * @param id The id that is associated with object.
 * @param object The object that is registered under the given id.
 */
void CGrtToGcBridge::addIdMapping(const string& id, CGCBase* object)
{
  FGcToIdMapper[object] = id;
}

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

/**
 * Helper method to convert a GRT value to a figure.
 *
 * @param dict The dict GRT value that needs to be scanned.
 * @param figure The target figure to fill.
 */
void CGrtToGcBridge::convertDict(MYX_GRT_VALUE* dict, CFigure* figure)
{
  figure->beginUpdate();

  CFigureElement* content = figure->content();
  fillDictElement(content, dict, L"");

  figure->endUpdate();
}

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

/**
 * Called by the GRT and callback functions to delete all figures that had been created from the given value.
 *
 * @param value The value for which want to delete the figures.
 */
void CGrtToGcBridge::deleteFigures(MYX_GRT_VALUE* value)
{
  // Go through all figures in the creator map and look, which were created from the given value.
  // These must then be deleted. Create first a local list of entries as the mapper must be updated.
  vector<CFigure*> list;
  for (CGcGrtMapper::iterator iterator = FCreatorMapper.begin(); iterator != FCreatorMapper.end(); ++iterator)
  {
    if (iterator->second == value)
      list.push_back((CFigure*) iterator->first);
  };

  for (vector<CFigure*>::iterator iterator = list.begin(); iterator != list.end(); ++iterator)
  {
    FCreatorMapper.erase(*iterator);
    delete *iterator;
  };
}

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

/**
 * Fills a figure child element in the given figure element with all member elements determined by source. 
 *
 * @param element The figure element to update.
 * @param source The source data for the element (must be a GRT dict).
 * @param path The current path of all parent figure elements.
 */
void CGrtToGcBridge::fillDictElement(CFigureElement* element, MYX_GRT_VALUE* source, wstring path)
{
  const char *_id= myx_grt_dict_item_get_as_string(source, "_id");
  myx_grt_reference_cache_lookup(FRuntime, _id);

  unsigned int count = myx_grt_dict_item_count(source);
  for (unsigned int i = 0; i < count; ++i)
  {
    MYX_GRT_VALUE* child = myx_grt_dict_item_value_by_index(source, i);
    wstring localPath = path + L"/" + utf8ToUtf16(myx_grt_dict_item_key_by_index(source, i));
    CFigureElement* subElement = element->figure()->elementFromKey(localPath);
    if (subElement != NULL)
    {
      switch (myx_grt_value_get_type(child))
      {
        case MYX_LIST_VALUE:
          {
            fillListElement(subElement, child, localPath);
            break;
          };
        case MYX_DICT_VALUE:
          {
            fillDictElement(subElement, child, localPath);
            break;
          };
        default:
          {
            const char* text = myx_grt_value_as_string(child);
            if (text != NULL)
              subElement->setCaption(text);
            break;
          };
      };
    };
  };
}

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

/**
 * Fills a list in the given figure with all member elements determined by source. 
 * The list is identified by the name of the source value.
 *
 * @param element The figure element to update.
 * @param source The source data for the list (must be a GRT list).
 * @param path The current path of all parent figure elements.
 */
void CGrtToGcBridge::fillListElement(CFigureElement* element, MYX_GRT_VALUE* source, wstring path)
{
  if (element != NULL)
  {
    unsigned int count = myx_grt_list_item_count(source);
    for (unsigned int i = 0; i < count; ++i)
    {
      MYX_GRT_VALUE* item = myx_grt_list_item_get(source, i);
      CFigureElement* child = element->addSubElement();

      const char* caption = NULL;
      switch (myx_grt_value_get_type(item))
      {
        case MYX_LIST_VALUE:
          {
            // TODO: Is a list of lists possible?
            //caption = myx_grt_dict_item_key_by_index(source, i);
            break;
          };
        case MYX_DICT_VALUE:
          {
            caption = myx_grt_dict_name_item_as_string(item);
            break;
          };
        default:
          {
            caption = myx_grt_value_as_string(item);
            if (caption != NULL)
            {
              // This might be a normal property or a reference to another value. Check this.
              MYX_GRT_VALUE* target = myx_grt_reference_cache_lookup(FRuntime, caption);
              if (target != NULL)
                caption = myx_grt_dict_name_item_as_string(target);
            };
            break;
          };
      };

      if (caption != NULL)
        child->setCaption(caption);
    };
  };
}

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

/**
 * Creates a error result object as required by the GRT.
 *
 * @param message The message to be used for the error.
 * @param details If not empty then this string is kept for the error as detail info too.
 * @return A DICT containing the error message as member "error".
 */
MYX_GRT_VALUE* CGrtToGcBridge::generateError(string message, string details)
{
  MYX_GRT_VALUE* result = myx_grt_dict_new(FRuntime, NULL);
  myx_grt_dict_item_set_value_from_string(result, "error", message.c_str());
  if (details.size() > 0)
    myx_grt_dict_item_set_value_from_string(result, "details", details.c_str());

  return result;
}

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

/**
 * Creates a result object as required by the GRT if there was no error.
 * Otherwise the error is returned instead.
 *
 * @param value The value to wrap in a DICT that is used as module result.
 * @return A DICT containing the given value as member "value".
 */
MYX_GRT_VALUE* CGrtToGcBridge::generateResult(MYX_GRT_VALUE* value)
{
  MYX_GRT_VALUE* result = myx_grt_dict_new(FRuntime, NULL);
  if (FLastError.size() > 0)
  {
    string error = FLastError;
    FLastError = "";
    myx_grt_dict_item_set_value_from_string(result, "error", error.c_str());
  }
  else
  {
    myx_grt_dict_item_set_value(result, "value", value);

    // The set call increases the ref count of value. Revert that as we already have
    // done that on creation of the value.
    myx_grt_value_release(value);
  };

  return result;
}

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

/**
 * Treats the first entry in parameter as a reference to a canvas object and returns it.
 *
 * @param parameter A GRT list that contains at least one entry. This entry must represent a generic canvas object.
 * @return The generic canvas found in the parameter list or NULL if it could not be found.
 */
CGenericCanvas* CGrtToGcBridge::getCanvasFromParameter(MYX_GRT_VALUE* parameter)
{
  CGenericCanvas* result = NULL;

  if ((myx_grt_value_get_type(parameter) == MYX_LIST_VALUE) && (myx_grt_list_item_count(parameter) > 0))
  {
    MYX_GRT_VALUE* item = myx_grt_list_item_get(parameter, 0);
    if (item != NULL)
      result = dynamic_cast<CGenericCanvas*> ((CGCBase*) myx_grt_value_bridge_data_object_get(item));
  };

  return result;
}

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

double CGrtToGcBridge::getFloatFromParameter(MYX_GRT_VALUE* parameter, unsigned int index)
{
  double result = 0;

  if ((myx_grt_value_get_type(parameter) == MYX_LIST_VALUE) && (myx_grt_list_item_count(parameter) > index))
  {
    MYX_GRT_VALUE* item = myx_grt_list_item_get(parameter, index);
    if (item != NULL)
      switch (myx_grt_value_get_type(item))
      {
        case MYX_INT_VALUE:
          result = myx_grt_value_as_int(item);
        case MYX_REAL_VALUE:
          result = myx_grt_value_as_real(item);
      };
  };

  return result;
}

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

MYX_GRT_VALUE* CGrtToGcBridge::getValueFromParameter(MYX_GRT_VALUE* parameter, unsigned int index)
{
  MYX_GRT_VALUE* result = NULL;

  if ((myx_grt_value_get_type(parameter) == MYX_LIST_VALUE) && (myx_grt_list_item_count(parameter) > index))
    result = myx_grt_list_item_get(parameter, index);

  return result;
}

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

int CGrtToGcBridge::getIntFromParameter(MYX_GRT_VALUE* parameter, unsigned int index)
{
  int result = 0;

  if ((myx_grt_value_get_type(parameter) == MYX_LIST_VALUE) && (myx_grt_list_item_count(parameter) > index))
  {
    MYX_GRT_VALUE* item = myx_grt_list_item_get(parameter, index);
    if (item != NULL)
      result = myx_grt_value_as_int(item);
  };

  return result;
}

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

CGCBase* CGrtToGcBridge::getObjectFromParameter(MYX_GRT_VALUE* parameter, unsigned int index)
{
  CGCBase* result = NULL;

  if ((myx_grt_value_get_type(parameter) == MYX_LIST_VALUE) && (myx_grt_list_item_count(parameter) > index))
  {
    MYX_GRT_VALUE* item = myx_grt_list_item_get(parameter, index);
    if ((item != NULL) && (myx_grt_value_get_type(item) == MYX_DICT_VALUE))
      result = (CGCBase*) myx_grt_value_bridge_data_object_get(item);
  };

  return result;
}

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

/**
 * Tries to find a GRT value that corresponds to the given object and returns it.
 * If no value can be found the one is created using the given struct name.
 *
 * @param object The object to lookup.
 * @param structName The name of the DICT struct in case a new DICT must be created.
 * @return A DICT that represents the given object.
 */
MYX_GRT_VALUE* CGrtToGcBridge::getOrCreateDict(CGCBase* object, const char* structName)
{
  MYX_GRT_VALUE* result;

  CGcGrtMapper::iterator iterator = FGcToGrtMapper.find(object);
  if (iterator == FGcToGrtMapper.end())
  {
    result = myx_grt_bridge_dict_new(FRuntime, structName, object);
    addMapping(result, object);
    myx_grt_value_release(result);
  }
  else
    result = iterator->second;

  return result;
}

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

const char* CGrtToGcBridge::getStringFromParameter(MYX_GRT_VALUE* parameter, unsigned int index)
{
  const char* result = NULL;

  if ((myx_grt_value_get_type(parameter) == MYX_LIST_VALUE) && (myx_grt_list_item_count(parameter) > index))
  {
    MYX_GRT_VALUE* item = myx_grt_list_item_get(parameter, index);
    if (item != NULL)
      result = myx_grt_value_as_string(item);
  };

  return result;
}

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

/**
 * Returns the GRT value that has been associated with the given object (if there is one).
 *
 * @param object The object of which the GRT is requested.
 * @return The associated GRT value if there is one.
 */
MYX_GRT_VALUE* CGrtToGcBridge::getGrtValue(CGCBase* object)
{
  MYX_GRT_VALUE* result = NULL;

  CGcGrtMapper::iterator iterator = FGcToGrtMapper.find(object);
  if (iterator != FGcToGrtMapper.end())
    result = iterator->second;

  return result;
}

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

/**
 * Returns the id that the given object has been given.
 *
 * @param object The object whose id is requested.
 * @return The id of the object if there is one, otherwise an empty string.
 */
string& CGrtToGcBridge::getId(CGCBase* object)
{
  CGcIdMapper::iterator iterator = FGcToIdMapper.find(object);
  if (iterator != FGcToIdMapper.end())
    return iterator->second;
  else
    return emptyString;
}

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

/**
 * Removes the id <-> GC mappings by using the object.
 *
 * @param object The object for wich the mapping can be removed.
 */
void CGrtToGcBridge::removeIdMapping(CGCBase* object)
{
  FGcToIdMapper.erase(object);
}

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

/**
 * Creates a new figure out of the given source and frees then the old figure.
 *
 * @param canvas The canvas to which the figures belong.
 * @param oldFigure The figure to replace.
 * @param source The GRT value from which the new figure is to be created.
 * @param layoutClass An optional parameter specifying a new layout to be used instead of the old one.
 */
void CGrtToGcBridge::updateFigure(CGenericCanvas* canvas, CFigure* oldFigure, MYX_GRT_VALUE* source, 
                                  const char* layoutClass)
{
  CFigureTemplate* oldLayout = oldFigure->template_();
  CFigureTemplate* layout = NULL;
  
  if (layoutClass != NULL)
  {
    CGCModel* model = canvas->getModel();
    MYX_GRT_STRUCT* grtType = myx_grt_dict_struct_get(FRuntime, source);
    do
    {
      const char* typeName = myx_grt_struct_get_name(grtType);
      layout = model->layout(typeName, layoutClass);
      if (layout != NULL)
        break;
      
      const char* parentName = myx_grt_struct_get_parent_name(grtType);
      // Break out if we reached the top of the hierarchy.
      if (parentName == NULL)
        break;
      grtType = myx_grt_struct_get(FRuntime, parentName);

    } while (layout == NULL); 
  };
  
  if (layout == NULL)
    layout = oldLayout;

  // If there is still no layout then we can't do anything.
  if (layout != NULL)
  {
    myx_grt_value_listener_remove(FCreatorMapper[oldFigure], this, valueCallback);
    FCreatorMapper.erase(oldFigure);
    CFigure* figure = new CFigure(canvas->getModel(), layout);
    convertDict(source, figure);
    oldFigure->change(figure, GC_CHANGE_FIGURE_EXCHANGE);
    FCreatorMapper[figure] = source;
    myx_grt_value_listener_add(FRuntime, source, this, valueCallback);
    delete oldFigure;
  };
}

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

/**
 * Adds a new mapping from object to value.
 *
 * @param value The value for which a mapping must be created.
 * @param object The object from which the mapping must be created.
 */
void CGrtToGcBridge::addMapping(MYX_GRT_VALUE* value, CGCBase* object)
{
  if (FGcToGrtMapper.find(object) == FGcToGrtMapper.end())
  {
    FGcToGrtMapper[object] = myx_grt_value_retain(value);
    object->addListener(&FListener);
  };
}

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

/**
 * Deletes the generic canvas object that is associated with the given GRT value.
 *
 * @param value The GRT value that is about to be deleted.
 * @return True if deletion went fine, otherwise false.
 */
bool CGrtToGcBridge::deleteObject(MYX_GRT_VALUE* value)
{
  /*
  MYX_GRT_VALUE_TYPE type = myx_grt_value_get_type(value);
  CGCBase* baseClass = (CGCBase*) myx_grt_value_bridge_data_object_get(value);
  bool result = (baseClass != NULL) || (type == MYX_LIST_VALUE);

  if (result && (FUpdateCount == 0))
  {
    switch (type) 
    {
      case MYX_LIST_VALUE:
        {
          /* TODO: deletion of a list value.
          const char* name = myx_grt_value_bridge_dict_key_get(value);
          int index = myx_grt_value_bridge_list_index_get(value);
          TGCVariant child = baseClass->property(name, index);
          baseClass->removeListEntry(name, index);
          if (RemoveMapping(value, baseClass))
            delete baseClass;
          /
          break;
        };
      case MYX_DICT_VALUE:
        {
          if (removeMapping(baseClass))
            delete baseClass;
          break;
        };

      // Simple values do not need to release something in the canvas.
    };
  };

  return result;
  */
  return true;
}

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

/**
 * Triggered when a GC object is about to be destroyed. We have to remove all associated GRT values for it then.
 *
 * @param object The object that is about to be destroyed.
 */
void CGrtToGcBridge::freeNotification(CGCBase* object)
{
  removeMapping(object);
  removeIdMapping(object);
}

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

/**
 * Initializes a GRT value by creating sub entries for it.
 *
 * @param value The GRT value that has just been created.
 * @return True if initialization went fine, otherwise false.
 */
bool CGrtToGcBridge::initObject(MYX_GRT_VALUE* value)
{
  bool result = true;

  if (FUpdateCount == 0)
  {
    CGCBase* baseClass = (CGCBase*) myx_grt_value_bridge_data_object_get(value);

    // When baseClass is NULL then a new GRT value is being initialized. This would require us to create the associated
    // GC object. However due to the way the canvas works GC objects cannot be created this way. There are special 
    // functions to do that. Hence we will return an error at this point if the user has created the GRT value this way.
    result = baseClass != NULL;
    char* owner = NULL;

    if (result)
    {
      MYX_GRT_STRUCT* typeData = myx_grt_dict_struct_get(FRuntime, value);
      int memberCount = myx_grt_struct_get_member_count_total(FRuntime, typeData);

      // Before initializing anything else set the _id member in order to allow recursive initialization
      // with owner references. Check if we already created an id for that object.
      string id = getId(baseClass);
      if (id == emptyString)
      {
        char* guid = myx_grt_get_guid();
        id = guid;
        g_free(guid);
        addIdMapping(id, baseClass);
      }
      else
        int i = 0;

      MYX_GRT_VALUE* temp = myx_grt_value_from_string(id.c_str());
      myx_grt_bridge_dict_item_set_value(value, "_id", temp, FALSE);
      myx_grt_value_release(temp);

      for (int i= 0; i < memberCount; ++i)
      {
        MYX_GRT_STRUCT_MEMBER* member = myx_grt_struct_get_member_by_index_total(FRuntime, typeData, i);
        MYX_GRT_VALUE_TYPE memberType = myx_grt_struct_member_get_type(member);
        const char *memberName = myx_grt_struct_get_member_name(member);
        const char *memberDefault = myx_grt_struct_get_member_default(member);

        switch (memberType)
        {
          case MYX_STRING_VALUE:
            {
              MYX_GRT_VALUE* childValue = NULL;
              
              if (strcmp2(memberName, "_id") == 0)
              {
                // Skip it. The _id member has already been set in advance.
                continue;
              }
              else 
                if (strcmp2(memberName, "owner") == 0)
                {
                  TGCVariant gcValue = baseClass->property(memberName, 0);
                  if (gcValue.isNonNullReference())
                  {
                    string id = getId(gcValue);
                    if (id != emptyString)
                      childValue = myx_grt_value_from_string(id.c_str());
                  };
                }
                else
                {
                  if (memberDefault)
                    childValue = myx_grt_value_from_string(memberDefault);
                  else
                    childValue = myx_grt_value_from_string("");
                };

              myx_grt_bridge_dict_item_set_value(value, memberName, childValue, FALSE);
              if (childValue != NULL)
                myx_grt_value_release(childValue);

              break;
            };
          case MYX_INT_VALUE:
            {
              if (memberDefault && memberDefault[0])
                myx_grt_bridge_dict_item_set_value_from_int(value, memberName, atoi(memberDefault), FALSE);
              else
                myx_grt_bridge_dict_item_set_value_from_int(value, memberName, 0, FALSE);
              break;
            };
          case MYX_REAL_VALUE:
            {
              if (memberDefault && memberDefault[0])
                myx_grt_bridge_dict_item_set_value_from_real(value, memberName, atof(memberDefault), FALSE);
              else
                myx_grt_bridge_dict_item_set_value_from_real(value, memberName, 0.0, FALSE);
              break;
            };
          case MYX_LIST_VALUE:
            {
              MYX_GRT_VALUE_TYPE contentType = myx_grt_struct_member_get_content_type(member);
              const char* contentStruct = myx_grt_struct_member_get_content_struct_name(member);
              MYX_GRT_VALUE* childValue = myx_grt_list_new(contentType, contentStruct);
              myx_grt_bridge_dict_item_set_value(value, memberName, childValue, FALSE);

              // Initialize the list members btw.
              updateObject(childValue);
              if (childValue != NULL)
                myx_grt_value_release(childValue);

              break;
            };
          case MYX_DICT_VALUE:
            {
              MYX_GRT_VALUE_TYPE contentType = myx_grt_struct_member_get_content_type(member);
              const char* contentStruct = myx_grt_struct_member_get_content_struct_name(member);
              TGCVariant gcValue = baseClass->property(memberName, 0);
              MYX_GRT_VALUE* childValue = NULL;
              
              if (contentStruct != NULL)
              {
                if (gcValue.isNonNullReference())
                  childValue = getOrCreateDict(gcValue, contentStruct);
              }
              else
                childValue = NULL; //myx_grt_dict_new_typed(contentType, contentStruct);

              myx_grt_bridge_dict_item_set_value(value, memberName, childValue, FALSE);

              break;
            };
        };
      };
    };
  };

  return result;
}

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

/**
 * Sets the module that holds the reference to this bridge.
 *
 * @param AModule The module to keep a reference of.
 */
void CGrtToGcBridge::module(MYX_GRT_MODULE* module)
{
  FModule = module;
}

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

/**
 * Triggered by our listener if certain things happen with a GRT value.
 */
void CGrtToGcBridge::notification(MYX_GRT_VALUE* value, MYX_GRT_VALUE_CALLBACK_REASON reason)
{
  switch (reason)
  {
    case MYX_GVCR_DELETE:
      {
        deleteFigures(value);
        break;
      };
  };
}

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

/**
 * Called by the listener when an error occurs in the generic canvas.
 *
 * @param object The object that raised the error.
 * @param message The actual message.
 */
void CGrtToGcBridge::onError(CGCBase* object, string message)
{
  string name = object->className();
  FLastError = name + ": " + message;
}

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

/**
 * Removes the mapping between value and object.
 *
 * @param object The GC object from whose mapping list value must be removed.
 * @return True if the mapping list of object is now empty, otherwise false.
 */
bool CGrtToGcBridge::removeMapping(CGCBase* object)
{
  bool result = false;

  CGcGrtMapper::iterator mapperIterator = FGcToGrtMapper.find(object);
  if (mapperIterator != FGcToGrtMapper.end())
  {
    object->removeListener(&FListener);

    MYX_GRT_VALUE* value = mapperIterator->second;
    if (myx_grt_value_get_type(value) == MYX_DICT_VALUE)
      myx_grt_value_bridge_data_object_set(value, NULL);
    else
      myx_grt_value_bridge_data_owner_set(value, NULL);
    myx_grt_value_release(value);

    FGcToGrtMapper.erase(mapperIterator);
    result = true;
  };

  return result;
}

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

/**
 * Updates a GRT list or dict by comparing its child or property list with that of the associated generic canvas object.
 *
 * @param value The GRT value that must be updated.
 * @return True if update went fine, otherwise false.
 */
bool CGrtToGcBridge::updateObject(MYX_GRT_VALUE* value)
{
  bool result = true;

  if (FUpdateCount == 0)
  {
    const char* name = myx_grt_value_bridge_dict_key_get(value);
    MYX_GRT_VALUE_TYPE type = myx_grt_value_get_type(value);
    CGCBase* baseClass;
    if (type == MYX_DICT_VALUE)
      baseClass = (CGCBase*) myx_grt_value_bridge_data_object_get(value);
    else
      baseClass = (CGCBase*) myx_grt_value_bridge_data_owner_get(value);

    result = baseClass != NULL;
    if (result)
    {
      switch (type)
      {
        case MYX_LIST_VALUE:
          {
            // A GRT list must be synchronized. Remember, only one change can happen at a given time.
            // What we do therefore is to walk both lists and find the first (and only) change.
            // There is an exception, though, in the case of initial comparation where the GRT
            // list is created the first time and when the GC list is cleared in one go.
            // More special cases for array members in GC.
            int listType = 0;
            int maxCount = 0;
            switch (getContainerID(name))
            {
              case GC_CONTAINER_SCALING:
                {
                  listType = 1;
                  maxCount = 3;
                  break;
                };
              case GC_CONTAINER_TRANSLATION:
                {
                  listType = 1;
                  maxCount = 3;
                  break;
                };
              case GC_CONTAINER_ROTATION:
                {
                  listType = 1;
                  maxCount = 4;
                  break;
                };
            };

            switch (listType)
            {
              case 0:
                {
                  int count = myx_grt_bridge_list_item_count(value);
                  int i = 0;
                  MYX_GRT_VALUE* childValue = NULL;
                  CGCBase* child = NULL;
                  TGCVariant gcValue;
                  while (true)
                  {
                    childValue = NULL;
                    child = NULL;

                    // Get the next GC child. Break out if there is no more to enumerate.
                    gcValue = baseClass->property(name, i);
                    if (!gcValue.isReference())
                    {
                      // If the returned value is not a reference to an object then something is wrong.
                      result = false;
                      break;
                    };

                    if (!gcValue.isNonNullReference())
                      break;

                    if (i < count)
                    {
                      childValue = myx_grt_bridge_list_item_get(value, i, 0);
                      child = (CGCBase*) myx_grt_value_bridge_data_owner_get(childValue);
                    };

                    // If there is no more GRT entry stop loop here.
                    if (child == NULL)
                      break;

                    if (child == gcValue)
                      ++i;
                    else
                    {
                      // There is a difference, which means either an entry has been added or removed.
                      // By checking the next entry in the GRT we can determine if an entry was removed.
                      // The same can be done with the GC list to determine if a new value was added.
                      if ((i + 1) < count)
                      {
                        childValue = myx_grt_bridge_list_item_get(value, i + 1, 0);
                        child = (CGCBase*) myx_grt_value_bridge_data_owner_get(childValue);
                      }
                      else
                        // Stop if there is no more GRT entry. The current one will be removed then
                        // and a new entry for the current GC value added.
                        break;

                      if (gcValue == child)
                      {
                        // The next GRT value matches the current GC value. This means the current 
                        // GRT value is obsolete and must be removed.
                        myx_grt_bridge_list_item_del(value, i, 0);
                      }
                      else
                      {
                        // The next GRT value also does not match the current GC list entry.
                        // In this case there must be a new GC entry, which also must be inserted into the GRT list.
                        const char* structName = myx_grt_list_content_get_struct_name(value);
                        childValue = getOrCreateDict(gcValue, structName);
                        myx_grt_bridge_list_item_insert(value, i, childValue, FALSE);
                        myx_grt_value_bridge_data_owner_set(childValue, gcValue);
                      };

                      // Well, we found the change. No need to process further.
                      break;
                    };
                  };

                  if (result)
                  {
                    // If there was no error so far then check both lists for remaining entries.
                    // First the GRT list. Delete the remaining entry if there was still one.
                    while (i < count)
                    {
                      myx_grt_bridge_list_item_del(value, i++, FALSE);
                    };

                    // Next is the GC list. If there is still an entry left then add a GRT entry for it.
                    // We handle here the special case of first initialization and add as many GRT
                    // entries as there are remaining GC entries, not just one.
                    const char* structName = myx_grt_list_content_get_struct_name(value);
                    while (gcValue != (CGCBase*) NULL)
                    {
                      childValue = getOrCreateDict(gcValue, structName);

                      // Set the user data again since the insert call will set it to that of the parent.
                      myx_grt_bridge_list_item_insert(value, i++, childValue, FALSE);
                      myx_grt_value_bridge_data_owner_set(childValue, gcValue);

                      gcValue = baseClass->property(name, i);
                      if (!gcValue.isReference())
                      {
                        result = false;
                        break;
                      };
                    };
                  };
                  break;
                };
              case 1:
                {
                  // An float list with a fixed number of members is to be synchronized.
                  int count = myx_grt_bridge_list_item_count(value);
                  while (count < maxCount)
                  {
                    MYX_GRT_VALUE* childValue = myx_grt_value_from_real(0);
                    myx_grt_bridge_list_item_insert(value, -1, childValue, 0);
                    if (childValue != NULL)
                      myx_grt_value_release(childValue);
                    ++count;
                  };

                  while (count > maxCount)
                    myx_grt_bridge_list_item_del(value, --count, 0);

                  for (int i = 0; i < maxCount; ++i)
                  {
                    MYX_GRT_VALUE* childValue = myx_grt_bridge_list_item_get(value, i, 0);
                    TGCVariant gcValue = baseClass->property(name, i);
                    myx_grt_bridge_value_change_real(childValue, gcValue);
                  };
                  break;
                };
            };

            break;
          };
        case MYX_DICT_VALUE:
          {
            // TODO: This would be a good place to validate if references still exist.
            // The dict value (bridge data) itself should still be valid.
            break;
          };
        default:
          result = false;
      };
    }
    else
      result = false;
  };

  return result;
}

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

/**
 * Determines values of simple properties or that of lists/dicts.
 *
 * @param Path The absolute path of the object in the GRT.
 * @return A GRT value containing the property value.
 */
bool CGrtToGcBridge::updateValue(MYX_GRT_VALUE* value)
{
  bool result = true;

  if (FUpdateCount == 0)
  {
    MYX_GRT_VALUE_TYPE type = myx_grt_value_get_type(value);
    switch (type)
      {
        case MYX_DICT_VALUE:
        case MYX_LIST_VALUE:
          break;
        default:
          {
            CGCBase* gcClass = (CGCBase*) myx_grt_value_bridge_data_owner_get(value);
            result = gcClass != NULL;
            if (result)
            {
              const char* key = myx_grt_value_bridge_dict_key_get(value);
              TGCVariant gcValue = gcClass->property(key, myx_grt_value_bridge_list_index_get(value));
              if (gcValue.isValid())
              {
                switch (type)
                {
                  case MYX_INT_VALUE:
                    {
                      myx_grt_bridge_value_change_int(value, gcValue);
                      break;
                    };
                  case MYX_REAL_VALUE:
                    {
                      myx_grt_bridge_value_change_real(value, gcValue);
                      break;
                    };
                  case MYX_STRING_VALUE:
                    {
                      // If the returned value is an object then we have very likely a reference here.
                      // We could do it the long way, though, and check if this property is actually a
                      // reference, but this is slow and we are almost sure here.
                      if (gcValue.isReference()) 
                      {
                        // If there is no reference given then the canvas does not know the actual owner.
                        // In this special case we leave the current owner untouched.
                        if (!gcValue.isNonNullReference())
                          break;

                        string id = getId(gcValue);
                        if (id != value->value.s)
                          myx_grt_bridge_value_change_string(value, id.c_str());
                      }
                      else
                      {
                        string s = gcValue;
                        if (s != value->value.s)
                          myx_grt_bridge_value_change_string(value, s.c_str());
                      };

                      break;
                    };
                  default:
                    result = false;
                };
              };
            };
          };
      };
  };

  return result;
}

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

/**
 * Called by the GRT when a changed GRT value must be reflected in the canvas.
 *
 * @param value The simple GRT value that carries the new value to be set.
 */
bool CGrtToGcBridge::writeValue(MYX_GRT_VALUE *value)
{
  CGCBase* baseClass = (CGCBase*) myx_grt_value_bridge_data_owner_get(value);
  bool result = baseClass != NULL;
  unsigned int index = myx_grt_value_bridge_list_index_get(value);

  // Act only if there isn't already an update under way and the object is not a list value.
  if (result && (FUpdateCount == 0))
  {
    TGCVariant gcValue;
    switch (myx_grt_value_get_type(value))
    {
      case MYX_INT_VALUE:
        {
          gcValue = value->value.i;
          break;
        };
      case MYX_REAL_VALUE:
        {
          gcValue = (float) value->value.r;
          break;
        };
      case MYX_STRING_VALUE:
        {
          gcValue = value->value.s;
          break;
        };
    };

    baseClass->beginUpdate();
    baseClass->property(myx_grt_value_bridge_dict_key_get(value), index, gcValue);
    baseClass->endUpdate();
  };

  return result;
}

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

/**
 * Adds an existing figure instance to a layer.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the layer to act upon.
 *   (1) A GRT dict representing the figure instance to add.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::addFigureInstance(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CLayer* layer = (CLayer*) getObjectFromParameter(value, 0);
  CFigureInstance* instance = (CFigureInstance*) getObjectFromParameter(value, 1);

  if (layer == NULL || instance == NULL)
    return generateError("Invalid parameter list", "addFigureInstance(layer, figure instance)");

  layer->addInstance(instance);

  return generateResult(result);
}

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

/**
 * Adds an exiting layer to the list of layers in the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the layer to add.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::addLayer(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  CLayer* layer = (CLayer*) getObjectFromParameter(value, 1);

  if (canvas == NULL || layer == NULL)
    return generateError("Invalid parameter list", "addLayer(canvas, layer)");

  canvas->addLayer(layer);

  return generateResult(result);
}

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

/**
 * Adds a number of layouts from an external file to the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string representing the file to load (utf-8 encodedd).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::addLayoutsFromFile(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* fileName = getStringFromParameter(value, 1);

  if (canvas == NULL || fileName == NULL)
    return generateError("Invalid parameter list", "addLayoutsFromFile(canvas, file name)");

  canvas->addLayoutsFromFile(fileName);

  return generateResult(result);
}

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

/**
 * Adds a number of styles from an external file.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string representing the file to load (utf-8 encodedd).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::addStylesFromFile(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* fileName = getStringFromParameter(value, 1);

  if (canvas == NULL || fileName == NULL)
    return generateError("Invalid parameter list", "addStylesFromFile(canvas, file name)");

  canvas->addStylesFromFile(fileName);

  return generateResult(result);
}

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

/**
 * Adds a figure instance to the current selection.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the figure instance to add to the selection.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::addToSelection(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  CFigureInstance* instance = (CFigureInstance*) getObjectFromParameter(value, 1);

  if (canvas == NULL || instance == NULL)
    return generateError("Invalid parameter list", "addToSelection(canvas, instance)");
  // TODO: Change this to direct access to a given view.
  //canvas->currentView()->addToSelection(instance);

  return generateResult(result);
}

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

/**
 * Starts the update mode of the canvas (to prevent frequent display refreshs when changing several things).
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::beginUpdate(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "beginUpdate(canvas)");

  canvas->beginUpdate();

  return generateResult(result);
}

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

/**
 * Checks for OpenGL errors and returns the last one if there is one.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::checkError(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "checkError(canvas)");

  canvas->checkError();

  return generateResult(result);
}

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

/**
 * Removes all figures from the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::clearContent(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "clearContent(canvas)");

  canvas->clearContent();

  return generateResult(result);
}

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

/**
 * Removes all layout definitions from the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::clearLayouts(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "clearLayouts(canvas)");

  canvas->clearLayouts();

  return generateResult(result);
}

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

/**
 * Removes all figure instances from the current selection.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::clearSelection(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "clearSelection(canvas)");

  canvas->currentView()->clearSelection();

  return generateResult(result);
}

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

/**
 * Removes all styles from the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::clearStyles(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "clearStyles(canvas)");

  canvas->clearStyles();

  return generateResult(result);
}

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

/**
 * Tests if the given coordinates (window coords) lay within the bounds of the given figure instance.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the figure instance to act upon.
 *   (1) A GRT real giving the x coordinate.
 *   (2) A GRT real giving the y coordinate.
 * @return A GRT module result, either carrying a value or an error. It is a 1 if the point fits in, otherwise 0.
 */
MYX_GRT_VALUE* CGrtToGcBridge::containsPoint(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CFigureInstance* instance = dynamic_cast<CFigureInstance*> (getObjectFromParameter(value, 0));
  double x = getFloatFromParameter(value, 1);
  double y = getFloatFromParameter(value, 2);

  if (instance == NULL)
    return generateError("Invalid parameter list", "containsPoint(figure instance, x, y)");

  bool fits = instance->containsPoint((float) x, (float) y);
  result = myx_grt_value_from_int(fits);

  return generateResult(result);
}

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

/**
 * Creates a new figure from the layout whose name is given as second parameter.
 * The layout template with the given name must exist already.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string containing the type of the layout (utf-8 encodedd).
 *   (2) A GRT string containing the class of the layout (utf-8 encodedd).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::createFigure(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* type = getStringFromParameter(value, 1);
  const char* layoutClass = getStringFromParameter(value, 2);
  if (layoutClass == NULL)
    layoutClass = "full";

  if (canvas == NULL || type == NULL)
    return generateError("Invalid parameter list", "createFigure(canvas, type, layout class)");

  CFigure* figure = canvas->createFigure(type, layoutClass);
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.Figure", (CGCBase*) figure);

  return generateResult(result);
}

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

/**
 * Creates a new figure instance representing the given figure on the given layer.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the layer to use.
 *   (1) A GRT dict representing the figure to create an instance for on the given layer.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::createFigureInstance(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CLayer* layer = (CLayer*) getObjectFromParameter(value, 0);
  CFigure* figure = (CFigure*) getObjectFromParameter(value, 1);

  if (layer == NULL || figure == NULL)
    return generateError("Invalid parameter list", "createFigureInstance(layer, figure)");

  CFigureInstance* instance = layer->createInstance(figure);
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.FigureInstance", (CGCBase*) instance);

  return generateResult(result);
}

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

/**
 * Creates a new layer with the given name and optionally adds it to the current view.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string giving the name of the new layer (utf-8 encoded).
 *   (2) A GRT integer representing a boolean value (1, for adding the new layer to the current view).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::createLayer(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* name = getStringFromParameter(value, 1);
  bool add = getIntFromParameter(value, 2) > 0;

  if (canvas == NULL || name == NULL)
    return generateError("Invalid parameter list", "createLayer(canvas, layer name, flag)");

  CLayer* layer = canvas->createLayer(name, add);
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.Layer", layer);

  return generateResult(result);
}

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

/**
 * Creates a new view using the given name.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string giving the name of the new view (utf-8 encoded).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::createView(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* name = getStringFromParameter(value, 1);

  if (canvas == NULL || name == NULL)
    return generateError("Invalid parameter list", "createView(canvas, name)");

  CGCView* view = canvas->createView(name);
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.View", view);

  return generateResult(result);
}

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

/**
 * Ends an update phase started by beginUpdate.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::endUpdate(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "endUpdate(canvas)");

  canvas->endUpdate();

  return generateResult(result);
}

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

/**
 * Returns the view that is currently used for display (only one view can be used at a time).
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::getCurrentView(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "getCurrentView(canvas)");

  CGCView* view = canvas->currentView();
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.View", view);

  return generateResult(result);
}

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

/**
 * Causes the bridge to drop all figures that belong to the given value.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict for which all figures must be deleted that were created from it.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::grtFigureDelete(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  MYX_GRT_VALUE* source = getValueFromParameter(value, 0);

  if (source == NULL)
    return generateError("Invalid parameter list", "grtFigureDelete(value)");

  deleteFigures(source);

  return generateResult(result);
}

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

/**
 * Causes the bridge to drop and recreate the figures that belong to the given value.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict for which all figures must be updated that were created from it.
 *   (2) A GRT string containing the class of the layout (utf-8 encoded, optional). If given then this value
 *       allows to recreate the figure with a different layout. If not given or not valid then the 
 *       layout of the given figure is used instead.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::grtFigureUpdate(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  MYX_GRT_VALUE* source = getValueFromParameter(value, 1);
  const char* layoutClass = getStringFromParameter(value, 2);

  if (canvas == NULL || source == NULL)
    return generateError("Invalid parameter list", "grtFigureUpdate(canvas, value[, layout class])");

  // Now go through all figures in the creator map and look, which were created from the given value.
  // These must then be updated. Create first a local list of entries as the mapper is modified on the way.
  vector<CFigure*> list;
  for (CGcGrtMapper::iterator iterator = FCreatorMapper.begin(); iterator != FCreatorMapper.end(); ++iterator)
  {
    if (iterator->second == source)
      list.push_back((CFigure*) iterator->first);
  };

  for (vector<CFigure*>::iterator iterator = list.begin(); iterator != list.end(); ++iterator)
    updateFigure(canvas, *iterator, source, layoutClass);

  return generateResult(result);
}

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

/**
 * Returns the GRT value from which the given figure was created.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing a figure.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::grtGetFigureCreator(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGCBase* figure = getObjectFromParameter(value, 0);

  if (figure == NULL)
    return generateError("Invalid parameter list", "grtGetFigureCreator(figure)");

  CGcGrtMapper::iterator iterator = FCreatorMapper.find(figure);
  if (iterator != FCreatorMapper.end())
    result = iterator->second;

  return generateResult(result);
}

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

/**
 * Returns the figure element from a figure given by a path (key).
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the figure to search through.
 *   (1) A GRT string with the path to use as search key.
 *   (2) A GRT integer as index into a list if the element given by the path is a list (optional).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::grtGetFigureElement(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CFigure* figure = (CFigure*) getObjectFromParameter(value, 0);
  const char* key = getStringFromParameter(value, 1);
  int index = getIntFromParameter(value, 2);

  if (figure == NULL || key == NULL)
    return generateError("Invalid parameter list", "grtGetFigureElement(figure, key)");

  CFigureElement* element = figure->elementFromKey(key);
  if (element != NULL)
  {
    // If an index was given then return the child element at that index instead of the element itself.
    if (myx_grt_list_item_count(value) > 2)
    {
      if ((int) element->children()->size() > index)
        element = element->children()->at(index);
      else
        element = NULL;
    };
    if (element != NULL)
      result = myx_grt_bridge_dict_new(FRuntime, "canvas.FigureElement", (CGCBase*) element);
  };

  return generateResult(result);
}

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

/**
 * Converts the given GRT value to a GC figure depending on the figure's template and a given layout class.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the value to convert.
 *   (2) A GRT string containing the class of the layout (utf-8 encoded, optional).
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::grtToFigure(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  MYX_GRT_VALUE* source = getValueFromParameter(value, 1);
  const char* layoutClass = getStringFromParameter(value, 2);
  if (layoutClass == NULL)
    layoutClass = "full";

  if (canvas == NULL || source == NULL)
    return generateError("Invalid parameter list", "grtToFigure(canvas, value, layout class)");

  CGCModel* model = canvas->getModel();
  MYX_GRT_STRUCT* grtType = myx_grt_dict_struct_get(FRuntime, source);
  CFigureTemplate* layout;
  do
  {
    const char* typeName = myx_grt_struct_get_name(grtType);
    layout = model->layout(typeName, layoutClass);
    if (layout != NULL)
      break;
    
    const char* parentName = myx_grt_struct_get_parent_name(grtType);
    // Break out if we reached the top of the hierarchy.
    if (parentName == NULL)
      break;
    grtType = myx_grt_struct_get(FRuntime, parentName);

  } while (layout == NULL); 

  if (layout == NULL)
  {
    // If layout is NULL then we did not find a layout yet for the given type and class.
    // In this case we fall back to the icon class of the top element. This must
    // always be defined.
    const char* typeName = myx_grt_struct_get_name(grtType);
    layout = model->layout(typeName, "icon");
  };

  // If there is still no layout then we can't do anything.
  if (layout != NULL)
  {
    CFigure* figure = new CFigure(model, layout);
    convertDict(source, figure);
    FCreatorMapper[figure] = source;
    myx_grt_value_listener_add(FRuntime, source, this, valueCallback);
    result = myx_grt_bridge_dict_new(FRuntime, "canvas.Figure", (CGCBase*) figure);
  };

  return generateResult(result);
}

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

/**
 * Returns the layer with the given name (if it exists).
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string containing the name of the layer to look for.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::layerByName(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* name = getStringFromParameter(value, 1);

  if (canvas == NULL || name == NULL)
    return generateError("Invalid parameter list", "layerByName(canvas, name)");

  CLayer* layer = canvas->layerByName(name);
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.Layer", (CGCBase*) layer);

  return generateResult(result);
}

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

/**
 * Repaints the given canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::refresh(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);

  if (canvas == NULL)
    return generateError("Invalid parameter list", "refresh(canvas)");

  canvas->refresh();

  return generateResult(result);
}

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

/**
 * Destroys the given GC object and removes it from any list.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the GC object to destroy.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::release(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGCBase* object = getObjectFromParameter(value, 0);

  if (object == NULL)
    return generateError("Invalid parameter list", "release(object)");

  object->release();

  return generateResult(result);
}

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

/**
 * Removes a figure instance from the given layer (without destroying it).
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the layer to act upon.
 *   (1) A GRT dict representing the figure instance to remove.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::removeFigureInstance(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CLayer* layer = (CLayer*) getObjectFromParameter(value, 0);
  CFigureInstance* instance = (CFigureInstance*) getObjectFromParameter(value, 1);

  if (layer == NULL || instance == NULL)
    return generateError("Invalid parameter list", "removeFigureInstance(layer, figure instance)");

  layer->removeInstance(instance);

  return generateResult(result);
}

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

/**
 * Removes a figure instance from the current selection.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the figure instance to remove.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::removeFromSelection(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  CFigureInstance* instance = (CFigureInstance*) getObjectFromParameter(value, 1);

  if (canvas == NULL || instance == NULL)
    return generateError("Invalid parameter list", "removeFromSelection(canvas, figure instance)");

  // TODO: Change this to direct access to a given view.
  //canvas->removeFromSelection(instance);

  return generateResult(result);
}

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

/**
 * Removes a layer from the list of layers in the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the layer to remove.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::removeLayer(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  CLayer* layer = dynamic_cast<CLayer*>(getObjectFromParameter(value, 1));
  if (canvas == NULL || layer == NULL)
    return generateError("Invalid parameter list", "removeLayer(canvas, layer)");

  canvas->removeLayer(layer);

  return generateResult(result);
}

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

/**
 * Removes a view from the list of views in the canvas.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the view to remove.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::removeView(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  CGCView* view = dynamic_cast<CGCView*>(getObjectFromParameter(value, 1));

  if (canvas == NULL || view == NULL)
    return generateError("Invalid parameter list", "removeView(canvas, view)");

  canvas->removeView(view);

  return generateResult(result);
}

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

/**
 * Sets a new view as the current view.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT dict representing the view to activate.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::setCurrentView(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  CGCView* view = dynamic_cast<CGCView*>(getObjectFromParameter(value, 1));

  if (canvas == NULL || view == NULL)
    return generateError("Invalid parameter list", "setCurrentView(canvas, view)");

  canvas->currentView(view);

  return generateResult(result);
}

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

/**
 * Switches the visibility of the selection.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT int acting as a boolean value, with 1 = show selection, 0 = hide selection
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::showSelection(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  bool show = getIntFromParameter(value, 1) > 0;

  if (canvas == NULL)
    return generateError("Invalid parameter list", "showSelection(canvas, flag)");

  canvas->currentView()->showSelection(show);

  return generateResult(result);
}

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

/**
 * Returns a view given by its name.
 *
 * @param value A GRT LIST containing the following entries necessary for the function:
 *   (0) A GRT dict representing the canvas to act upon.
 *   (1) A GRT string containing the name of the view.
 * @return A GRT module result, either carrying a value or an error.
 */
MYX_GRT_VALUE* CGrtToGcBridge::viewByName(MYX_GRT_VALUE *value)
{
  MYX_GRT_VALUE* result = NULL;

  CGenericCanvas* canvas = getCanvasFromParameter(value);
  const char* name = getStringFromParameter(value, 1);

  if (canvas == NULL || name == NULL)
    return generateError("Invalid parameter list", "viewByName");

  CGCView* view = canvas->viewByName(name);
  result = myx_grt_bridge_dict_new(FRuntime, "canvas.View", view);

  return generateResult(result);
}

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

