/* 
 * © 2007-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef _MODEL_DIAGRAM_IMPL__H_
#define _MODEL_DIAGRAM_IMPL__H_

#include <mdc.h>
#include <grtpp.h>

#include "grts/structs.model.h"
#include "grts/structs.meta.h"

#include "wbpublic_public_interface.h"

#include "base_bridge.h"
#include "figure_common.h"

class WBPUBLICBACKEND_PUBLIC_FUNC model_Diagram::ImplData : public BridgeBase, public wbfig::FigureEventHub
{
  typedef BridgeBase super;

protected:
  model_Diagram *_self;

  mdc::CanvasView *_canvas_view;
  sigc::connection _selection_signal_conn;

  sigc::signal<void, model_DiagramRef> _selection_changed_signal;

  sigc::signal<void, model_ObjectRef> _realize_object_signal;
  
  sigc::signal<void, model_ObjectRef, mdc::CanvasItem*, bool, mdc::Point> _item_crossed_signal;
  sigc::signal<void, model_ObjectRef, mdc::CanvasItem*, mdc::Point, mdc::MouseButton, mdc::EventState> _item_click_signal;
  sigc::signal<void, model_ObjectRef, mdc::CanvasItem*, bool, mdc::Point, mdc::MouseButton, mdc::EventState> _item_mouse_button_signal;
  
  int _updating_selection;
  bool _connected_update;
  
  virtual ~ImplData();
  
  void member_changed(const std::string &name, const grt::ValueRef &ovalue);
  virtual void member_list_changed(grt::internal::OwnedList *list, bool added, const grt::ValueRef &value);

  void canvas_selection_changed(bool added, mdc::CanvasItem *item);

  void realize_contents();
  void realize_selection();
  
  void update_options(const std::string &key);

  virtual bool is_realizable();

  virtual GrtObject* get_object() { return _self; }

  model_LayerRef get_layer_under_figure(const model_FigureRef &figure);
  
  virtual bool figure_click(const model_ObjectRef &owner, mdc::CanvasItem *target, const mdc::Point &point, mdc::MouseButton button, mdc::EventState state);
  virtual bool figure_button_press(const model_ObjectRef &owner, mdc::CanvasItem *target, const mdc::Point &point, mdc::MouseButton button, mdc::EventState state);
  virtual bool figure_button_release(const model_ObjectRef &owner, mdc::CanvasItem *target, const mdc::Point &point, mdc::MouseButton button, mdc::EventState state);
  virtual bool figure_enter(const model_ObjectRef &owner, mdc::CanvasItem *target, const mdc::Point &point);
  virtual bool figure_leave(const model_ObjectRef &owner, mdc::CanvasItem *target, const mdc::Point &point);
  
public:
  ImplData(model_Diagram *self);

  void set_page_counts(int x, int y);
  
  void add_figure(const model_FigureRef &figure);
  virtual void add_connection(const model_ConnectionRef &conn);
  
  void remove_figure(const model_FigureRef &figure);
  virtual void remove_connection(const model_ConnectionRef &conn);
  
  void delete_layer(const model_LayerRef &layer);

  bool update_layer_of_figure(const model_FigureRef &figure);
  
  void select_object(const model_ObjectRef &object);
  void unselect_object(const model_ObjectRef &object);
  void unselect_all();

  virtual bool realize();
  virtual void unrealize();

public:  
  mdc::CanvasView *get_canvas_view() const { return _canvas_view; }

  static mdc::Size get_size_for_page(const app_PageSettingsRef &page);

  void stack_layer(const model_LayerRef &layer, mdc::CanvasItem *item);
  void stack_connection(const model_ConnectionRef &conn, mdc::CanvasItem *item);
  void stack_figure(const model_FigureRef &figure, mdc::CanvasItem *item);

  sigc::signal<void, model_DiagramRef> signal_selection_changed() { return _selection_changed_signal; }
  
  sigc::signal<void, model_ObjectRef, mdc::CanvasItem*, bool, mdc::Point> signal_item_crossed() { return _item_crossed_signal; }
  sigc::signal<void, model_ObjectRef, mdc::CanvasItem*, mdc::Point, mdc::MouseButton, mdc::EventState> signal_item_click() { return _item_click_signal; }
  sigc::signal<void, model_ObjectRef, mdc::CanvasItem*, bool, mdc::Point, mdc::MouseButton, mdc::EventState> signal_item_mouse_button() { return _item_mouse_button_signal; }
  
  sigc::signal<void, model_ObjectRef> signal_object_realized() { return _realize_object_signal; }
  void notify_object_realize(const model_ObjectRef &object);

  void update_size();
  void update_from_page_size();

  void add_tag_badge_to_figure(const model_FigureRef &figure, const meta_TagRef &tag);
  void remove_tag_badge_from_figure(const model_FigureRef &figure, const meta_TagRef &tag);

private:
  model_Diagram *self() const { return _self; }
};

#endif // _MODEL_DIAGRAM_IMPL__H_
